2014-09-29 144 views
6

我在寫一些類似於atoi()strtoll()的字符串轉換函數。我想包括我的函數的一個版本,它可以接受char16_t *或char32_t *,而不僅僅是char *或wchar_t *。C11 Unicode支持

我的函數可以正常工作,但是當我寫它時,我意識到我不明白char16_t或char32_t是什麼。我知道標準只要求它們是一個至少16或32位的整數類型,但其含義是它們是UTF-16或UTF-32。我也知道該標準定義了幾個函數,但它們不包括任何* get或* put函數(就像他們在C99中添加wchar.h時所做的那樣)。

所以我想知道:他們期望我用char16_t和char32_t做什麼?

+1

轉換爲UTF-8,還有什麼? – Deduplicator 2014-09-29 18:58:04

+0

@Deduplicator:如果這就是他們希望你對他們做的事情,你會認爲他們會給你這樣做的功能...... – 2014-09-29 19:16:31

+0

你打算不僅支持'0..9'(U + 0030 .. U + 0039)(也可能是'A..Z/a..z',最高級別爲最高級別,基數爲36),但在完整的Unicode表格中也標記爲「Numeric」的所有其他字符? 'Coz這包括印刷形式(超級和下標,圓圈數字高達20(!))和腳本特定形式(阿拉伯數字,希伯來數字),以及羅馬數字,古希臘和「計數杆」等等。 – usr2564301 2014-09-29 20:56:55

回答

9

這是一個很好的問題,沒有明顯的答案。

在C11中添加的uchar.h類型和功能在很大程度上是無用的。它們僅支持新類型(char16_tchar32_t)與特定於語言環境的實現定義的多字節編碼之間的轉換,這些映射除非區域設置基於UTF-8,否則不會完整。不支持有用的轉換(來自wchar_t以及來自/來自UTF-8的有用轉換)。當然,由於這些轉換是由相關的RFC/UCS/Unicode標準100%指定的,因此您可以推出自己的轉換到UTF-8 /從UTF-8轉換,但要小心:大多數人執行錯誤並且存在危險的錯誤。

注意,新編譯器級設有爲UTF-8,UTF-16,和UTF-32的文字(u8u,和U,分別地)是潛在有用的;你可以使用你自己的函數以有意義的方式處理結果字符串,這些方式完全不依賴於語言環境。但是在我看來,對C11中Unicode的支持的庫級別基本上沒用。

+0

你知道多少它限制了可移植性,以承擔多字節編碼是UTF-8? (我的意思是,這是類似於「標準允許非2的補碼」,這在實踐中可能經常被忽略,或者這真的是我應該擔心的事情嗎?) – mafso 2014-09-29 20:43:47

+0

@mafso:我不認爲* internal *表示作爲UTF8的字符串是潛在的可移植性問題。但是如果沒有可移植的(幾乎可以肯定「每個定義」)方式來顯示結果,你將如何顯示文本? – usr2564301 2014-09-29 20:49:04

+1

@Jongware:我知道它不可移植(理論上)。但是這種「特定於語言環境的多字節編碼」和「特定於語言環境的寬字符編碼」的東西是用C89進行標準化的,而Unicode編碼並不像今天這樣被廣泛使用(IIRC他們甚至沒有當時標準化)。我的問題是,如果它現在可以安全地假設在編程中使用Unicode編碼。 – mafso 2014-09-29 20:57:38

3

測試ASCII範圍內的UTF-16或UTF-32章程是「常規」10位數字,+, - 或「正常」空格之一是否容易執行以及將'0'-'9'轉換爲一個數字。鑑於此,atoi_utf16/32()收益如atoi()。一次只檢查一個角色。

測試是否有一些其他 UTF-16/UTF-32是一個數字或白色空間 - 更難。代碼將需要擴展isspace(), isdigit(),如果所需的語言環境可用,則可能需要切換語言環境(setlocale())。 (注:可能需要恢復的區域設置當函數完成

轉換是通過isdigit()而不是通常的10到它的價值是有問題的一個字符不管怎麼說,這出現到甚至沒有被允許。

轉換步驟:

  1. 設置區域設置的相應的一個爲UTF-16/UTF-32

  2. 使用isspace() F。或空白檢測。

  3. 對於your_atof()轉換是一個類似的方式。

  4. 恢復本地。

+0

不要忘記,UTF-16和UTF-32都有大端和小端的變體,你可能會關心。 – JohnH 2014-09-29 20:29:30

+0

@JohnH:這如何與UTF-32相關? – mafso 2014-09-29 20:33:46

+1

@mafso大/小端變體確實適用於UTF-16和UTF-32。在_byte_級別,2或4字節的順序非常不符合軟件的字節順序。這可以使用各種字節重新排序功能來糾正。使用Unicode代碼點> = 0x10000,編碼爲UTF-16時,2個UTF-16代理的順序有時會以大或小的順序排列。其中只有一個是正確的(忘記哪個)。當使用錯誤的時候,它應該標記爲編碼錯誤,雖然有些系統是寬鬆的(非投訴)。 – chux 2014-09-29 21:01:22

0

這個問題可能有點老了,但我想談談與char16_tchar32_t支持實現你的功能。

最簡單的方法是使用char32_t類型(稱之爲strtoull_c32)編寫您的strtoull函數。這使解析unicode更容易,因爲UTF-32中的每個字符佔用4個字節。然後通過將UTF-8UTF-16編碼內部轉換爲UTF-32並將它們傳遞給strtoull_c32來實現strtoull_c16strtoull_c8

我真的沒有看過C11標準庫中的Unicode設施,但如果他們沒有提供將這些類型轉換爲UTF-32的合適方法,那麼您可以使用第三方庫爲您進行轉換。

ICU,這是由IBM啓動,然後由Unicode聯盟採用。這是一個功能豐富且穩定的庫,已經存在了很長時間。

我最近爲C89創建了一個UTF庫(UTFX),您也可以使用它。這是非常簡單和輕量級的,單元測試和記錄。您可以放棄,或者使用它來了解更多關於UTF轉換如何工作的信息。