Преобразование многобайтового массива символов в массив QChar

#qt #multibyte #qchar

#qt #многобайтовый #qchar

Вопрос:

У меня есть два буфера (примерных размеров):

 char c[512];
QChar q[256];
  

Предполагается, что ‘c’ содержит многобайтовую символьную строку (UTF-8). Мне нужно преобразовать его в последовательность QChar и поместить ее в ‘q’.
Я думаю, хорошим примером того, что мне нужно, могла бы быть функция MultiByteToWideChar.

ВАЖНО: эта операция не должна включать никаких явных или неявных выделений памяти, за исключением, возможно, дополнительных выделений в стеке. Пожалуйста, не отвечайте, если вы не уверены, что означает вышесказанное.

Комментарии:

1. Добро пожаловать в StackOverflow! Ваш вопрос вызывает у меня вопрос (и, я думаю, у других тоже): «Почему нет выделения?» Это серьезно ограничивает использование любого Qt из-за использования Qt PIMPL в большинстве классов.

2. Кроме того, знаете ли вы кодек вашей многобайтовой строки? (Я думаю, это так из-за фиксированных размеров массива в соотношении 2: 1)

3. Привет, Мартин. Логичный вопрос. Речь здесь идет о фрагментации памяти и использовании при операциях с высокой частотой кадров. Поэтому PIMPL в данном конкретном случае является немного обременительным. Что касается кодеков — Qt справляется с этим вопросом (например, при создании QString из QByteArray или const char *) Я не хочу ничего другого. Просто внешние заполнители. Windows API предоставляет такие функции, которые преобразуют широкий символ в многобайтовые строки и наоборот. Почему Qt этого не делает? (Или так ли это?)

4. Позволю себе не согласиться — Qt интерпретирует const char * как UTF-8, за исключением случаев, когда вы явно указываете иное. Ваш массив символов может содержать 512 символов. В UTF-8 это будет до 512 QChars.

5. Под «многобайтовой» вы, вероятно, имеете в виду текущую кодовую страницу ansi в Windows, не так ли? (большинство из них на самом деле являются однобайтовыми :)) Похоже, что не все знают этот термин, возможно, было бы лучше уточнить его в вопросе.

Ответ №1:

QChar содержит ushort единственный элемент as, поэтому его размер sizeof(ushort) .

В QString контексте он представляет «символы» UTF-16 (кодовые точки).

Итак, здесь все дело в кодировании.

Если вы знаете, что ваши данные в char const * формате UTF-16 имеют тот же порядок байтов, что и в вашей системе, просто скопируйте их:

 memcpy(q, c, 512);
  

Если вы хотите инициализировать a QString своими const char * данными, вы могли бы просто интерпретировать его как UTF-16, используя QString::fromRawData() :

 QString strFromData = QString::fromRawData(reinterpret_cast<QChar*>(c), 256);
// where 256 is sizeof(c) * sizeof(char) / sizeof(QChar)
  

Тогда вам даже не нужен QChar q[256] массив.

Если вы знаете, что ваши данные имеют формат UTF-8, вам следует использовать QString::fromUtf8() , а затем просто получить доступ к его внутренней памяти с помощью QString::constData() .

Используя QString с UTF-8, я не знаю ни одного метода, полностью предотвращающего выделение кучи. Но упомянутый способ должен выделяться только дважды: один раз для PIMPL QString , один раз для строковых данных UTF-16.


Если ваши входные данные закодированы как UTF-8 , ответ Нет: вы не можете преобразовать их с помощью Qt.

Доказательство: просмотр исходного кода qtbase/src/corelib/codecs/qutfcodec.cpp мы видим, что все функции для кодирования / декодирования создают новые QString / QByteArray экземпляры. Ни одна функция не работает с двумя массивами, как в вашем вопросе.

Комментарии:

1. Спасибо, Мартин. Это было бы просто. Как насчет UTF-8? Я думаю, хорошим примером того, что мне нужно, может быть MultiByteToWideChar ( learn.microsoft.com/en-us/windows/desktop/api/stringapiset /… )

2. Спасибо, Мартин. Я предполагаю, что это означает «нет, нет никакого способа сделать это».

3. Даже при использовании MultiByteToWideChar вам необходимо указать кодировку.

4. Я считаю, что либо ваши ограничения слишком жесткие, либо Qt — неподходящий инструмент для этой работы. Вероятно, вы могли бы выполнить преобразование с помощью Qt, не выделяя строки в куче, например, с помощью QTextStream , но вам понадобится QTextCodec , и это будет создано в куче снова.