终于解决c语言中文问题
前言
编码一直是让人头疼的问题,没有之一.那么不同平台下,不同编码,不同编译器,不同控制台输出编码,都会有各种问题…下面集中讨论下各种编码的不同组合会发生什么?
实验环境
编译器:
IDE1:sublime text 3
IDE2:记事本…
查看器:binary viewer.
控制台1:git bash
控制台2:cmd
控制台3:ps
PRAT1 源码内部中文,显示,长度,测试1-7
TEST 1
环境:源码用utf-8编码,纯输出测试.IDE:st.
使用wcahr_t数组创建中文字符串,测试wcslen函数和wprintf对中文的支持:
#include <wchar.h>
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, "");
wchar_t *c = L"我爱中国ABC23";
wprintf(L"长度:%d\n", wcslen(c));
}
编译命令:gcc a.c -o a.exe 结果测试:
TEST 2
直接printf输出中文测试.
TEST 3
printf("%ls\n", c);
butbutbut:st下:
TEST 4
测试wcstombs函数
setlocale(LC_ALL, "");
wchar_t *c = L"我爱中国ABC23";
char a[123];
wcstombs(a, c, 123);
printf("%s\n", a);
sublime仍不能输出.
TEST 5
注释掉第一行本地设置函数:大家都统一了…
(下面还是恢复setlocale)
TEST 6
直接用char存储中文字符(源码中),并用[w]printf分别测试:
TEST 7
源码内部使用wchar_t存储中文,源码UTF-8编码.
setlocale(LC_ALL, "");
wchar_t *c = L"我爱中国";
printf("%ls[[[printf+%%ls::\n", c);
wprintf(L"%ls[[[wprintf+%%ls::\n", c);
PART1 总结
至此第一部分测试结束,结论是:
源码使用utf-8编码(这点是必须的,我试过源码拿记事本另存ANSI之后gcc编译都不过去…)
为了适应更多控制台,最好用wchar_t存中文,如果源码内部必须要中文的话.
sublime的问题之后再解决…
存中文字符串用wchar_t* 或者wchar_t[],加上前缀L;
输出用[最好是w]printf加上%ls标志符.
番外:试过在windows系控制台下,调用chcp 65001
控制台输出编码调整成UTF-8,好像自动适应了诶…
也就是说,wchar_t+wprintf(%ls)是最好的最稳妥的操作…
P.S.事实上,在有可能有中文出现的地方,尽量用wchar_t,而且gcc编译不要跟网上一样带上任何-fxxxx-charset= 参数,这不好.
PART 2 外部文件中文访问测试
这里有一个记事本写成的a.txt,内容:
这部分开始之前,先用bv查看一下文件头部隐式内容.
挺好没有BOM头,那什么是BOM捏.看这个:先用记事本把这个文件另存为,名字填a.txt覆盖掉,然后底下的编码选择UTF-8
再次刷新一下bv试试?
好吧我也不晓得为莫斯这样,反正utf-8编码的就是很不爽:
保险起见,先把文件换回ANSI编码.
这里提示一下啊,windows下ANSI就是指GBK…[参考见后文]
TEST 1
源码:
#include <wchar.h>
#include <stdio.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, "");
FILE *fp=fopen("a.txt", "r");
char s[123];
fgets(s, 123, fp);
printf("%s\n", s);
return 0;
}
注意最后那个空格,这个是文件里我打的,但是截图解不出来…
其中,GITBASH上一条输出是控制台编码utf-8编码下的,正常,cmd和ps都是.936(GBK)…
TEST 2
测试mbstowcs函数,使用wprintf输出:
现在,文件是用的是ANSI.
sublime仍然不行.
TEST 3
把文件改成utf-8?!!
另:每次截图的都按最后一行输出算.
这就不好//
PART 2 总结
综上所述,读取外部文本文件时,文本应该GBK编码,然后使用接口把内容读进char数组,再调用mbstowcs函数转化,最后使用wprintf函数输出,跟源码内部中文处理一个样.
经过以上实验,可以发现,用wchar_t(宽字符)
和wprintf
函数,我们可以相比下更"通用"地处理中文,灵活性大大增加.
为什么说"通用"呢?其根本原因是,windows系控制台常用chcp参数:936(默认,GBK)或者65001(UTF-8)都兼容了我们的输出,这也就是说,再不改变二进制可执行文件的编译过程情况下,无论控制台编码如何,输出都正常.
PART 3 切片(索引)测试
这部分很简单啊,直接上手咯
首先声明一个中文字符串
wchar_t c[] = L"我爱中国123abc";
然后,来个简短的小测试:
printf("%d\n", c[0]);
25105,没错就是"我",有python为证:
nice,那么其他同理,索引0开始没毛病.
那单字输出试试呢?(没错就是在%c加个l,%lc)
printf("%lc\n", c[0]);
很好依然sublime不行但是其他都可以.
总结
wchar_t类型用于处理中文,wprintf+%ls/lc用来输出,如果读外部文件的话,就要用ANSI也就是GBK保存.取索引什么的照样用
reference
https://codingdict.com/article/2293
https://www.zhihu.com/question/26701633