目前共有7篇帖子。 内容转换:不转换▼
 
点击 回复
359 6
char[]和wchar_t[]的根本区别
一派护法 十九级
1楼 发表于:2016-1-4 13:38
char[]是多字节字符串,一个字符可能用一个数组元素表示,也有可能用多个数组元素表示。
而wchar_t[]每个字符固定使用一个数组元素表示。

因此,char和wchar_t的根本区别是字符串的存储方式,而不是字符串的编码。从理论上来说,它们都可以用来存储任意编码的任意字符串。不过实际上,因为在不同编译器上定义wchar_t的位数不同,可能是16或32位。而UTF8中汉字是用3个字节存储的,所以,当编译器把wchar_t认作是16位时,wchar_t字符数组不能用来存放UTF8编码的字符串。
一派护法 十九级
2楼 发表于:2016-1-4 13:41
基于这个原因,一般我们要存储任意编码的字符串时,特别是在进行编码转换时,都是用char[]字符数组。不过用char[]的话,计算字符串中的字符个数会比较麻烦,在字符串中移动光标也更麻烦。
一派护法 十九级
3楼 发表于:2016-1-4 13:49
在Windows下的VC++编译器下,字符串(无论是单引号还是双引号括起来的)的默认编码是ANSI,这种编码与系统locale高度相关。比如说,在中文Win7下用记事本写一个含有汉字的文本文件,再在英文版Win7下打开,就会发现文件中凡是中文的地方都全部乱码了,而英文字母正常。此时,如果把英文版Win7的控制面板中的locale改成Simplified Chinese PRC的话,那么再打开txt文件,中文就能正常显示了。

而Linux下的gcc,g++编译器下,字符串的默认编码就是UTF-8,一个汉字占三个字节。输出的txt文件如果含有中文,那么无论是用什么语言的Windows系统打开,只要安装了中文字体,无需改动locale设置就能正常显示中文字符。

对于如下C++代码:
char str[] = "中文abc";
cout << sizeof(str) / sizeof(char) << endl;
在Windows下的VC++中编译,输出的是8。
而在Linux下的g++中编译,输出的却是10。
这一点,充分说明了char字符数组可以存储任意编码的字符串。
一派护法 十九级
4楼 发表于:2016-1-4 13:53
对于语句char str[] = "中文abc";
在VC++下,形成的字符数组是:
{'中' >> 8, '中' & 0xff, '文' >> 8, '文' & 0xff, 'a', 'b', 'c', '\0'}
而在g++下形成的却是:
{'中' >> 16, '中' >> 8 & 0xff, '中' & 0xff, '文' >> 16, '文' >> 8 & 0xff, '文' & 0xff, 'a', 'b', 'c', '\0'}
一派护法 十九级
5楼 发表于:2016-1-4 14:12
因此,在修改多字节字符串中的单个字符时,最好使用strcpy函数,不要直接修改数组元素。
例如要把字符数组char str[] = "中文abc";中的“文”字改成“国”字,应该写成:
char str[] = "中文abc";
char *pointer = strstr(str, "文"); // 该指针指向“文”字的开头
memcpy(pointer, "国", sizeof("国") - 1); // 把“国”复制到“文”字那里覆盖掉,但不复制“国”字最后的\0标记
cout << str << endl;
输出:中国abc

如果直接修改数组元素,则是:
char str[] = "中文abc";
str[2] = (char)('国' >> 8);
str[3] = (char)('国' & 0xff);
cout << str << endl;
不过,这样写会有兼容性问题。该段程序在Linux下用g++编译器编译后,运行会出错。
一派护法 十九级
6楼 发表于:2016-1-4 14:15
在上述程序中用的是memcpy而不是strcpy。其实这两个函数差不多,只不过strcpy会把“国”字末尾的\0也复制过去覆盖掉,最终的字符串成了“中国”(即“中国\0bc\0”)而不是“中国abc”。
用memcpy的好处就是可以指定复制的长度。sizeof减1后就可以把那个\0减掉,不复制它。
一派护法 十九级
7楼 发表于:2016-1-23 23:41
下面一段C++程序演示了如何手动将wchar_t字符串转换为UTF8格式存放到char数组中并写入txt文件:
    wchar_t wstr[] = L"这是一段中文字符串。";
    wchar_t *wch;
    char ch[3];
    FILE *fp;
    fopen_s(&fp, "file.txt", "wb");
    for (wch = wstr; *wch != '\0'; wch++)
    {
        ch[0] = 0xe0 + (*wch >> 12);
        ch[1] = 0x80 + ((*wch >> 6) & 0x3f);
        ch[2] = 0x80 + (*wch & 0x3f);
        fwrite(ch, sizeof(ch), 1, fp);
    }
    fclose(fp);
上面这一段程序只能正确的转换U+0800~U+FFFF之间的字符。

回复帖子

内容:
用户名: 您目前是匿名发表
验证码:
(快捷键:Ctrl+Enter)
 

本帖信息

点击数:359 回复数:6
评论数: ?
作者:巨大八爪鱼
最后回复:巨大八爪鱼
最后回复时间:2016-1-23 23:41
 
©2010-2024 Arslanbar Ver2.0
除非另有声明,本站采用知识共享署名-相同方式共享 3.0 Unported许可协议进行许可。