2011-12-21 120 views
-4

這是一個關於Unicode的初學者問題。我正在使用Embarcadero C++ Builder 2009,他們據說改變了默認字符串以使用Unicode。Unicode轉換問題

  • 我在我的源代碼編輯器中輸入了各種不符合標準「7位ASCII」的符號。
  • 我的程序使用C++ Builder的String類型來獲取用戶輸入。
  • 我也通過將值設置爲wchar_t來手動添加輸入。

似乎在解釋符號的方式上存在衝突。有時我會得到一個符號,例如代碼0x00C7('Ç'),但有時候相同的符號會被編碼爲0xFFC7,例如在源代碼編輯器中。據我瞭解,前者是合適的Unicode,後者是「別的東西」。有人能證實這一點嗎?

我在想這個「別的東西」編碼是從哪裏來的,以及如何擺脫它?

編輯:進一步的研究:它似乎是0xFF的**出現編碼,其中一個地方就是,當我做這樣的事情:

string str = ...; 
wchar_t wch = (wchar_t)str[i]; 

同樣的結果不管它是的std :: string或VCL字符串。 wchar_t與Unicode不一樣嗎?

+0

如果使用utf-8進行編碼,則每個unicode字符可能佔用1,2或4個字節或更多。據我瞭解,wchar_t每個字符的大小總是2個字節,所以可能是問題所在。 – greatwolf 2011-12-21 10:23:16

+0

@VictorT。那麼我應該使用哪種字符類型?我認爲普通** char **是8位。 – Lundin 2011-12-21 10:27:36

+0

對於寬字符的字符串(Unicode),您應該使用'wstring'而非'string'。新的'String'類型使用以UTF-16存儲的寬字符(不要擔心其他編碼,例如UTF8)。你的代碼'string str = ...;'會丟失數據。那麼你不應該在你的第二行需要演員陣容。 – 2011-12-22 16:13:30

回答

4

我猜測問題是在你的編譯器char被簽名(標準允許它是有符號或無符號的,它是實現定義/特定的)。因此,無論何時將位7設置爲1(0x80至0xFF)的字符轉換爲任何更大的整數類型,都將其視爲負值,並將其標記擴展以保留負值,換句話說,第7位被複制到第8位,第9位等,並被分配到較大整數類型的所有較高位中。所以,0xC7可以變成0xFFC7和0xFFFFFFC7。爲防止發生這種情況,請先將chars改爲unsigned chars

+0

我也懷疑這一點,所以我小心地使用我自己的uint8類型的字符。但是,我猜** ** char **可能被某些字符串類型或庫對象內部使用。 – Lundin 2011-12-21 10:56:50

+0

C++的'string'通常爲每個字符串元素使用普通的'char'。如果'char'有符號,那麼'str [some index]'也是如此,因此只要它在表達式(包括賦值)中使用,就會受到符號擴展的影響。 – 2011-12-21 11:00:25

+0

我剛剛意識到源代碼中的char文字最可能是** char **類型,或者更確切地說,int被截斷爲char。他們的確會被解釋爲負數。這解釋了一些古怪但不是全部。 – Lundin 2011-12-21 11:02:08

1

寬字符類型w_type是實現定義的,不需要對應於Unicode字符的概念。檢查出description of w_type in the Unicode Standard

如果「Ç」更改爲0xFFC7,它看起來非常像符號擴展名,即字符內部存儲爲字節0xC7,然後將其作爲有符號的8位整數並轉換爲16位整數簽名擴展。

+0

對wchar_t的簽名是否有任何保證,是否總是未簽名/簽名?因爲看起來wchar_t可能是這裏的罪魁禍首。 – Lundin 2011-12-21 10:58:45

+2

'wchar_t'的簽名並不是這裏的罪魁禍首。罪魁禍首是'char'的簽名。 – 2011-12-21 11:07:52

+0

@Alex不夠好,但出於好奇,標準對wchar_t的簽名有什麼意義? – Lundin 2011-12-21 12:06:29