char16_t 的 C++ wprintf 格式说明符,用于打印 unicode 字符串

C++ wprintf format specifier for char16_t for printing unicode string

我成功编译了以下代码:

#include <io.h>
#include <fcntl.h>
#include <iostream>
#include <cstddef>
#include <cstdio>
int main()
{
    _setmode(_fileno(stdout), _O_U16TEXT);
    
    char16_t chinese[] = u"\u4e66\u4e2d\u81ea\u6709\u9ec4\u91d1\u5c4b";
    wprintf(L"String written with unicode codes: %ls \n", chinese);
    
    wchar_t arabic[] = L"أَبْجَدِيَّة عَرَبِيَّة";
    wprintf(L"String written with L-String: %ls \n", arabic);
    std::wcout << std::endl;  std::system("PAUSE");
}

它打印:

但是,编译器对中文大小写发出警告(不是阿拉伯语大小写):

warning C4477: 'wprintf' : format string '%ls' requires an argument of type 'wchar_t *', but variadic argument 1 has type 'char16_t *'

那么正确的 wprintf 格式字符串是什么?

wchar_tchar16_t 不同。 wchar_t 在 windows 上是 2 字节字符,但(通常)在 linux 上是 4 字节字符。这就像 intint16_t 的问题。标准没有定义wchar_t.

所以问题不是 wprintf 使用什么格式说明符。而是如何将 char16_t 字符串转换为 wchar_t 字符串。

在 Windows 下,您可能只需将 char16_t 转换为 wchar_t,这就是 wprintf 隐式发生的情况,因为它实际上并没有验证它的参数。警告 C4477 只是 (Visual Studio?) 编译器提示您的问题的一点帮助。

但在其他平台上,您必须实际转换字符串。

所以最好的解决方案是这样的: wprintf("%ls", boost::utf16_to_wchar_t(chinese));(我只是在这里抛出 boost,因为它们有转换功能。我不知道要使用的确切功能)。

或者使用 wchar_t 转义序列并将 chinese 定义为 wchar_t* 字符串。

What would be then the correct wprintf format string?

char16_t 没有 printf 格式说明符。它不存在。

您必须将 char16_t 字符串转换为多字节字符串或宽字符串,然后打印它。

c16rtomb 将是执行此操作的标准 C 函数。 Convert between string, u16string & u32string 显示如何在 C++ 中执行此操作。