如何将 uint16_t 转换为宽字符串 (std::wstring)
How to convert uint16_t to a wide string (std::wstring)
我的问题与这个较旧的问题有关
Format specifiers for uint8_t, uint16_t, ...?
只是回顾一下原始问题是关于如何使用 scanf 的 uint8_t、uint16_t、uint32_t 和 uint64_t 的说明符?
问题的答案如下:
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 完全改变了答案,我也使用 C++11,我确实可以访问 boost 库,尽管我不想使用它们。
纯属猜测,因为我目前没有时间尝试。
能否使用预处理器将宽字符串 L 标记粘贴到展开的 SCNd16 的前面?
这是一个VS2013 compiler bug。由于它已被关闭为 "fixed",也许它会在 VS2015 中工作(没有安装预览来试一试)。
你的代码行
swscanf (line.c_str(), L"Value of integer: %" SCNd16 L"\n", &my_integer);
格式正确,因为即使 SCNd16
扩展为缺少 L
前缀的字符串文字,标准规定如果在两个相邻的字符串文字中,一个缺少编码前缀,它被视为具有与另一个相同的编码前缀。
§2.14.5/14 [lex.string]
In translation phase 6 (2.2), adjacent string literals are concatenated. If both string literals have the same encoding-prefix, the resulting concatenated string literal has that encoding-prefix. If one string literal has no encoding-prefix, it is treated as a string literal of the same encoding-prefix as the other operand. ...
通常,您可以使用预处理器通过标记连接来加宽字符串。例如,定义一组这样的宏
#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"
或使用您展示的 运行 时间转换解决方案。
我的问题与这个较旧的问题有关 Format specifiers for uint8_t, uint16_t, ...?
只是回顾一下原始问题是关于如何使用 scanf 的 uint8_t、uint16_t、uint32_t 和 uint64_t 的说明符?
问题的答案如下:
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 完全改变了答案,我也使用 C++11,我确实可以访问 boost 库,尽管我不想使用它们。
纯属猜测,因为我目前没有时间尝试。
能否使用预处理器将宽字符串 L 标记粘贴到展开的 SCNd16 的前面?
这是一个VS2013 compiler bug。由于它已被关闭为 "fixed",也许它会在 VS2015 中工作(没有安装预览来试一试)。
你的代码行
swscanf (line.c_str(), L"Value of integer: %" SCNd16 L"\n", &my_integer);
格式正确,因为即使 SCNd16
扩展为缺少 L
前缀的字符串文字,标准规定如果在两个相邻的字符串文字中,一个缺少编码前缀,它被视为具有与另一个相同的编码前缀。
§2.14.5/14 [lex.string]
In translation phase 6 (2.2), adjacent string literals are concatenated. If both string literals have the same encoding-prefix, the resulting concatenated string literal has that encoding-prefix. If one string literal has no encoding-prefix, it is treated as a string literal of the same encoding-prefix as the other operand.
...
通常,您可以使用预处理器通过标记连接来加宽字符串。例如,定义一组这样的宏
#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"
或使用您展示的 运行 时间转换解决方案。