2011-12-21 3 views
-4

Вот вопрос новичка на Unicode. Я использую Embarcadero C++ Builder 2009, где они якобы изменили строки по умолчанию, чтобы использовать Unicode.Вопросы преобразования Юникода

  • Я печатаю различные символы в своем исходном редакторе, которые не являются частью стандартного «7-битного ASCII».
  • Моя программа использует строковый тип C++ Builder для ввода пользовательского ввода.
  • Я также добавляю ввод вручную, установив значение в wchar_t.

Казалось бы, существуют конфликты в интерпретации символов. Иногда я получаю символ, например, код 0x00C7 ('Ç'), но иногда тот же символ кодируется как 0xFFC7, например, в редакторе исходного кода. Насколько я понимаю, первый - это правильный Юникод, последний - «что-то еще». Может кто-то подтвердить это?

Интересно, откуда такое кодирование «что-то еще» и как избавиться от него?

EDIT: Дальнейшие исследования: кажется, что одно место, где ** появляется 0xFF кодирование, когда я делаю что-то вроде этого:

string str = ...; 
wchar_t wch = (wchar_t)str[i]; 

тот же результат независимо от того, если это станд :: строка или VCL Строка , Есть wchar_t не то же самое, что и Unicode?

+0

Если utf-8 используется для кодирования, то каждый символ юникода может занимать 1, 2 или 4 байта или более. Насколько я понимаю, wchar_t всегда имеет размер 2 байта для каждого символа, что может быть проблемой. – greatwolf

+0

@ VictorT. Тогда какой тип характера я должен использовать? Я думаю, что простой ** char ** - 8 бит. – Lundin

+0

Вы должны использовать 'wstring' не' string' для строк с широкими символами (Unicode.) Новый тип 'String' использует широкие символы, хранящиеся как UTF-16 (не беспокойтесь о других кодировках, таких как UTF8 на данный момент.) Ваш код 'string str = ...;' потеряет данные как есть. Тогда вам не понадобится бросок во второй строке. –

ответ

4

Я предполагаю, что проблема заключается в том, что в вашем компиляторе подписан протокол char (стандарт позволяет либо подписаться, либо без знака, он определен или определен конкретным). Таким образом, всякий раз, когда вы конвертируете символы, у которых бит 7 установлен в 1 (от 0x80 до 0xFF), в любой более крупный целочисленный тип, он рассматривается как отрицательное значение, и он получает расширенный знак для сохранения отрицательного значения или, другими словами, этот бит 7 копируется в бит 8, бит 9 и т. д. во все старшие разряды большего целочисленного типа. Таким образом, 0xC7 может превратиться в 0xFFC7 и 0xFFFFFFC7. Чтобы этого не произошло, сначала нанесите chars на номер unsigned chars.

+0

Я тоже подозревал об этом, поэтому я тщательно использую свой собственный тип uint8 для символов. Однако, я полагаю, ** char ** может быть использован внутренне каким-то строковым типом или объектом библиотеки. – Lundin

+0

«Строка» C++ обычно использует простой символ «char» для каждого строкового элемента. Если 'char' подписан, то есть' str [некоторый индекс] 'и поэтому подлежит расширению знака всякий раз, когда он используется в выражениях (включая присвоения). –

+0

Я просто понял, что литералы символов в исходном коде, скорее всего, имеют тип ** char **, или, вернее, int, усеченный на char. Они действительно будут интерпретироваться как отрицательные числа. Это объясняет некоторые странности, но не все. – Lundin

1

Широкий характер типа w_type определяется реализацией и не должен соответствовать понятию символа Юникода. Проверьте description of w_type in the Unicode Standard.

Если «Ç» изменен на 0xFFC7, он очень похож на расширение знака, то есть символ внутренне сохраняется в виде байта 0xC7, который затем принимается как подписанное 8-битовое целое и преобразуется в 16-разрядное целое число с расширение знака.

+0

Есть ли какие-либо гарантии для подписанности wchar_t, всегда ли это unsigned/signed? Потому что, похоже, wchar_t может быть виновником. – Lundin

+2

Подпись 'wchar_t' не является преступником. Преступником является подпись 'char'. –

+0

@Alex Достаточно честный, но из любопытства, что стандарт говорит о подписке wchar_t? – Lundin

Смежные вопросы