[代码] C++编码转化

1. char与wchar_t定义字符串

  1. char与wchar_t定义字符串的编码方式?
    char是扩展ANSI,在简体中文系统下,是GB2312。这是一种变长的编码方式。
    wchar_t
    是UTF16。这是一种定长的编码方式。
  2. GB2312的解码?
    根据数值来判断。具体数字不清楚,估计大于127的都是汉字的编码,[0-127]是ANSI。比如:如果遇到的是1个大于127的字符,那么就继续读1个字符,这两个字符,组成1个编码,找到一个汉子。如果遇到的是1个小于等于127的字符,那么就是1个ANSI字符。
  3. 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;
}
char与wchar_t的长度与编码

2. 根据指针转化编码

多字节编码:UTF8,GB2312等等
固定字节编码:Unicode(实际上就是UTF16)

  1. 多字节编码之间的转化,需要通过固定字节编码。
    比如:UTF8转GB2312:先把UTF8转为Unicode,再把转为Unicdoe->GB2312。
  2. 多字节编码与Unicode的转化,可以直接转。
    比如:UTF8与GB2312可以直接转。
  3. 代码中的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;
}
没有\0的后果

4. 硬编码的二进制文件读写

项目中有个策略文件,读写都是二进制的方式。
举例:写入1个int,1个char,10个char。读取1个int,1个char,10个char。这样肯定不会有问题。甚至是混合char与wchar_t都没有问题。因为读取和写入的顺序都是一一对应的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容