Почему NSString и NSLog по-разному обрабатывают% C и% lc (и% S и% ls)? - PullRequest
5 голосов
/ 21 марта 2009

Apple Спецификаторы формата строки заявки на документы,

Спецификаторы формата, поддерживаемые методами форматирования NSString и функциями форматирования CFString, соответствуют спецификации IEEE printf ; … Вы также можете использовать эти спецификаторы формата с функцией NSLog.

Но, хотя спецификация printf определяет %C в качестве эквивалента для %lc и %S в качестве эквивалента для %ls, только %C и %S работают правильно с NSLog и +[NSString stringWithFormat:].

Например, рассмотрим следующий код:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[]) {
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    unichar str[3];
    str[0] = 63743;
    str[1] = 33;
    str[2] = (unichar)NULL;

    NSLog(@"NSLog");
    NSLog(@"%%S:  %S", str);
    NSLog(@"%%ls: %ls", str);

    NSLog(@"%%C:  %C", str[0]);
    NSLog(@"%%lc: %lc", str[0]);

    NSLog(@"\n");
    NSLog(@"+[NSString stringWithFormat:]");

    NSLog(@"%%S:  %@", [NSString stringWithFormat:@"%S", str]);
    NSLog(@"%%ls: %@", [NSString stringWithFormat:@"%ls", str]);

    NSLog(@"%%C:  %@", [NSString stringWithFormat:@"%C", str[0]]);
    NSLog(@"%%lc: %@", [NSString stringWithFormat:@"%lc", str[0]]);

    [pool drain];
    return 0;
}

Учитывая спецификацию printf, я ожидаю, что каждая из вышеперечисленных пар напечатает одно и то же. Но когда я запускаю код, я получаю следующий вывод:

2009-03-20 17:00:13.363 UnicharFormatSpecifierTest[48127:10b] NSLog
2009-03-20 17:00:13.365 UnicharFormatSpecifierTest[48127:10b] %S:  !
2009-03-20 17:00:13.366 UnicharFormatSpecifierTest[48127:10b] %ls: ˇ¯!
2009-03-20 17:00:13.366 UnicharFormatSpecifierTest[48127:10b] %C:  
2009-03-20 17:00:13.367 UnicharFormatSpecifierTest[48127:10b] %lc: 
2009-03-20 17:00:13.367 UnicharFormatSpecifierTest[48127:10b] 
2009-03-20 17:00:13.368 UnicharFormatSpecifierTest[48127:10b] +[NSString stringWithFormat:]
2009-03-20 17:00:13.368 UnicharFormatSpecifierTest[48127:10b] %S:  !
2009-03-20 17:00:13.369 UnicharFormatSpecifierTest[48127:10b] %ls: ˇ¯!
2009-03-20 17:00:13.369 UnicharFormatSpecifierTest[48127:10b] %C:  
2009-03-20 17:00:13.370 UnicharFormatSpecifierTest[48127:10b] %lc: 

Я что-то не так делаю, или это ошибка в коде Apple?

1 Ответ

6 голосов
/ 21 марта 2009

В Mac OS X <machine/_types.h> определяет wchar_t как int, так что это четыре байта (32 бита) на всех поддерживаемых в настоящее время архитектурах.

Как вы заметили, справочная страница printf (3) определяет %S как эквивалент %ls, который принимает указатель на некоторые wchar_t символы (wchar_t *).

Документация Какао, на которую вы ссылались (и ее эквивалент CF), однако, определяет %S отдельно:

  • %S: массив с нулевым символом в конце 16-бит символы Юникода

Акцент добавлен. Также то же самое относится к %C.

Итак, это не ошибка. CF и Какао интерпретируют %S и %C иначе, чем printf и его кузены интерпретируют их. CF и Какао обрабатывают символ (ы) как UTF-16, тогда как printf (предположительно) рассматривает их как UTF-32.

Интерпретация CF / Cocoa более полезна при работе с Core Services, так как некоторые API (например, File Manager) будут передавать вам текст в виде массива UniChar s, а не CFString; до тех пор, пока вы не завершите этот массив нулем, вы можете использовать его с %S для печати строки.

...