Многобайтовая кодировка UTF-8 в массивах на C++

У меня возникли проблемы с работой с 3-байтовыми символами Unicode UTF-8 в массивах. Когда они находятся в массивах символов, я получаю предупреждения о многосимвольной символьной константе и неявном преобразовании констант, но когда я использую массивы wchar_t, wcout вообще ничего не возвращает. Из-за характера проекта это должен быть массив, а не строка. Ниже приведен пример того, что я пытался сделать.

#include <iostream>
#include <string>
using namespace std;
int main()
{
    wchar_t testing[40];
    testing[0] = L'\u0B95';
    testing[1] = L'\u0BA3';
    testing[2] = L'\u0B82';
    testing[3] = L'\0';
    wcout << testing[0] << endl;
    return 0;
}

Какие-либо предложения? Я работаю с OS X.


person user1850145    schedule 24.11.2012    source источник
comment
Когда вы сохраняете их в массивах char, такая кодовая точка займет три char. Многосимвольные символьные константы — совсем другое дело.   -  person Daniel Fischer    schedule 25.11.2012
comment
wstring не являются utf8 (они не обязательно UTF-16 или UCS4). Вы не знаете, какая у них кодировка, поэтому запись в них фиксированных значений вызывает проблемы.   -  person BatchyX    schedule 25.11.2012
comment
У них нет какой-либо кодировки. Это всего лишь несколько байтов.   -  person Lightness Races in Orbit    schedule 25.11.2012


Ответы (1)


Поскольку '\u0B95' требует 3 байта, он считается многосимвольным литералом. Многосимвольный литерал имеет тип int и значение, определяемое реализацией. (На самом деле, я не думаю, что gcc подходит для этого)

Помещение префикса L перед литералом приводит к тому, что он имеет тип wchar_t и имеет значение, определенное реализацией (он сопоставляется со значением в наборе расширенных символов выполнения, который является определяемым реализацией надмножеством базового набор расширенных символов выполнения).

Стандарт C++11 предоставляет нам еще несколько типов и литералов, поддерживающих Unicode. Дополнительными типами являются char16_t и char32_t, значениями которых являются кодовые точки Unicode, представляющие символ. Они аналогичны UTF-16 и UTF-32 соответственно.

Поскольку вам нужны символьные литералы для хранения символов из базовой многоязычной плоскости, вам понадобится литерал char16_t. Это может быть записано, например, как u'\u0B95'. Поэтому вы можете написать свой код следующим образом, без предупреждений или ошибок:

char16_t testing[40];
testing[0] = u'\u0B95';
testing[1] = u'\u0BA3';
testing[2] = u'\u0B82';
testing[3] = u'\0';

К сожалению, библиотека ввода/вывода плохо работает с этими новыми типами.

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

const char* testing = u8"\u0B95\u0BA3\u0B82";

Это будет кодировать символы как UTF-8.

person Joseph Mansfield    schedule 24.11.2012