1. char与wchar_t定义字符串
- char与wchar_t定义字符串的编码方式?
char是扩展ANSI,在简体中文系统下,是GB2312。这是一种变长的编码方式。
wchar_t是UTF16。这是一种定长的编码方式。 - GB2312的解码?
根据数值来判断。具体数字不清楚,估计大于127的都是汉字的编码,[0-127]是ANSI。比如:如果遇到的是1个大于127的字符,那么就继续读1个字符,这两个字符,组成1个编码,找到一个汉子。如果遇到的是1个小于等于127的字符,那么就是1个ANSI字符。 - UTF16的解码?
所有字符都是2个字节编码,编码都是唯一的。
int main()
{
const char* text = "你好A<>";
printf("len = %d\n", strlen(text));
printf("sizeof(text[0]) = %d\n", sizeof(text[0]));
for (int i = 0; i < strlen(text); i++)
{
printf("%d\n", text[i]);
}
const wchar_t* wtext = L"你好A<>";
printf("len = %d\n", wcslen(wtext));
printf("sizeof(wtext[0]) = %d\n", sizeof(wtext[0]));
for (int i = 0; i < wcslen(wtext); i++)
{
printf("%d\n", wtext[i]);
}
getchar();
return 0;
}
2. 根据指针转化编码
多字节编码:UTF8,GB2312等等
固定字节编码:Unicode(实际上就是UTF16)
- 多字节编码之间的转化,需要通过固定字节编码。
比如:UTF8转GB2312:先把UTF8转为Unicode,再把转为Unicdoe->GB2312。 - 多字节编码与Unicode的转化,可以直接转。
比如:UTF8与GB2312可以直接转。 - 代码中的len+1
int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
上面这行代码,会从gb2312指向的char*开始扫描,知道遇到\0,计算一共扫描了多少个字符(但不包括最后的\0),把这个数,返回到len上面。
len+1,就是为了,在字符串最后加上一个\0。
//UTF-8到GB2312的转换
char* U2G(const char* utf8)
{
// UTF-8 -> Unicode
int len = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
wchar_t* wstr = new wchar_t[len+1];
memset(wstr, 0, len+1);
MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, len);
// Unicode -> GB2312
len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
char* str = new char[len+1];
memset(str, 0, len+1);
WideCharToMultiByte(CP_ACP, 0, wstr, -1, str, len, NULL, NULL);
// 删除Unicode的Buffer
if(wstr) delete[] wstr;
// 返回GB2312的Buffer
return str;
}
//GB2312到UTF-8的转换
char* G2U(const char* gb2312)
{
// GB2312 -> Unicode
int len = MultiByteToWideChar(CP_ACP, 0, gb2312, -1, NULL, 0);
wchar_t* wstr = new wchar_t[len+1];
memset(wstr, 0, len+1);
MultiByteToWideChar(CP_ACP, 0, gb2312, -1, wstr, len);
// Unicode -> UTF-8
len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL);
char* str = new char[len+1];
memset(str, 0, len+1);
WideCharToMultiByte(CP_UTF8, 0, wstr, -1, str, len, NULL, NULL);
// 删除Unicode的Buffer
if(wstr) delete[] wstr;
// 返回UTF8的Buffer
return str;
}
3. 在字符串末尾加\0是否必要
很多库函数,比如strlen,printf,都是根据\0判断字符串结束。
比如:下面的例子,memcpy的时候,没有把\0拷贝过来,那么printf,strlen就会打印出其他位置的内容。这是很危险的。
int main()
{
const char* str = "abcde";
char * non_zero_str = new char[5];
memcpy(non_zero_str, str, sizeof(char) * 5);
printf("non_zero_str = %s\n", non_zero_str);
printf("strlen(non_zero_str) = %d\n", strlen(non_zero_str));
getchar();
return 0;
}
4. 硬编码的二进制文件读写
项目中有个策略文件,读写都是二进制的方式。
举例:写入1个int,1个char,10个char。读取1个int,1个char,10个char。这样肯定不会有问题。甚至是混合char与wchar_t都没有问题。因为读取和写入的顺序都是一一对应的。