【问题标题】:C++ cout hex values?C++ cout 十六进制值?
【发布时间】:2010-10-03 12:33:30
【问题描述】:

我想做:

int a = 255; 
cout << a;

让它在输出中显示 FF,我该怎么做?

【问题讨论】:

    标签: c++ hex cout


    【解决方案1】:

    用途:

    #include <iostream>
    
    ...
    
    std::cout << std::hex << a;
    

    many other options to control the exact formatting of the output number,比如前导零和大小写。

    【讨论】:

    • 这似乎将所有未来的输出从 cout 更改为 hex;因此,如果您只想以十六进制打印“a”,则可能需要cout &lt;&lt; hex &lt;&lt; a &lt;&lt; dec; 之类的内容将其改回。
    • @ShreevatsaR 通过十六进制恢复 dec 的一个问题是 dec 可能不是之前设置的值,尤其是在您编写通用库方法时。 This question 有一些关于如何存储和恢复状态的答案。您可以使用ios::fmtflags f(cout.flags()); 保存状态并使用out.flags(f); 恢复它。
    • 然后通过std::cout.flags(f);恢复
    【解决方案2】:

    std::hex 定义在&lt;ios&gt; 中,它包含在&lt;iostream&gt; 中。但是要使用 std::setprecision/std::setw/std::setfill/etc 之类的东西,您必须包含 &lt;iomanip&gt;

    【讨论】:

      【解决方案3】:

      要操纵流以十六进制打印,请使用 hex 操纵器:

      cout << hex << a;
      

      默认情况下,十六进制字符以小写形式输出。要将其更改为大写,请使用 uppercase 操纵器:

      cout << hex << uppercase << a;
      

      若要稍后将输出改回小写,请使用nouppercase 操纵器:

      cout << nouppercase << b;
      

      【讨论】:

      • nouppercase 会把输出改回十进制吗?
      • 只是为了添加杂项,上面的sn-p不会使输入“apple”变成“APPLE”。
      【解决方案4】:

      如果你想打印一个十六进制数字,然后恢复为十进制,你可以使用这个:

      std::cout << std::hex << num << std::dec << std::endl;
      

      【讨论】:

        【解决方案5】:

        std::hex 为您提供十六进制格式,但它是一个有状态选项,这意味着您需要保存和恢复状态,否则它将影响所有未来的输出。

        天真地切换回 std::dec 只有在以前的标志位置才有用,但情况可能并非如此,尤其是在您编写库时。

        #include <iostream>
        #include <ios>
        
        ...
        
        std::ios_base::fmtflags f( cout.flags() );  // save flags state
        std::cout << std::hex << a;
        cout.flags( f );  // restore flags state
        

        这结合了 Greg Hewgill 的答案和来自 another question 的信息。

        【讨论】:

          【解决方案6】:

          我知道这不是 OP 所要求的,但我仍然认为值得指出如何使用 printf 来做到这一点。我几乎总是更喜欢使用它而不是 std::cout(即使没有以前的 C 背景)。

          printf("%.2X", a);
          

          '2' 定义精度,'X' 或 'x' 定义大小写。

          【讨论】:

          • printf 与 cout 的战斗由来已久。当然,cout 具有从 ostream 派生的良好属性,并获得所有抽象优势。 C 没有流对象的概念,因此 printf 和 fprintf 是两个不同的命令。真的,如果 stdout 是 FILE* 在 C 语言中会很好。会让事情变得更容易。
          • @rlbond 标准输出是 C 中的 FILE *。
          • 这就是为什么printf("hello\n") 等同于fprintf(stdout, "hello\n")。更有用的是,您可以将stdout(或stdin,或stderr)传递给采用FILE* 参数的函数。
          【解决方案7】:

          您也可以使用不同种类的标志和掩码。更多信息请参考http://www.cplusplus.com/reference/iostream/ios_base/setf/

          #include <iostream>
          using namespace std;
          
          int main()
          {
              int num = 255;
              cout.setf(ios::hex, ios::basefield);
              cout << "Hex: " << num << endl;
          
              cout.unsetf(ios::hex);
              cout << "Original format: " << num << endl;
          
              return 0;
          }
          

          【讨论】:

          • 我认为这段代码的行为是未定义的。 setf 清除 ios::basefield 位,包括 ios::dec(标准流的默认值),并且只设置 ios::hex。当 ios::hex 未设置时,ios::basefield 中的每一位都未设置。它是如何 num 第二次打印的?这些位都未设置的证据:ideone.com/fYXyh6。根据 Thinking in C++ vol 2 page 189,这对于 ios::floatfield 是允许的,但对于 ios::basefield 并没有说同样的话。
          【解决方案8】:

          使用std::uppercasestd::hex 格式化整数变量a 以十六进制格式显示。

          #include <iostream>
          int main() {
             int a = 255;
          
             // Formatting Integer
             std::cout << std::uppercase << std::hex << a << std::endl; // Output: FF
             std::cout << std::showbase  << std::hex << a << std::endl; // Output: 0XFF
             std::cout << std::nouppercase << std::showbase  << std::hex << a << std::endl; // Output: 0xff
          
             return 0;
          }
          

          【讨论】:

            【解决方案9】:

            C++20 std::format

            这是我认为现在最干净的方法,因为它不会污染std::cout 状态和std::hex

            main.cpp

            #include <format>
            #include <string>
            
            int main() {
                std::cout << std::format("{:x} {:#x} {}\n", 16, 17, 18);
            }
            

            预期输出:

            10 0x11 18
            

            尚未在 GCC 10.0.1、Ubuntu 20.04 上实现。

            但是成为 C++20 的很棒的库,一旦安装后应该是一样的:

            git clone https://github.com/fmtlib/fmt
            cd fmt
            git checkout 061e364b25b5e5ca7cf50dd25282892922375ddc
            mkdir build
            cmake ..
            sudo make install
            

            main2.cpp

            #include <fmt/core.h>
            #include <iostream>
            
            int main() {
                std::cout << fmt::format("{:x} {:#x} {}\n", 16, 17, 18);
            }
            

            编译运行:

            g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main2.out main2.cpp -lfmt
            ./main2.out
            

            记录于:

            更多信息请访问:std::string formatting like sprintf

            C++20 之前的版本:干净地打印并将 std::cout 恢复到以前的状态

            main.cpp

            #include <iostream>
            #include <string>
            
            int main() {
                std::ios oldState(nullptr);
                oldState.copyfmt(std::cout);
                std::cout << std::hex;
                std::cout << 16 << std::endl;
                std::cout.copyfmt(oldState);
                std::cout << 17 << std::endl;
            }
            

            编译运行:

            g++ -ggdb3 -O0 -std=c++11 -Wall -Wextra -pedantic -o main.out main.cpp
            ./main.out
            

            输出:

            10
            17
            

            更多详情:Restore the state of std::cout after manipulating it

            在 GCC 10.0.1、Ubuntu 20.04 上测试。

            【讨论】:

            【解决方案10】:

            你好吗!

            #include <iostream>
            #include <iomanip>
            
            unsigned char arr[] = {4, 85, 250, 206};
            for (const auto & elem : arr) {
                std::cout << std::setfill('0') 
                          << std::setw(2) 
                          << std::uppercase 
                          << std::hex 
                          << (0xFF & elem) 
                          << " ";
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2013-03-31
              • 2014-11-30
              • 2018-07-26
              • 2011-08-04
              • 2011-06-01
              相关资源
              最近更新 更多