为何`wprintf`会将非ASCII字符替换为问号`?`?
为何
wprintf会将非ASCII字符替换为问号?? 这个问题我刚接触Linux宽字符编程时踩过一模一样的坑!本质原因是程序默认的区域设置(locale)不支持非ASCII字符,导致宽字符输出时无法正确转换为终端能识别的编码,最后只能用问号来替代。
给你拆解一下来龙去脉:
- C程序启动后,默认的locale是
"C"(也叫POSIX locale),这个古老的设置只认ASCII字符,对任何非ASCII宽字符都处理不了。当wprintf尝试把宽字符L'ä'转换成终端能显示的多字节编码时,"C"locale直接表示“我不认识这个字符”,就用问号?来凑数了。 - 像
wprintf这类宽字符I/O函数,完全依赖当前程序的locale来做编码转换。如果不主动设置正确的locale,它就会一直用默认的"C"locale干活,非ASCII字符肯定出问题。
那怎么解决呢?其实只要加一行代码就行:
首先要包含<locale.h>头文件,然后在main函数开头调用setlocale(LC_ALL, ""),让程序自动读取系统的默认locale(也就是你终端当前用的编码,现在Linux终端基本都是UTF-8了)。修改后的代码是这样的:
#include <stdio.h> #include <wchar.h> #include <locale.h> int main() { // 初始化locale为系统默认值 setlocale(LC_ALL, ""); wprintf(L"Hej hopp: %lc\n", L'ä'); }
为什么这行代码有用?setlocale(LC_ALL, "")会读取你系统里的LANG、LC_CTYPE等环境变量,把程序的locale设置成和终端一致的编码(比如en_US.UTF-8或者sv_SE.UTF-8)。这样wprintf就知道要把宽字符L'ä'转换成UTF-8编码输出到终端,终端也能正确识别并显示出ä了。
额外提一句:如果你的终端编码不是UTF-8(比如老系统用的ISO-8859-1),那可能还要调整终端编码,但现在Linux桌面环境下的终端基本都是默认UTF-8,所以核心问题还是没初始化locale。
备注:内容来源于stack exchange,提问作者Per Lundberg
相关产品推荐
相关产品推荐

