2010-10-16 39 views
10

我閱讀了一些關於C++中字符串和字符編碼最佳實踐的文章,但是我正在努力尋找一種對我來說合理簡單和正確的通用方法。我可以就以下問題徵求意見嗎?我傾向於使用UTF-8和UTF-32,並定義是這樣的:C++中的字符串和字符編碼

typedef std::string string8; 
typedef std::basic_string<uint32_t> string32; 

的string8類將被用於UTF-8,和具有單獨的類型僅僅是一個編碼的催。另一種方法是將string8作爲std :: string的子類,並刪除UTF-8不完全正確的方法。

當需要固定字符大小時,string32類將用於UTF-32。

UTF-8 CPP函數utf8 :: utf8to32()和utf8 :: utf32to8()甚至更簡單的包裝函數將用於在兩者之間進行轉換。

+0

請注意'string8'仍然與'std :: string'類型相同;它只是一個不同的名字。 – 2010-10-16 20:15:39

+0

哪個'std :: basic_string'函數*對於UTF-8是正確的? – dalle 2010-10-16 20:20:34

+0

UTF-32通過wstring/Unicode購買你什麼?順便說一句Visual Studio定義了'u16string'和'u32string'。 – 2010-10-16 20:31:04

回答

9

如果您計劃只是傳遞字符串並且從不檢查它們,您可以使用普通的std::string,儘管這是一個窮人的工作。

問題是,大多數框架,甚至標準,都愚蠢地(我認爲)在內存中強制編碼。我說愚蠢,因爲編碼只應該在接口上,並且這些編碼不適用於數據的內存中操作。此外,編碼很容易(這是一個簡單的CodePoint轉換 - >字節和相反),而主要難點實際上是操縱數據。

對於8位或16位,由於std::stringstd::wstring都不知道Unicode字符是什麼,所以存在切割中間字符的風險。更糟糕的是,即使使用32位編碼,也存在將字符從適用於其的變音符中分離出來的風險,這也是愚蠢的。

就標準而言,Unicode在C++中的支持因此是非常不利的。

如果你真的想操作Unicode字符串,你需要一個Unicode識別的容器。通常的方法是使用庫,儘管它的接口真的是C-ish。但是,您將獲得使用多種語言實際使用Unicode所需的一切。

+1

我發現你對有關diacritics的評論有點嚇人。從某種意義上講,它與我正在嘗試做的事情最爲相關,即以相對簡單的方式「正確」處理字符串。 – nassar 2010-10-19 02:13:57

+0

@nassar:不幸的是它很可怕,因爲我們缺乏適當的支持:'( – 2010-10-19 07:08:43

+0

)ICU(在C++的其他接口中)有一個與std :: string互操作的C++字符串類 – 2010-10-20 05:00:24

1

特徵描述here可能會有所幫助。這是一種古老而有用的技術。

1

沒有指定字符串編碼必須用於字符串,wstring等常用的方法是在寬字符串中使用unicode。應使用哪些類型和編碼取決於您的要求。

如果您只需要將數據從A傳遞給B,請選擇使用UTF-8編碼的std :: string(不要引入新類型,只需使用std :: string)。如果您必須使用字符串(提取,concat,sort,...)選擇std :: wstring,並在Windows上對UCS2/UTF-16(僅限BMP)和Linux上的UCS4/UTF-32進行編碼。 好處是固定大小:每個字符的大小爲2(或UCS4爲4)字節,而帶有UTF-8的std :: string返回錯誤的length()結果。

對於轉換,您可以檢查sizeof(std :: wstring :: value_type)== 2或4以選擇UCS2或UCS4。我正在使用ICU庫,但可能有簡單的包裝庫。

不建議派生自std :: string,因爲basic_string不是爲(缺少虛擬成員等)而設計的。如果你真的真的需要你自己的類型,如std :: basic_string < my_char_type>爲此寫一個自定義的專業化。

新的C++ 0x標準定義wstring_convert <>和wbuffer_convert <>與一個std ::的codecvt從窄字符集轉換爲寬字符集(例如UTF-8至UCS2)。 Visual Studio 2010已經實現了這個afaik。

+2

我特意避開了UCS-2,因爲在我看來,如果有人要處理字符編碼的麻煩,那麼不妨做到這一點,並支持完整的Unicode。 (與此同時,我正在尋找一些比通用ICU更笨重的東西)。對於UTF-16,它似乎具有可變長度編碼和使用大量內存的缺點。這就是爲什麼我建議結合使用UTF-8和UTF-32。 – nassar 2010-10-16 23:00:50

+0

關於從std :: string派生的點。謝謝! – nassar 2010-10-16 23:14:57

+1

我認爲定義一個新類型並不重要,但很多在代碼中看到std :: string的人往往會忘記多字節字符並錯誤地使用字符位置。它是UTF-8的事實可以在評論中傳達,但在類型名稱中提醒似乎很有幫助,因爲在我看來,諸如std :: string :: insert()這樣的方法確實提示了8位字符。 – nassar 2010-10-16 23:33:31