c语言下中文处理

终于解决c语言中文问题

  • 前言
  • 实验环境
  • PRAT1 源码内部中文,显示,长度,测试1-7
    • TEST 1
    • TEST 2
    • TEST 3
    • TEST 4
    • TEST 5
    • TEST 6
    • TEST 7
    • PART1 总结
  • PART 2 外部文件中文访问测试
    • TEST 1
    • TEST 2
    • TEST 3
    • PART 2 总结
  • PART 3 切片(索引)测试
  • 总结
  • reference

前言

编码一直是让人头疼的问题,没有之一.那么不同平台下,不同编码,不同编译器,不同控制台输出编码,都会有各种问题…下面集中讨论下各种编码的不同组合会发生什么?

实验环境

编译器:c语言下中文处理_第1张图片
IDE1:sublime text 3c语言下中文处理_第2张图片
IDE2:记事本…
查看器:binary viewer.
控制台1:git bash
c语言下中文处理_第3张图片
控制台2:cmd

控制台3:ps

PRAT1 源码内部中文,显示,长度,测试1-7

TEST 1

环境:源码用utf-8编码,纯输出测试.IDE:st.
使用wcahr_t数组创建中文字符串,测试wcslen函数和wprintf对中文的支持:

#include 
#include 
#include 

int main() {
	setlocale(LC_ALL, "");
	wchar_t *c = L"我爱中国ABC23";
	wprintf(L"长度:%d\n", wcslen(c));	
}

编译命令:gcc a.c -o a.exe 结果测试:
c语言下中文处理_第4张图片

TEST 2

直接printf输出中文测试.
c语言下中文处理_第5张图片

TEST 3

printf("%ls\n", c);
c语言下中文处理_第6张图片
butbutbut:st下:

TEST 4

测试wcstombs函数

	setlocale(LC_ALL, "");
	wchar_t *c = L"我爱中国ABC23";
	char a[123];
	wcstombs(a, c, 123);
	printf("%s\n", a);

c语言下中文处理_第7张图片
sublime仍不能输出.

TEST 5

注释掉第一行本地设置函数:大家都统一了…
c语言下中文处理_第8张图片
(下面还是恢复setlocale)

TEST 6

直接用char存储中文字符(源码中),并用[w]printf分别测试:
c语言下中文处理_第9张图片

TEST 7

源码内部使用wchar_t存储中文,源码UTF-8编码.
c语言下中文处理_第10张图片

	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,内容:

c语言下中文处理_第11张图片
这部分开始之前,先用bv查看一下文件头部隐式内容.
c语言下中文处理_第12张图片
挺好没有BOM头,那什么是BOM捏.看这个:先用记事本把这个文件另存为,名字填a.txt覆盖掉,然后底下的编码选择UTF-8
c语言下中文处理_第13张图片
再次刷新一下bv试试?
好吧我也不晓得为莫斯这样,反正utf-8编码的就是很不爽:

保险起见,先把文件换回ANSI编码.
这里提示一下啊,windows下ANSI就是指GBK…[参考见后文]

TEST 1

源码:

#include 
#include 
#include 

int main() {
	setlocale(LC_ALL, "");
	FILE *fp=fopen("a.txt", "r");
	char s[123];
	fgets(s, 123, fp);
	printf("%s\n", s);
	return 0;
}


注意最后那个空格,这个是文件里我打的,但是截图解不出来…
c语言下中文处理_第14张图片
其中,GITBASH上一条输出是控制台编码utf-8编码下的,正常,cmd和ps都是.936(GBK)…

TEST 2

测试mbstowcs函数,使用wprintf输出:
c语言下中文处理_第15张图片
现在,文件是用的是ANSI.
c语言下中文处理_第16张图片
sublime仍然不行.

TEST 3

把文件改成utf-8?!!
c语言下中文处理_第17张图片
另:每次截图的都按最后一行输出算.
这就不好//

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为证:
c语言下中文处理_第18张图片
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

你可能感兴趣的:(学习笔记,c语言,编程语言,windows)