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?
Ответы
Ответ 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, возможно, это кому-то полезно.