我正在尝试调用printf()以使用 输出 Unicode 字符/字符串%s,但它不打印任何内容。
如果我这样调用printf():
printf("\xE2\x98\xA0")
Run Code Online (Sandbox Code Playgroud)
我得到一个?.
但是,如果我这样使用%ls:
printf("%ls", "?") /* or */
printf("%ls", L"?") /* or */
printf("%ls", L"\xE2\x98\xA0")
Run Code Online (Sandbox Code Playgroud)
我什么也没打印;
另外,如何声明一个wchar_t包含 Unicode 字符的字符串? wchar_t wstro[50] = L"?"不起作用。
我需要malloc()一个wchar_t在它然后把Unicode数据?
您将 Unicode 与 UTF-8 以及两者都与wchar_t.
Unicode 是一种抽象的东西,带有代码点,结合了字符和其他属性。
UTF-8 是一种常见的 Unicode 编码方式,它与 ASCII 兼容(仅在 ASCII 字符串的情况下),并与 C 字符串兼容(因此以零结尾(字符串中没有其他 0 字节)。\xE2\x98\xA0是 UTF- 8 代表。
该字符?可能也采用 UTF-8 编码。这取决于您的编辑器,但通常编辑器不使用 wchar_t。
所以:对于 UTF-8,你应该只使用%s而不是%ls. 所以你的3次尝试是错误的。
我一般来说,使用 UTF-8 等char*和普通字符串函数(只是不要在随机字节处断开字符串,但这也意味着如果后面是一些组合代码点,也不要在随机 UTF-8 代码点之后断开字符串。
您可以使用 wchar_t,但通常使用使用 wchar_t 的协议,但特别是在这种情况下,您应该格外小心,因为 wchar_t 的大小可能与所需的字符大小(预期编码)不兼容 [例如您的系统等wchar_t 可能只有 2 个字节,但因此您可以使用 UCS2,但不能使用 UTF-32,或者相反,如果系统将 wchar_t 定义为 4 个字节)。
因此,保持简单并尝试仅使用 UTF-8,并将其用作普通的 C 字符串。
此答案假设您在 MS Windows 中工作
很遗憾,我们在 2018 年,但这些东西仍然无法正常工作。但这里是事情的状态:
printf("\xE2\x98\xA0");(与printf("%s", "\xE2\x98\xA0");) 有效,因为您只是将 3 个字符输出到输出流。C 语言中没有发生 Unicode 或特殊字符处理。您的终端环境会在输出中查找 UTF-8 字符串并相应地选择显示字形。
同样,如果您将输出写入文件(使用fprintf或流重定向),您将看到该文件包含0xE2, 0x98, 0xA0,然后您可以选择使用将 UTF-8 转换为显示字形的文本文件查看器。
这部分一切正常,您可以(并且可能应该)编写您的程序,只将 UTF-8 编码的字符写入FILE流。
当我们想要输出wchar_t字符时,问题就开始了。理论上这应该有效:
printf("%ls", L"\u2620");
Run Code Online (Sandbox Code Playgroud)
应该发生的wcstombs是调用将 unicode 代码点序列转换为多字节序列。但是要使用哪种多字节格式呢?UTF-8 现在已经无处不在,但过去还有其他格式,如 ShiftJIS、Big-5 等。
您必须使用 指定多字节格式setlocale。语言环境的细节是实现定义的。
这是踢球者。对于一般 UTF-8 输出,Windows 不支持 C 语言环境。如果你尝试setlocale(LC_CTYPE, ".65001");它只是不起作用。
您可以使用支持的语言环境输出 Unicode 的某些子集。例如在MSDN例如使用Japanese_Japan.932作品,输出所述Unicode输入作为移位-JIS。(不是 UTF-8)。
更糟糕的是,如果您使用 Windows API 函数WideStringToMultiByte,它确实接受CP_UTF8. 您可以使用此函数转换L"\u2620";为char缓冲区,printf然后生成 UTF-8 输出。
但是当然你不能将它“插入”到FILE流处理中,它只调用wcstombs而不是WideStringToMultiByte.
为什么他们不允许".UTF-8"作为 的语言环境wcstombs?恶意行为?谁知道。
理论上应该起作用的下一件事情是:
FILE *fp = fopen("a.txt", "w");
fwide(fp, 1);
fwprintf(fp, L"\u2620");
Run Code Online (Sandbox Code Playgroud)
然而实际上,MS 运行时实际上并没有对fwide;做任何事情。它不支持面向宽的流。Microsoft 的wprintf系列实现实际上只输出窄字符,而不是宽字符,并且它们使用的wcstombs方法与窄 printf 系列相同。
因此,该代码不起作用,并且来自日语 wcstombs 示例的代码fwprintf(fp, L"\u3603");(使用 .932 CP 集)输出多字节序列而不是原始宽字符。
要通过stdio.hAPI编写 UTF-16 文件,您实际上别无选择,只能使用窄字符并将其视为二进制文件。
| 归档时间: |
|
| 查看次数: |
19934 次 |
| 最近记录: |