Подтвердить что ты не робот

Xcode UTF-8 литералы

Предположим, что у меня есть символ MUSICAL SYMBOL G CLEF: ** 𝄞 **, который я хочу иметь в строковом литерале в исходном файле Objective-C.

OS X Character Viewer говорит, что CLEF UTF8 F0 9D 84 9E и Unicode 1D11E(D834+DD1E) в своих терминах.

После некоторого futzing around и используя t он ICU UNICODE Демонстрация, я получил следующий код для работы:

NSString *[email protected]"\U0001d11e";
NSString *uni2=[[NSString alloc] initWithUTF8String:"\xF0\x9D\x84\x9E"];
NSString *[email protected]"𝄞";
NSLog(@"unicode: %@ and %@ and %@",uni, uni2, uni3);

Мои вопросы:

  • Можно ли упорядочить способ, которым я занимаюсь литературой UTF-8? Это кажется мне клонированным.
  • Является ли часть @"\U0001d11e UTF-32?
  • Почему на самом деле работает резка и вставка CLEF из программы просмотра персонажей? Я думал, что файлы Objective-C должны быть UTF-8?
4b9b3361

Ответ 1

  • Я бы предпочел, чтобы вы это сделали в uni3, но, к сожалению, не рекомендуется. В противном случае я предпочел бы метод uni в uni2. Другим вариантом будет [NSString stringWithFormat:@"%C", 0x1d11e].
  • Это "универсальное имя символа", введенное в C99 (раздел 6.4.3) и импортированное в Objective-C с OS X 10.5. Технически это не обязательно для вас UTF-8 (это до компилятора), но на практике UTF-8, вероятно, вы получите.
  • Кодирование файла исходного кода, вероятно, является UTF-8, что соответствует ожиданиям, поэтому все происходит. Также возможно, что исходный файл UTF-16 или UTF-32, и компилятор делает правильную вещь при компиляции. Тем не менее, Apple не рекомендует это.

Ответ 2

Ответы на ваши вопросы (тот же порядок):

  • Зачем выбирать? xcode использует C99 в настройке по умолчанию. См. спецификацию проекта C0X 6.4.3 для универсальных имен символов. См. Ниже.

  • Более технически, @"\U0001d11e - это 32-разрядная кодовая точка Unicode для этого символа в набор символов ISO 10646.

  • Я бы не стал рассчитывать на это поведение. Вы должны абсолютно, уверенно, без сомнений, иметь все символы в исходном файле 7 бит ASCII. Для строковых литералов используйте кодировку или, предпочтительно, подходящий внешний ресурс, способный обрабатывать двоичные данные.

Универсальные имена символов (из WG14/N1256 Проект C0X, который CLANG следует довольно хорошо):

Универсальные имена символов могут использоваться в идентификаторах, символьных константах, и строковые литералы для обозначения символы, которые не входят в основную набор символов.

Универсальный имя символа \Unnnnnnnn обозначает характер, чей восьмизначный короткий идентификатор (как указано в ISO/IEC 10646) nnnnnnnn). Аналогично, имя универсального символа \unnnn обозначает персонажа, чей четырехзначный короткий идентификатор - nnnn (и чей восьмизначный короткий идентификатор 0000nnnn).

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

char *utf8CStr = 
   "May all your CLEF \xF0\x9D\x84\x9E be left like this: \U0001d11e";
NSString *uni4=[[NSString alloc] initWithUTF8String:utf8CStr];

Форма \Unnnnnnnn позволяет вам выбрать любую кодовую точку Юникода, и это то же значение, что и поле "Юникод" в левом нижнем углу средства просмотра символов. Прямой ввод \Unnnnnnnn в исходном файле C99 обрабатывается соответствующим компилятором. Обратите внимание, что существует только два варианта: \unnnn, который представляет собой смещение на 256 символов для кодовой страницы по умолчанию или \Unnnnnnnn, который является полным 32-битным символом любой кодовой точки Юникода. Вам нужно наложить левый на 0, если вы не используете все 4 или все 8 цифр или \u или\U.

Более интересна форма \xF0\x9D\x84\x9E в том же строковом литерале. Это вставляет необработанную кодировку UTF-8 того же символа. После этого передается метод initWithUTF8String, но буквальный и закодированный литерал заканчиваются кодированным UTF-8.

Это может быть, возможно, является нарушением 130 раздела 5.1.1.2, чтобы использовать необработанные байты таким образом. Учитывая, что исходная строка UTF-8 будет закодирована аналогично, я думаю, что все в порядке.

Ответ 3

  • Вы также можете написать символ clef в строковом литерале:

    NSString *uni2=[[NSString alloc] initWithUTF8String:"𝄞"];
    
  • \U0001d11e соответствует кодовой точке юникода для символа ключа G. Форма символа UTF-32 такая же, как и его кодовая точка, поэтому вы можете думать о ней как о UTF-32, если хотите. Здесь ссылка на таблицы unicode для музыкальных символов.

  • Возможно, ваш файл UTF-8. G clef является допустимым символом UTF8 - проверьте вывод hexdump для вашего файла:

    00  4e 53 53 74 72 69 6e 67  20 2a 75 6e 69 33 3d 40  |NSString *[email protected]|
    10  22 f0 9d 84 9e 22 3b 0a  20 20 4e 53 4c 6f 67 28  |"....";.  NSLog(|
    

    Как вы можете видеть, правильное представление UTF-8 этого символа находится в файле справа, где вы ожидаете его. Вероятно, безопаснее использовать один из ваших других методов и попытаться сохранить исходный файл в диапазоне ASCII.

Ответ 4

Я создал некоторые классы утилиты для простой конвертации между кодами Unicode, байтовыми последовательностями UTF-8 и NSString. Вы можете найти код в Github, возможно, это кому-то полезно.