числовое значение символа юникода в цели c - PullRequest
0 голосов
/ 14 ноября 2011

возможно ли получить числовое значение из символа юникода в target-c?

@ "A" - 0041, @ "➜" - 279C, @ "Ω" - 03A9, @ "@" - 091D ...?

Ответы [ 2 ]

6 голосов
/ 22 мая 2013

ОК, так что, возможно, стоит указать несколько вещей в отдельном ответе здесь. Во-первых, термин «характер» неоднозначен, поэтому мы должны выбрать более подходящий термин в зависимости от того, что мы имеем в виду. (Подробнее см. Символы и кластеры графем в документации для разработчиков Apple, а также веб-сайт Unicode .)

Если вы запрашиваете кодовую единицу UTF-16 , тогда вы можете использовать

unichar ch = [myString characterAtIndex:ndx];

Обратите внимание, что это только эквивалентно кодовой точке Unicode в случае, когда кодовая точка находится в Базовой многоязычной плоскости (т.е. она меньше, чем U + FFFF).

Если вы запрашиваете код Unicode с кодом , то вам следует знать, что UTF-16 поддерживает символы вне BMP (то есть U + 10000 и выше), используя суррогатных пар . Таким образом, для любой кодовой точки выше U + 10000 будет две кодовых единицы UTF-16. Чтобы обнаружить этот случай, вам нужно сделать что-то вроде

uint32_t codepoint = [myString characterAtIndex:ndx];

if ((codepoint & 0xfc00) == 0xd800) {
  unichar ch2 = [myString characterAtIndex:ndx + 1];

  codepoint = (((codepoint & 0x3ff) << 10) | (ch2 & 0x3ff)) + 0x10000;
}

Обратите внимание, что в производственном коде вы также должны проверить и справиться со случаем, когда суррогатная пара каким-то образом была усечена.

Важно , ни кодовые единицы UTF-16, ни кодовые точки Unicode не обязательно соответствуют чему-либо, что и конечный пользователь будет рассматривать как «символ» (консорциум Unicode обычно именует это как графем кластер , чтобы отличить его от других возможных значений «характер»). Есть много примеров, но наиболее простым для понимания является, вероятно, сочетание диакритических знаков. Например, символ «Ä» может быть представлен как кодовая точка Unicode U + 00C4 или как пара кодовых точек U + 0041 U + 0308.

Иногда люди (например, @DietrichEpp в комментариях к его ответу) утверждают, что вы можете справиться с этим путем преобразования в предварительно составленную форму перед обработкой вашей строки. Это что-то вроде красной сельди, потому что предварительно составленная форма имеет дело только с символами, которые имеют предварительно составленный эквивалент в Юникоде. например это не поможет со всеми комбинирующими метками; это не поможет с индийскими или арабскими шрифтами; с хангул джамосом это не поможет. Есть и много других случаев.

Если вы пытаетесь манипулировать кластерами графем (вещи, которые пользователь может воспринимать как «символы»), вам, вероятно, следует использовать методы NSString -rangeOfComposedCharacterSequencesForRange:, rangeOfComposedCharacterSequenceAtIndex: или функция CFString CFStringGetRangeOfComposedCharactersAtIndex. Очевидно, что вы не можете держать кластер графемы в целочисленной переменной, и он не имеет присущего ему числового значения; скорее это представлено строкой кодовых точек, которые представлены строкой кодовых единиц. Например:

NSRange gcRange = [myString rangeOfComposedCharacterSequenceAtIndex:ndx];
NSString *graphemeCluster = [myString substringWithRange:gcRange];

Обратите внимание, что graphemeCluster может быть произвольно длинной (!)

Даже в этом случае мы игнорировали влияние таких вопросов, как поддержка Unicode для двунаправленного текста. То есть порядок кодовых точек, представленных единицами кода в вашей строке NSString , в некоторых случаях может быть обратным тому, что вы могли ожидать. Худшие случаи связаны с такими вещами, как английский текст, встроенный в арабский или иврит; это поддерживается текстовой системой Cocoa, и поэтому вы действительно можете получить двунаправленные строки в вашем коде.

Подводя итог: Вообще говоря, следует избегать изучения NSString и CFString экземпляров unichar by unichar . Если это вообще возможно, используйте соответствующий метод NSString или функцию CFString. Если вы do обнаружите, что изучаете кодовые блоки UTF-16, сначала ознакомьтесь со стандартом Unicode (я рекомендую «Unicode Demystified», если вы не можете перечитать саму книгу Unicode), чтобы Вы можете избежать главных ловушек.

2 голосов
/ 14 ноября 2011

Какао-строки позволяют вам получить доступ к элементам UTF-16 с помощью -characterAtIndex:, поэтому следующий код преобразует строку в кодовую точку Unicode:

unsigned strToChar(NSString *str)
{
    unsigned c1, c2;
    c1 = [str characterAtIndex:0];
    if ((c1 & 0xfc00) == 0xd800) {
        c2 = [str characterAtIndex:1];
        return (((c1 & 0x3ff) << 10) | (c2 & 0x3ff)) + 0x10000;
    } else {
        return c1;
    }
}

Мне не известны какие-либо вспомогательные функцииза это.Вы можете использовать -characterAtIndex: самостоятельно, если вы в порядке с вашим кодом, который ужасно ломается, когда кто-то использует символы вне BMP;многие приложения в OS X ужасно ломаются таким образом.

Следующее должно отображаться как музыкальный "G clef", U + 1D11E, но если вы скопируете и вставите его в некоторые текстовые редакторы (TextMate),они позволят вам сделать странные вещи, такие как удаление половины символа, после чего ваш текстовый файл становится мусором.

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