2014-10-19 2 views
5

Моя цель состоит в том, чтобы перебирать строки текста символа Юникода по характеру, но приведенный ниже код итерация код единицы вместо кодовых точек, даже если я использую next32PostInc(), который, как предполагается, итерацию код Ориентир:ICU итерация кодовых

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; 
} 

код выше производит правильный вывод, который является китайским иероглифом 斯 но 3 итераций происходят для этого одного символа, а не только 1. Может ли кто-нибудь объяснить, что я делаю неправильно?

Вкратце, Я просто хочу пройти символы в цикле и с удовольствием использовать те или иные классы итераций ICU.

все еще пытается решить эту проблему ...

Я также наблюдал некоторые плохое поведение, используя UnicodeString, как показано ниже. Я использую 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 

}

Я использую VC++ 2013.

+0

Передача 'обугленного *' само по себе в 'UnicodeString' конструктор подчиняется умолчанию платформы кодовая. '' - '' подчиняется кодировке вашего исходного кода, но '' 斯 "' не может быть представлен в 8 бит. Является ли ваш исходный код UTF-8? Это может объяснить ваши плохие преобразования. Вам нужно будет использовать конструктор 'UnicodeString', который позволяет указать исходные данные UTF-8, чтобы он правильно преобразовывался. –

+0

Да, мой источник находится в формате UTF-8. –

ответ

6

Поскольку исходные данные в UTF-8, вы должны сказать, что UnicodeString. Его конструктор имеет параметр codepage для этой цели, но вы устанавливаете его в пустую строку:

UnicodeString testString(testChars, ""); 

Это говорит UnicodeString выполнить инвариантное преобразования, которое не то, что вы хотите. В итоге вы получаете 3 кодовых пункта (U + 00E6 U + 0096 U + 00AF) вместо 1 кодового пункта (U + 65AF), поэтому ваша петля повторяется три раза.

Вы должны изменить вызов конструктора, чтобы UnicodeString знать данные UTF-8, например:

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

Вау, спасибо Реми, это было то, о чем я даже не подумал, я собираюсь экспериментировать с вашим предложением, чтобы, надеюсь, решить мою проблему до принятия. –