xcode UTF-8 литералы - PullRequest
       33

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

21 голосов
/ 17 апреля 2011

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

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

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

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

Мои вопросы:

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

Ответы [ 4 ]

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

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

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

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

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

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

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

Универсальное имя символа \ Unnnnnnnn обозначает символ, чей восьмизначный короткий идентификатор (как указано в ИСО / МЭК 10646) равен nnnnnnnn) Точно так же имя универсального символа \ unnnn обозначает символ, чей четырехзначный короткий идентификатор nnnn (ичей восьмизначный короткий идентификатор 0000nnnn).

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

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

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

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

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

2 голосов
/ 17 апреля 2011
  1. Вы также можете написать символ ключа в строковом литерале:

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

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

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

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

0 голосов
/ 19 октября 2013

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...