C语言如何正确处理拉丁特殊字符的读写及乱码问题?
解决C语言读写拉丁特殊字符乱码问题
问题根源
双向乱码的本质是三个编码环节不匹配导致的:
- 代码源文件的存储编码
- C程序运行时locale指定的字符编码
- 终端/控制台的显示编码、输入文件的存储编码
只要其中任意两个不一致,就会出现要么硬编码字符串乱码、要么读取的外部字符串乱码的情况。
具体解决步骤
1. 先确定统一使用的编码
优先推荐用UTF-8,跨平台兼容性最好,Windows 10 1903及之后的版本已经原生支持;如果仅在葡萄牙语区域的Windows环境运行,也可以选择CP1252编码。
2. 统一源文件存储编码
用你的代码编辑器修改.c源文件的存储编码,和你选定的编码保持一致:
- 选UTF-8的话,保存为「UTF-8 无BOM」格式(Visual Studio老版本可选UTF-8带BOM避免识别错误)
- 选CP1252的话,保存为「ANSI」格式即可(葡萄牙语区域的Windows系统下ANSI默认对应CP1252)
3. 正确配置setlocale
你之前仅配置LC_CTYPE的覆盖范围不足,LC_CTYPE仅控制字符分类逻辑,要覆盖输入输出的编码转换,需要设置LC_ALL:
如果你选UTF-8编码:
- Windows环境调用:
setlocale(LC_ALL, ".UTF8") - Linux/macOS环境调用:
setlocale(LC_ALL, "pt_BR.UTF-8") - 跨平台通用写法可以先用
setlocale(LC_ALL, ""),会自动继承系统当前的区域编码,只要系统默认编码是UTF-8就可以正常工作
如果你选CP1252编码(仅Windows适用):
直接调用:setlocale(LC_ALL, "Portuguese_Brazil.1252")
4. 匹配输入文件和终端的编码
- 你用
fgets读取的外部文本文件,存储编码要和你选定的编码一致,如果需要读取其他编码的文件,需要额外用iconv或者MultiByteToWideChar之类的接口做编码转换 - 终端的显示编码也要同步匹配:
- UTF-8对应Windows cmd的代码页65001,运行程序前可以执行
chcp 65001切换 - CP1252对应Windows cmd的代码页1252,运行程序前执行
chcp 1252切换
- UTF-8对应Windows cmd的代码页65001,运行程序前可以执行
常见避坑提示
- 不要在同一个输出流里混用窄字符函数(
printf/fgets)和宽字符函数(wprintf/fgetws),混用会触发未定义行为,大概率会出现乱码 - 如果用Visual Studio编译,可以在项目属性的「高级」选项里统一设置源文件编码和执行字符集,减少手动修改的问题
内容的提问来源于stack exchange,提问作者Zaratruta
相关产品推荐
相关产品推荐

