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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dtsroy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值