一个关于WINDOWS下字符的问题
假设有下列代码,其中,a.txt文件的内容是
abcdefghijklmn
一二三四五六七八九十
#include <stdio.h>
#define FILENAME "a.txt"
int main(void)
{
FILE *fp=fopen(FILENAME,"rt");
int str[256],ch,num=0,i;
if(fp==NULL)
{
printf("No such file:%s.\n",FILENAME);
exit(1);
}
while((ch=fgetc(fp))!=EOF)
{
printf("%c",ch);
str[num++]=ch;
}
printf("\n字符数:%d\n",num);
for(i=0;i<num;i++)
{
printf("%d ",str[i]);
}
system("PAUSE");
return 0;
}
输出是:
abcdefghijklmn
一二三四五六七八九十
字符数:35
97 98 99 100 101 102 103 104 105 106 107 108 109 110 10 210 187 182 254 200 253
203 196 206 229 193 249 198 223 176 203 190 197 202 174 请按任意键继续. . .
每次从文件中读取的是一个字节的内容,然后输出到标准输出流,一个汉字需要调用两次printf函数,那么CMD是如何识别出是汉字的呢?还有,每个汉字的2个字节与编码有关吗(比如UNICODE)?
[解决办法]
C语言不识别编码, 只有函数库iconv之类的会按照你的指示转换编码.
C语言文件自身有编码,直接影响到字符串常量的编码.
C语言只认识一堆字节, 如果你希望在一堆UTF8的字节里找一堆GBK字节, 是不可能成功找出关键字的, C语言的所有string.h库都是单字节匹配,因为即便是UTF8,GBK,它们也是单字节组成的多字节字符,
strstr("你好吗", "好吗");
无论C文件是UTF8还是GBK,上面这个strstr函数内部都是一个双重for循环的单字节匹配,
对于GBK码的C源文件,假设 : 你 是\x81\x82, 好 是\xa2\xa3 吗 是\xb2\xb3,那么整个调用其实是在以下两个堆字节之间做for循环匹配:
strstr("\x81\x82\xa2\xa3\xb2\xb3", "\xa2\xa3\xb2\xb3"); 这个函数只是匹配字节,它不管你编码是什么,懂了吗?
C文件是UTF8也是类似的,所以在使用时一定要统一编码才能正确的从一堆字节中找出想要的字节,clear?
[解决办法]
再比如strlen,它只是数一数字节有几个,肯定不是“你好吗”这3个字的个数。
比如C源文件是UTF8的,那么strlen("你好吗abd"); 你肯定猜不出是几,因为UTF8对于非ASCII是多字节可变编码的,除非你去查表。 那怎么统计字符串长度? 很简单,UTF16是双字节定长编码,它和GBK/UTF8不一样,但可以互相转换。 所以iconv把"你好吗abd"这个strlen("你好吗abd")长度的字节流交给iconv,从utf8转成unicode,看看iconv的输出是K字节,那么实际长度就是K/2,也就是6个字。