С C ++ 11, мне все еще нужна нестандартная библиотека для работы со строками для текста Unicode? - PullRequest
11 голосов
/ 28 февраля 2012

Я заметил, что метод длины std :: string возвращает длину в байтах, и тот же метод в std :: u16string возвращает количество 2-байтовых последовательностей.

Я также заметил, чтокогда символ или кодовая точка находятся за пределами BMP, длина возвращает 4, а не 2.

Кроме того, escape-последовательность Unicode ограничена \ unnnn, поэтому любая кодовая точка выше U + FFFF не может быть вставленаescape escape.

Другими словами, кажется, что нет поддержки суррогатных пар или кодовых точек вне BMP.

Учитывая это, является принятой или рекомендуемой практикой использованиянестандартная библиотека для работы со строками, которая понимает UTF-8, UTF-16, суррогатные пары и т. д.1012 * Пример:

/*
* Example with the Unicode code points U+0041, U+4061, U+10196 and U+10197
*/

#include <iostream>
#include <string>

int main(int argc, char* argv[])
{
    std::string example1 = u8"A䁡??";
    std::u16string example2 = u"A䁡??";

    std::cout << "Escape Example: " << "\u0041\u4061\u10196\u10197" << "\n";
    std::cout << "Example: " << example1 << "\n";
    std::cout << "std::string Example length: " << example1.length() << "\n";
    std::cout << "std::u16string Example length: " << example2.length() << "\n";

    return 0;
}

Вот результат, который я получаю при компиляции с GCC 4.7:

Escape Example: A䁡မ6မ7
Example: A䁡??
std::string Example length: 12
std::u16string Example length: 6

Ответы [ 3 ]

9 голосов
/ 28 февраля 2012

std::basic_string ориентирован на единицу кода, а не на символ.Если вам нужно работать с кодовыми точками, вы можете преобразовать их в char32_t, но в стандарте пока нет ничего для более продвинутой функциональности Unicode.

Также вы можете использовать escape-последовательность \UNNNNNNNN для кодовых точек не-BMP,в дополнение к их непосредственному вводу (при условии, что вы используете исходную кодировку, которая их поддерживает).

В зависимости от ваших потребностей это может быть вся необходимая поддержка Юникода.Многим программам не нужно делать больше, чем просто манипулировать строками, например, те, которые можно легко выполнить непосредственно с единицами кода.Для чуть более высокого уровня потребностей вы можете преобразовать единицы кода в точки кода и работать над ними.Для нужд более высокого уровня, таких как работа с кластерами графем, потребуется дополнительная поддержка.

Я бы сказал, что это означает, что в стандарте есть адекватная поддержка для представления данных Unicode и выполнения основных манипуляций.Любая сторонняя библиотека, используемая для более высокого уровня функциональности, должна основываться на стандартной библиотеке.Со временем стандарт, скорее всего, будет включать в себя и более функциональные возможности более высокого уровня.

7 голосов
/ 28 февраля 2012

С риском преждевременного суждения, мне кажется, что язык, используемый в стандартах, несколько двусмыслен (хотя окончательный вывод ясен, см. В конце):

В описании литералов char16_t (т. Е. u"...", как в вашем примере), размер литерала определяется как:

Размер строкового литерала char16_t представляет собой общее количество escape-последовательностей, имен универсальных символов и других символов, плюс один для каждого символа, требующего суррогатную пару, плюс один для завершающего u '\ 0'.

И сноска уточняет:

[Примечание. Размер строкового литерала char16_t - это количество единиц кода, а не количество символов. —Конечная записка]

Это подразумевает определение символа и кодовой единицы . Суррогатная пара - один символ , но две кодовые единицы .

Однако описание length() метода std::basic_string (из которого std::u16string получено) утверждает:

Возвращает количество символов в строке, то есть std :: distance (begin (), end ()). Это так же, как размер ().

Как видно, в описании length() используется слово символ для обозначения того, что определение char16_t называет кодовой единицей .

Тем не менее, вывод всего этого таков: Длина определяется как единицы кода, следовательно, ваш компилятор соответствует стандарту, и будет сохраняться потребность в специальных библиотеках для обеспечения правильного подсчета символов .

Я использовал ссылки ниже:

  • Для определения размера литералов char16_t: Здесь
  • Для описания std::basic_string::length(): Здесь
0 голосов
/ 03 марта 2012

Учитывая это, является ли принятой или рекомендуемой практикой использование нестандартной библиотеки для работы со строками, которая понимает UTF-8, UTF-16, суррогатные пары и т. Д.?

Трудно говорить о рекомендуемой практике для языкового стандарта, который был создан несколько месяцев назад и еще не полностью реализован, но в целом я бы согласился: возможности языка и Unicode в C ++ 11 по-прежнему безнадежно неадекватны (хотя они, очевидно, стали намного лучше), и для серьезной работы вы должны бросить их и использовать вместо них ICU или Boost.Locale .

Добавление строк Unicode и функций преобразования в C ++ 11 - это первый шаг к реальной поддержке Unicode; время покажет, окажутся ли они полезными или будут забыты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...