Как перебирать символы Юникода в C ++? - PullRequest
6 голосов
/ 28 сентября 2011

Я знаю, что для получения символа Unicode в C ++ я могу сделать:

std::wstring str = L"\u4FF0";

Однако, что если я захочу получить все символы в диапазоне от 4FF0 до 5FF0? Можно ли динамически создавать символы юникода? Я имею в виду что-то вроде этого псевдокода:

for (int i = 20464; i < 24560; i++ { // From 4FF0 to 5FF0
    std::wstring str = L"\u" + hexa(i); // build the unicode character
    // do something with str
}

Как бы я это сделал в C ++?

Ответы [ 3 ]

10 голосов
/ 28 сентября 2011

Тип wchar_t, содержащийся внутри wstring, является целочисленным типом, поэтому вы можете использовать его напрямую:

for (wchar_t c = 0x4ff0;  c <= 0x5ff0;  ++c) {
    std::wstring str(1, c);
    // do something with str
}

Будьте осторожны, пытаясь сделать это с символами выше 0xffff, поскольку в зависимости от платформы (например, Windows) они не поместятся в wchar_t.

Если, например, вы хотите увидеть блок смайликов в строке, вы можете создать суррогатные пары:

std::wstring str;
for (int c = 0x1f600; c <= 0x1f64f; ++c) {
    if (c <= 0xffff || sizeof(wchar_t) > 2)
        str.append(1, (wchar_t)c);
    else {
        str.append(1, (wchar_t)(0xd800 | ((c - 0x10000) >> 10)));
        str.append(1, (wchar_t)(0xdc00 | ((c - 0x10000) & 0x3ff)));
    }
}
4 голосов
/ 28 сентября 2011

Вы не можете увеличивать символы Юникода, как если бы это был массив, некоторые символы создаются из нескольких символов (UTF-8) и нескольких символов WCHAR (UTF-16) из-за диакритических знаков и т. Д. Если вы Если вы действительно серьезно относитесь к этому, вы должны использовать такой API, как UniScribe или ICU.

Некоторые ресурсы для чтения:

http://en.wikipedia.org/wiki/UTF-16/UCS-2

http://en.wikipedia.org/wiki/Precomposed_character

http://en.wikipedia.org/wiki/Combining_character

http://scripts.sil.org/cms/scripts/page.php?item_id=UnicodeNames#4d2aa980

http://en.wikipedia.org/wiki/Unicode_equivalence

http://msdn.microsoft.com/en-us/library/dd374126.aspx

2 голосов
/ 28 сентября 2011

Как насчет:

for (std::wstring::value_type i(0x4ff0); i <= 0x5ff0; ++i)
{
    std::wstring str(1, i);
}

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

Кроме того, учитывая платформу, над которой вы работаете *Единица символа 1006 * может иметь ширину 2, 4 или N байтов, так что будьте преднамеренными относительно того, как вы ее используете.

...