第二章 字符和字符串处理

  • 应用程序应始终使用Unicode字符串,并且通过安全的字符串函数去操作字符串,防止缓冲区溢出错误
  • Windows Vista中,每个Unicode字符都使用UTF-16编码
const wchar_t* pWStrC = L"Hello 蛮大人";   //字符串之前的L表示Unicode字符串
auto nSize = _tcsclen(pWStrC);            //nSize = 9
/*
TCHAR, TEXT, _T, _tcs*系列函数可以根据是否定义UNICODE来生成或
处理ANSI或UNICODE字符串*
*/

#ifdef UNICODE
typedef wstring mstring;
#else
typedef string mstring;
#endif
//则mstring能很好的搭配TCHAR*使用
  • 一些建议
  • 始终用通用数据类型(TCHAR)来表示文本和字符串
  • 用明确的数据类型(unsigned char)来表示字节、字节指针、数据缓冲区
  • 用TEXT或_T表示字面量字符和字符串
  • 始终使用安全的字符串处理函数


字符编码

ASCII

ASCII 码使用指定的7 位或8 位二进制数组合来表示128 或256 种可能的字符。

  • 标准ASCII 码也叫基础ASCII码,使用7 位二进制数(剩下的1位二进制为0)来表示所有的大写和小写字母,数字0 到9、标点符号,以及在美式英语中使用的特殊控制字符。
  • 后128个称为扩展ASCII码。
ANSI

不同的国家和地区制定了不同的标准,由此产生了 GB2312、GBK、Big5、Shift_JIS 等各自的编码标准。这些使用 1 至 4 个字节来代表一个字符的各种汉字延伸编码方式,称为 ANSI 编码。在简体中文Windows操作系统中,ANSI 编码代表 GBK 编码;在日文Windows操作系统中,ANSI 编码代表 Shift_JIS 编码。 不同 ANSI 编码之间互不兼容,当信息在国际间交流时,无法将属于两种语言的文字,存储在同一段 ANSI 编码的文本中。 当然对于ANSI编码而言,0x00~0x7F之间的字符,依旧是1个字节代表1个字符。这一点是ANSI编码与Unicode编码之间最大也最明显的区别。

GB2312

GB2312 是对 ASCII 的中文扩展。
0-127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(高字节)从0xA1用到0xF7,后面一个字节(低字节)从0xA1到0xFE,这样我们就可以组合出大约7000多个简体汉字了。在这些编码里,还把数学符号、罗马希腊的字母、日文的假名们都编进去了,连在 ASCII 里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全角”字符,而原来在127号以下的那些就叫”半角”字符了。

GBK

GBK包括了GB2312 的所有内容,同时又增加了近20000个新的汉字(包括繁体字)和符号。 加了几千个新的少数民族的字,GBK扩成了 GB18030。

UNICODE
  • Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。目前的Unicode字符分为17组编排,0X00 至 0x10FFFF,每组称为平面(Plane),而每平面拥有65536个码位,共1114112个。然而目前只用了少数平面。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。
  • UTF-8
    特点是对不同范围的字符使用不同长度的编码。对于0x00-0x7F之间的字符,UTF-8编码与ASCII编码完全相同。
UNICODE UTF-8
0000 0000-0000 007F 0xxxxxxx
0000 0080-0000 07FF 110xxxxx 10xxxxxx
0000 0800-0000 FFFF 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx


字符串转码与落盘

#include <string>
#include <assert.h>
#include <memory>
#include <Windows.h>

using std::unique_ptr;

template<typename T>
void Write(const char* pFilePathC, T* pStr, const size_t nSizeC, const 
    unsigned char* pAddFrontC = nullptr, const int nAddLenC = 0)
{
    FILE* fp = _fsopen(pFilePathC, "wb", _SH_DENYWR);
    if (fp)
    {
        size_t nRealSize = 0;
        if (pAddFrontC)
        {
            nRealSize = fwrite(pAddFrontC, 1, nAddLenC, fp);
            assert(nAddLenC == nRealSize);
        }

        nRealSize = fwrite(pStr, 1, nSizeC, fp);
        assert(nSizeC == nRealSize);
        fclose(fp);
        return;
    }
    assert(false);
}

const bool ANSIToUTF8(const char* pStrInC, char* pStrOut, 
    const int nBuffLenC);

int main()  
{  
    const char* pStrC = "Hello 蛮大人";        
    //内存中值(0x, 小端):48 65 6c 6c 6f 20 c2 f9 b4 f3 c8 cb 00
    const wchar_t* pWStrC = L"Hello 蛮大人";
/*
    内存中值(0x, 小端):
    48 00 65 00 6c 00 6c 00 6f 00 20 00 ee 86 27 59 ba 4e 00 00
*/
    unique_ptr<wchar_t[]> pWBuff(new wchar_t[wcslen(pWStrC) + 1]());
    if (pWBuff)
    {
        for (size_t i = 0; i < wcslen(pWStrC); ++i)
        {
            pWBuff[i] = _byteswap_ushort(pWStrC[i]);
        }
    }

    char aUtf8Str[1024] = {};
    bool nRe = ANSIToUTF8(pStrC, aUtf8Str, sizeof aUtf8Str);
    assert(nRe);

    Write("ANSI.txt", pStrC, strlen(pStrC));
    Write("UNICODE_NotAddHead.txt", pWStrC, wcslen(pWStrC) * 
        sizeof(wchar_t));
    Write("UNICODE_BIG_NotAddHead.txt", pWBuff.get(), wcslen(pWStrC) * 
        sizeof(wchar_t));
    Write("UTF-8_NotAddHead.txt", aUtf8Str, strlen(aUtf8Str));
    
    const unsigned char aUnicode[2] = {0xFF, 0xFE};
    const unsigned char aUnicodeBig[2] = {0xFE, 0xFF};
    const unsigned char aUtf8[3] = {0xEF, 0xBB, 0xBF};
    Write("UNICODE_AddHead.txt", pWStrC, wcslen(pWStrC) * sizeof(wchar_t),
        aUnicode, 2);
    Write("UNICODE_BIG_AddHead.txt", pWBuff.get(), wcslen(pWStrC) * 
        sizeof(wchar_t), aUnicodeBig, 2);
    Write("UTF-8_AddHead.txt", aUtf8Str, strlen(aUtf8Str), aUtf8, 3);

/*
    Windows的记事本对不同编码文件添加的数据头:
    ANSI        无
    UNICODE     0xFFFE
    UNICODE-big 0xFEFF
    UTF-8       0xEFBBBF
*/

/*
    文件名                      记事本     NotePad++
    ANSI.txt                    正常      正常
    UNICODE_NotAddHead.txt      乱码      正常
    UNICODE_AddHead.txt         正常      正常
    UNICODE_BIG_NotAddHead.txt  乱码      乱码
    UNICODE_BIG_AddHead.txt     正常      正常
    UTF-8_NotAddHead.txt        正常      正常
    UTF-8_AddHead.txt           正常      正常
*/

/*
    #define CP_ACP          0       // default to ANSI code page
    #define CP_OEMCP        1       // default to OEM  code page
    #define CP_MACCP        2       // default to MAC  code page
    #define CP_THREAD_ACP   3       // current thread's ANSI code page
    #define CP_SYMBOL       42      // SYMBOL translations

    #define CP_UTF7         65000   // UTF-7 translation
    #define CP_UTF8         65001   // UTF-8 translation
*/
    return 0;  
}  


const bool ANSIToUTF8(const char* pStrInC, char* pStrOut,
    const int nBuffLenC)
{
    int nSize = MultiByteToWideChar(CP_ACP, 0, pStrInC, -1, NULL, 0);
    unique_ptr<wchar_t> pWBuff(new wchar_t[nSize]);
    MultiByteToWideChar(CP_ACP, 0, pStrInC, -1, pWBuff.get(), nSize);
    nSize = WideCharToMultiByte(CP_UTF8, 0, pWBuff.get(), -1, NULL, 0,
        NULL, NULL);

    if (nBuffLenC < nSize)
    {
        return false;
    }

    WideCharToMultiByte(CP_UTF8, 0, pWBuff.get(), -1, pStrOut, nSize, 
        NULL, NULL);
    return true;
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容