如何将uint16_t转换为宽字符串(std :: wstring)

时间:2015-01-12 20:04:18

标签: c++ string c++11

我的问题与这个较老的问题有关 Format specifiers for uint8_t, uint16_t, ...?

回顾原始问题是关于如何使用uint8_t,uint16_t,uint32_t和uint64_t与scanf的说明符?

问题的答案如下:

sscanf (line, "Value of integer: %" SCNd32 "\n", &my_integer);

但有没有人知道如何做到这一点,但会产生一个宽字符串?

std::wstring line;
swscanf (line.c_str(), L"Value of integer: %" SCNd16 L"\n", &my_integer);

sbove行给了我一个连接错误。我相信因为SCNd16不是用于广泛的?

目前我的解决方案是在原始答案中创建std :: string,然后将其转换为宽字符串

sscanf_s(line.c_str(), "%" SCNd16 "\n", &sixteenBitInteger)
// code here to check for EOF and EINVAL
//then I convert it 
typedef std::codecvt_utf8<wchar_t> ConverterType; 
std::wstring_convert<ConverterType, wchar_t> converter;
std::wstring convertedString = converter.from_bytes(line);

但它相当难看,我相信必须有一个更加精致的方式来进行这种转换? 如果它有助于理解我的使用,我使用uint16_t类型来存储Web服务器的端口号,但我希望能够将它转换为宽字符串,因为这是预期的显示类型。我也在使用C ++ 11,如果它改变了答案,我可以访问boost库,但我宁愿不使用它们。

2 个答案:

答案 0 :(得分:4)

这是VS2013 compiler bug。由于它已被关闭为“固定”,它可能在VS2015中工作(没有安装预览试试)。

您拥有的代码行

swscanf (line.c_str(), L"Value of integer: %" SCNd16 L"\n", &my_integer);

格式正确,因为即使SCNd16扩展为缺少L前缀的字符串文字,标准也会说如果两个相邻的字符串文字中缺少一个编码前缀,则它是视为具有与另一个相同的编码前缀。

§2.14.5/ 14 [lex.string]

  

在翻译阶段6(2.2)中,连接相邻的字符串文字。如果两个字符串文字具有相同的 encoding-prefix ,则生成的连接字符串文字具有 encoding-prefix 。如果一个字符串文字没有 encoding-prefix ,则将其视为与另一个操作数相同的 encoding-prefix 的字符串文字。 ...


通常,您可以使用预处理器通过使用标记连接来扩展字符串。例如,定义一组像这样的宏

#define WIDEN_(x) L##x
#define WIDEN(x) WIDEN_(x)

并将有问题的代码行转换为

swscanf (line.c_str(), L"Value of integer: %" WIDEN(SCNd16) L"\n", &my_integer);

会解决问题,但由于实现细节,它不会在VS2013上解决。 SCNd16宏实际上扩展为两个单独的字符串文字 - "h" "d"。所以上面的宏扩展了第一个文字,但不是第二个,你遇到了同样的(假的)错误。

您的选择是对字符串"hd"进行硬编码,或者使用您显示的运行时转换解决方案。

答案 1 :(得分:0)

一个纯粹的猜测,因为我现在没有时间尝试它。

您是否可以使用preprocesser将宽字符串L标记粘贴到展开的SCNd16的前面?