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.