NSCharacter Set использует int, но мне нужен неназначенный short?

Я использую MWFeedParser для добавления канала в мое приложение. Теперь фреймворк передает дату, и у меня есть несколько предупреждений, в основном из-за старого типа кода.

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

Код относительно:

    // Character sets
NSCharacterSet *stopCharacters = [NSCharacterSet characterSetWithCharactersInString:[NSString stringWithFormat:@"< \t\n\r%C%C%C%C", 0x0085, 0x000C, 0x2028, 0x2029]];

Теперь это предупреждение:

\t\n\r%C%C%C%C", 0x0085, 0x000C, 0x2028, 0x2029]];

Предупреждение:

Формат указывает тип "unsigned short", но аргумент имеет тип "int"

Итак, я изменился на:

\t\n\r%i%i%i%i", 0x0085, 0x000C, 0x2028, 0x2029]];

который действительно удалил предупреждения и дал мне идеальный код:-) (без предупреждений или ошибок)

Когда я запустил приложение, оно не проанализировало дату и не смогло открыть ссылку. Я не уверен, что это вещь C, но сейчас она определенно находится за пределами моей области знаний. Есть ли кто-нибудь, кто может помочь мне, который может решить эту проблему, и все еще работает в приложении?

Заранее спасибо:-)

РЕДАКТИРОВАТЬ

     - (NSString *)stringByConvertingHTMLToPlainText {

// Pool
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// Character sets
NSCharacterSet *stopCharacters = [NSCharacterSet characterSetWithCharactersInString:@"< \t\n\r\x0085\x000C\u2028\u2029"];    
NSCharacterSet *newLineAndWhitespaceCharacters = [NSCharacterSet characterSetWithCharactersInString:@"< \t\n\r\205\014\u2028\u2029"];


NSCharacterSet *tagNameCharacters = [NSCharacterSet characterSetWithCharactersInString:@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"];

// Scan and find all tags
NSMutableString *result = [[NSMutableString alloc] initWithCapacity:self.length];
NSScanner *scanner = [[NSScanner alloc] initWithString:self];
[scanner setCharactersToBeSkipped:nil];
[scanner setCaseSensitive:YES];
NSString *str = nil, *tagName = nil;
BOOL dontReplaceTagWithSpace = NO;
do {

    // Scan up to the start of a tag or whitespace
    if ([scanner scanUpToCharactersFromSet:stopCharacters intoString:&str]) {
        [result appendString:str];
        str = nil; // reset
    }

    // Check if we've stopped at a tag/comment or whitespace
    if ([scanner scanString:@"<" intoString:NULL]) {

        // Stopped at a comment or tag
        if ([scanner scanString:@"!--" intoString:NULL]) {

            // Comment
            [scanner scanUpToString:@"-->" intoString:NULL]; 
            [scanner scanString:@"-->" intoString:NULL];

        } else {

            // Tag - remove and replace with space unless it's
            // a closing inline tag then dont replace with a space
            if ([scanner scanString:@"/" intoString:NULL]) {

                // Closing tag - replace with space unless it's inline
                tagName = nil; dontReplaceTagWithSpace = NO;
                if ([scanner scanCharactersFromSet:tagNameCharacters intoString:&tagName]) {
                    tagName = [tagName lowercaseString];
                    dontReplaceTagWithSpace = ([tagName isEqualToString:@"a"] ||
                                               [tagName isEqualToString:@"b"] ||
                                               [tagName isEqualToString:@"i"] ||
                                               [tagName isEqualToString:@"q"] ||
                                               [tagName isEqualToString:@"span"] ||
                                               [tagName isEqualToString:@"em"] ||
                                               [tagName isEqualToString:@"strong"] ||
                                               [tagName isEqualToString:@"cite"] ||
                                               [tagName isEqualToString:@"abbr"] ||
                                               [tagName isEqualToString:@"acronym"] ||
                                               [tagName isEqualToString:@"label"]);
                }

                // Replace tag with string unless it was an inline
                if (!dontReplaceTagWithSpace && result.length > 0 && ![scanner isAtEnd]) [result appendString:@" "];

            }

            // Scan past tag
            [scanner scanUpToString:@">" intoString:NULL];
            [scanner scanString:@">" intoString:NULL];

        }

    } else {

        // Stopped at whitespace - replace all whitespace and newlines with a space
        if ([scanner scanCharactersFromSet:newLineAndWhitespaceCharacters intoString:NULL]) {
            if (result.length > 0 && ![scanner isAtEnd]) [result appendString:@" "]; // Dont append space to beginning or end of result
        }

    }

} while (![scanner isAtEnd]);

// Cleanup
[scanner release];

// Decode HTML entities and return
NSString *retString = [[result stringByDecodingHTMLEntities] retain];
[result release];

// Drain
[pool drain];

// Return
return [retString autorelease];

}

3 ответа

Решение

Это полный беспорядок

Причина, по которой это полный беспорядок, заключается в том, что вы сталкиваетесь с ошибкой компилятора и произвольным ограничением в спецификации C.

Прокрутите вниз для исправления.

Предупреждение компилятора

Формат указывает тип "unsigned short", но аргумент имеет тип "int"

Мой вывод заключается в том, что это ошибка компилятора в Clang. Определенно безопасно игнорировать это предупреждение, потому что (unsigned short) аргументы всегда выдвигаются (int) прежде чем они будут переданы в функции Vararg в любом случае. Все это в стандарте C (и это относится и к Objective C).

printf("%hd", 1); // Clang generates warning. GCC does not.
                  // Clang is wrong, GCC is right.

printf("%hd", 1 << 16); // Clang generates warning.  GCC does not.
                        // Clang is right, GCC is wrong.

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

Помните, что на самом деле невозможно пройти short в printf()потому что он должен быть повышен до int, GCC никогда не выдает предупреждение для констант, Clang игнорирует тот факт, что вы передаете константу, и всегда выдает предупреждение, потому что тип неправильный. Оба варианта неверны.

Я подозреваю, что никто не заметил, потому что - зачем вам передавать постоянное выражение printf() тем не мение?

В краткосрочной перспективе вы можете использовать следующий хак:

#pragma GCC diagnostic ignored "-Wformat"

Универсальные имена персонажей

Ты можешь использовать \uXXXX нотации. За исключением того, что вы не можете, потому что компилятор не позволит вам использовать U+0085 сюда. Зачем? См. § 6.4.3 C99:

Имя универсального символа не должно указывать символ, короткий идентификатор которого меньше 00A0 Кроме как 0024 ($), 0040 (@), или же 0060 (), ни один в ассортименте D800 через DFFF включительно.

Это исключает \u0085,

Есть предложение исправить эту часть спецификации.

Исправление

Вы действительно хотите постоянную строку, не так ли? Использовать этот:

[NSCharacterSet characterSetWithCharactersInString:
  @"\t\n\r\xc2\x85\x0c\u2028\u2029"]

Это зависит от того факта, что исходная кодировка - UTF-8. Не волнуйтесь, это не изменится в ближайшее время.

\xc2\x85 в строке кодировка UTF-8 U+0085, Появление 85 в обоих это совпадение.

Проблема в том, что 0x0085и т. д. буквальные целые. Таким образом, они не соответствуют %C спецификатор формата, который ожидает unichar, который является неподписанным коротким.

Нет прямого способа указать литеральное сокращение в C, и я не знаю ни о каком расширении Objective-C. Но вы можете использовать метод грубой силы:

NSCharacterSet *stopCharacters =
         [NSCharacterSet characterSetWithCharactersInString:
                  [NSString stringWithFormat:@"< \t\n\r%C%C%C%C", 
                               (unichar)0x0085, (unichar)0x000C,
                               (unichar)0x2028, (unichar)0x2029]];

Вам не нужен stringWithFormat, вы можете встраивать символы Юникода непосредственно в строку, используя escape \ u. Например \u0085.

Другие вопросы по тегам