2014-10-19 24 views
5

Moim celem jest iteracyjne ciągi znaków tekstu Unicode po znaku, ale poniżej kod jest iteracja Kod Jednostki zamiast punktów kodowych chociaż używam next32PostInc() która ma iteracji kodu punkty:ICU iterate codepoints

void iterate_codepoints(UCharCharacterIterator &it, std::string &str) { 
    UChar32 c; 
    while (it.hasNext()) { 
     c = it.next32PostInc(); 
     str += c; 
    } 
} 

void my_test() { 
    const char testChars[] = "\xE6\x96\xAF"; // Chinese character 斯 in UTF-8 
    UnicodeString testString(testChars, ""); 
    const UChar *testText = testString.getTerminatedBuffer(); 

    UCharCharacterIterator iter(testText, u_strlen(testText)); 

    std::string str; 
    iterate_codepoints(iter, str); 
    std::cout << str; // outputs 斯 in UTF-8 format 
} 


int main() { 
    my_test(); 
    return 0; 
} 

powyższy kod daje poprawny wynik, który jest chiński znak 斯 ale 3 iteracje są występujące w tym jeden znak, a nie tylko 1. Czy ktoś wyjaśnić, co robię źle?

W skrócie: Po prostu chcę przechodzić znaki w pętli i chętnie wykorzystam tę klasę iteracji ICU.

wciąż próbuje rozwiązać ten ...

zaobserwowałem również złe zachowanie przy użyciu UnicodeString jak widać poniżej. Używam VC++ 2013.

void test_02() { 
    // UnicodeString us = "abc 123 ñ";  // results in good UTF-8: 61 62 63 20 31 32 33 20 c3 b1 
    // UnicodeString us = "斯";    // results in bad UTF-8: 3f 
    // UnicodeString us = "abc 123 ñ 斯"; // results in bad UTF-8: 61 62 63 20 31 32 33 20 c3 b1 20 3f (only the last part '3f' is corrupt) 
    // UnicodeString us = "\xE6\x96\xAF"; // results in bad UTF-8: 00 55 24 04 c4 00 24 
    // UnicodeString us = "\x61";   // results in good UTF-8: 61 
    // UnicodeString us = "\x61\x62\x63"; // results in good UTF-8: 61 62 63 
    // UnicodeString us = "\xC3\xB1";  // results in bad UTF-8: c3 83 c2 b1 
    UnicodeString us = "ñ";     // results in good UTF-8: c3 b1  
    std::string cs; 
    us.toUTF8String(cs); 
    std::cout << cs; // output result to file, i.e.: main >output.txt 

}

Używam VC++ 2013.

+0

Podjęcie 'char *' sama do 'konstruktora UnicodeString' podlega domyślnie platformy strona kodowa. '' ñ "' jest zależne od zestawu znaków twojego kodu źródłowego, ale '' 斯 "' nie może być reprezentowane w 8bit. Czy twój kod źródłowy to UTF-8? To może wyjaśnić twoje złe nawrócenia. Konieczne byłoby użycie konstruktora 'UnicodeString', który pozwala określić dane źródłowe na UTF-8, aby został poprawnie skonwertowany. –

+0

Tak, moje źródło ma format UTF-8. –

Odpowiedz

6

Ponieważ dane źródłowe jest UTF-8, trzeba powiedzieć, że do UnicodeString. Jej konstruktor ma parametr codepage do tego celu, ale jest ustawienie go na pusty ciąg znaków:

UnicodeString testString(testChars, ""); 

To mówi UnicodeString wykonać niezmienny konwersji, który nie jest to, co chcesz. W efekcie otrzymujesz 3 współrzędne kodowe (U + 00E6 U + 0096 U + 00AF) zamiast 1 punktu kodowego (U + 65AF), dlatego twoja pętla wykonuje trzykrotne iteracje.

Musisz zmienić swoje wezwanie konstruktora pozwolić UnicodeString wiedzieć danych jest UTF-8, np:

UnicodeString testString(testChars, "utf-8"); 
+0

Wow, dziękuję Remy, to było coś, o czym nawet nie myślałem, zamierzam poeksperymentować z twoją sugestią, aby, mam nadzieję, rozwiązać problem przed zaakceptowaniem. –