2011-10-11 48 views
2

我編寫了一個擴展isalnum以識別UTF-8編碼變音符號的函數。擴展'isalnum'以識別UTF-8變音符號

有沒有更好的方法來解決這個問題?

的代碼如下:

bool isalnumlaut(const char character) { 
    int cr = (int) (unsigned char) character; 
    if (isalnum(character) 
      || cr == 195 // UTF-8 
      || cr == 132 // Ä 
      || cr == 164 // ä 
      || cr == 150 // Ö 
      || cr == 182 // ö 
      || cr == 156 // Ü 
      || cr == 188 // ü 
      || cr == 159 // ß 
    ) { 
     return true; 
    } else { 
     return false; 
    } 
} 

編輯:

我測試,現在我的解決方案几次,似乎做雖然我的目的的工作。任何強烈的反對意見?

+1

UTF-8是一種Unicode編碼。 Unicode中有幾十個變音符號。尤其是,Unicode有一個「獨立的」unlaut,U + 0308。它爲前面的字符添加變音符號。即U + 0041 U + 0308是Ä。另外,爲什麼在該列表中?這沒有變音。 – MSalters

+0

@ MSalters我認爲你的意思是結合,而不是「獨立」。 (正式的,這是一個「diaeresis」,而不是一個「變音符號」 - 「Umlaut」這個詞是指它在德語中對發音的影響。)Unicode既包含結合diaeresis也包含間隔diaeresis(U + 00A8),加上約80個「預先組合」的字符,使用分音功能。 ('grep DIAERESIS UnicodeData.txt'的結果。) –

+0

@James:當然。但考慮到這個問題的措辭,我沒有使用正式的術語。順便說一下,你也可能在這個計數中包含了「低於」(U + 0324),以及預知的用途,例如我知道的MS U + 1E72 – MSalters

回答

5

你的代碼不會做你所聲稱的。

Ä的utf-8表示法是兩個字節 - 0xC3,0x84。在utf-8中,值大於0x7F的單個字節沒有意義。


一些一般性的建議:

  • Unicode是大的。考慮使用已經處理了所見問題的庫,如ICU

  • 它沒有通常意義的功能單一代碼單元碼點上運行。具有在任一代碼點範圍或單個字形(關於這些術語的定義,請參見here)上運行的函數更有意義。

  • 對於與通用字符集一樣大的字符集,您的字母數字概念可能會被低估;你想把西裏爾字母中的字符看作字母數字嗎? Unicode的字母概念可能不符合你的要求 - 特別是如果你沒有考慮到它的話。

+0

Unicode實際上已經竭盡全力指定每個字符的字母數字屬性。尤其是,Unicode字符類別'Alphabetic'和'Numeric_Type'(來自UAX#44)將合理地覆蓋'isalnum()'。 – MSalters

+0

@ MSalters:好點。我已經澄清了語言,以明確它是OP對字母數字的理解可能會被低估。 –

1

我不是100%肯定,但在<locale>的C++ std::isalnum幾乎可以肯定,承認區域特定的附加字符:http://www.cplusplus.com/reference/std/locale/isalnum/

+1

'std :: isalnum'函數不適用於像UTF-8這樣的多字節編碼。不管區域設置如何。只看一個'char'是不夠的。你必須查看整個字符(這可能需要四個UTF-8中的'char')。 –

+0

那個不適用於MBCS,如UTF-8。 – MSalters

+0

即使4個字符可能不夠,這取決於他想如何處理組合字符。 –

1

這是不可能與您定義的接口,因爲UTF-8是一種 多字節編碼;單個字符需要多個char至 來表示它。 (我有代碼用於確定UTF-8是否是一組指定的在我的圖書館的字符的 構件,但 字符由一對迭代的指定,而不是一個單一char。)