設置 | 登錄 | 註冊

目前共有7篇帖子。

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之間的字符。

內容轉換:

回覆帖子
內容:
用戶名: 您目前是匿名發表。
驗證碼:
看不清?換一張
©2010-2025 Purasbar Ver3.0 [手機版] [桌面版]
除非另有聲明,本站採用知識共享署名-相同方式共享 3.0 Unported許可協議進行許可。