【问题标题】:C++ How to convert an unsigned integer to a hex string without a thousands separatorC ++如何将无符号整数转换为没有千位分隔符的十六进制字符串
【发布时间】:2023-01-26 19:07:42
【问题描述】:

为了存储按钮文本的颜色,我将变量uint32_t textColor 设置为值 0xF5CE52 (0d16109138)。现在我需要将此 textColor 值作为十六进制值插入到字符串中。但是,当我尝试通过字符串流将 textColor 转换为十六进制字符串时,似乎在十六进制字符串中插入了千位分隔符,我无法弄清楚如何防止这种情况发生......

要将 textColor 转换为十六进制字符串,我使用了以下代码:

uint32_t textColor = 0xF5CE52;
stringstream btnColorHex;
btnColorHex << uppercase << setfill('0') << setw(6) << hex << textColor;

我使用以下方法打印它:

cout << "btnColorHex.str() - " << btnColorHex.str() << endl;

结果如下:

btnColorHex.str() - F5C.E52

注意:我已将我的系统区域设置为荷兰语格式的数字格式,它使用 .作为千位分隔符和 , 作为小数点分隔符。

我希望将以下内容打印到控制台:

btnColorHex.str() - F5CE52

我通过删除 .之后从字符串中提取,但是当我在 PC 上测试这段代码时,当我使用 , 作为千位分隔符将语言环境设置为美国格式时,这当然不起作用。

我也尝试过将 uint32_t 转换为 unsgined int,但这导致了同样的问题。

我可以尝试使用纯 C 中的 sprintf() 之类的函数来规避此问题,但如果有合适的 C++ 方法可以先执行此操作,我现在就想这样做。

所以我的问题是:C++ 中是否有一种方法可以将无符号整数格式化为十六进制字符串,而无需插入千位分隔符?

【问题讨论】:

  • 您是否尝试过在您的应用中禁用区域设置?试试btnColorHex.imbue(std::locale("C"));
  • 由于 C++11 std::sprintf 是 C++ 标准的一部分。 Link cppreference。也就是说,我会改用snprintf。

标签: c++ string formatting integer hex


【解决方案1】:

要禁用区域设置格式,请使用 imbue(std::locale("C"))

您的代码现在将如下所示:

uint32_t textColor = 0xF5CE52;
stringstream btnColorHex;
btnColorHex.imbue(std::locale("C"));
btnColorHex << uppercase << setfill('0') << setw(6) << hex << textColor;

现在无论 PC 的语言环境如何,输出都将始终正确格式化:

btnColorHex.str() - F5CE52

【讨论】:

    【解决方案2】:

    您可以将其手写为

    #include <cstdint>
    #include <cstdlib>
    #include <iostream>
    
    std::string hex( uint32_t value ) {
        char str[16];
        char* p = &str[16];
        do {
            p--;
            uint32_t digit = value % 16; 
            value /= 16;
            *p = digit>=10 ? 'a' + (digit-10) : '0' + digit;
        } while ( value > 0 );
        p--;
        *p = 'x';
        p--;
        *p = '0';
        return std::string(p,&str[16]-p);
    }
    

    运行为

    int main()
    {
        for ( int j=0; j<10; ++j ) {
            uint32_t value = std::rand();
            std::cout << std::hex << value << " " << hex( value ) << std::endl;
        }
    }
    

    产品

    6b8b4567 0x6b8b4567
    327b23c6 0x327b23c6
    643c9869 0x643c9869
    66334873 0x66334873
    74b0dc51 0x74b0dc51
    19495cff 0x19495cff
    2ae8944a 0x2ae8944a
    625558ec 0x625558ec
    238e1f29 0x238e1f29
    46e87ccd 0x46e87ccd
    

    神马:https://godbolt.org/z/xxEnqs7es

    另一种选择是使用 C++20 的 std::format。然而目前只有 gcc/clang on trunk (unreleased) 实现了这个特性。

    #include <format>
    
    std::string hex( uint32_t value ) {
        return std::format("0x{:x}", value);
    }
    

    神马:https://godbolt.org/z/roMc5ajcj

    【讨论】:

      猜你喜欢
      • 2015-02-18
      • 2021-11-05
      • 2011-04-11
      • 2011-08-21
      • 1970-01-01
      • 2019-05-03
      • 2019-10-31
      相关资源
      最近更新 更多