为什么wprintf在linux上将unicode中的俄语文本音译成拉丁语?

vxbzzdmp  于 2021-06-03  发布在  Sqoop
关注(0)|答案(2)|浏览(402)

为什么下面的程序


# include <stdio.h>

# include <wchar.h>

int main() {
  wprintf(L"Привет, мир!");
}

打印“女贞,和平号!”在linux上?具体来说,为什么它要将unicode中的俄语文本音译为拉丁语,而不是将其转换为utf-8或使用替换字符?
在锁销上演示小车行为:https://godbolt.org/z/36zecg
非宽版 printf("Привет, мир!") 按预期打印此文本(“привет, мир!").

6ojccjat

6ojccjat1#

因为宽字符的转换是根据当前设置的区域设置完成的。默认情况下,c程序总是以仅支持ascii字符的“c”语言环境开始。
您必须先切换到任何俄语或utf-8语言环境:

setlocale(LC_ALL, "ru_RU.utf8"); // Russian Unicode
setlocale(LC_ALL, "en_US.utf8"); // English US Unicode

或当前系统区域设置(这可能是您需要的):

setlocale(LC_ALL, "");

整个计划将是:


# include <stdio.h>

# include <wchar.h>

# include <locale.h>

int main() {
  setlocale(LC_ALL, "ru_RU.utf8");
  wprintf(L"Привет, мир!\n");
}

至于您的代码在其他机器上的工作方式-这是由于libc在那里的操作方式。一些实现(如musl)不支持非unicode区域设置,因此可以无条件地将宽字符转换为utf-8序列。

vcirk6k6

vcirk6k62#

为什么它要将unicode中的俄语文本翻译成拉丁语,而不是将其转换成utf-8或使用替换字符?
因为程序的起始语言环境是默认的,所以 C 区域设置。所以它把宽弦转换成 C 区域设置。 C locale既不能处理utf-8,也不能处理任何unicode,因此您的标准库最好能将宽字符转换为在中使用的一些基本字符集 C 区域设置。
您可以将区域设置更改为任何utf-8区域设置,并且程序应该输出utf-8字符串。
注:(在实现中我知道)的编码 FILE 在选择流方向(宽与法线)时确定并保存流。记住在使用之前设置区域设置 stdout (即:这个对这个)。

相关问题