2010-04-03 5 views

ответ

11

Чтобы проверить, что строка заканчивается с числами, вы можете использовать NSPredicate, такие как:

NSPredicate endsNumerically = [NSPredicate predicateWithFormat:@"SELF matches %@", @"\\d+$"]; 
[endsNumerically evaluateWithObject:string]; // returns TRUE if predicate succeeds 

NSScanner иногда полезно для извлечения вещи из строк, но не сканирует назад. Вы можете определить класс Gnirts (обратная строка) и использовать его с NSScanner, но это, вероятно, больше хлопот, чем того стоит.

NSString-х rangeOfCharacterFromSet:options:, который я имел надежду на использование, смотрит только для одного символа (это как strchr and strrchr, если вы знакомы с C), но мы можем свернуть наши собственные, который возвращает непрерывный диапазон символов из набора (немного как strspn) как category на NSString. Пока мы это делаем, давайте включим методы, возвращающие подстроки, а не диапазоны.

RangeOfCharacters.h:

@interface NSString (RangeOfCharacters) 
/* note "Characters" is plural in the methods. It has poor readability, hard to 
* distinguish from the rangeOfCharacterFromSet: methods, but it's standard Apple 
* convention. 
*/ 
-(NSRange)rangeOfCharactersFromSet:(NSCharacterSet*)aSet; 
-(NSRange)rangeOfCharactersFromSet:(NSCharacterSet*)aSet options:(NSStringCompareOptions)mask; 
-(NSRange)rangeOfCharactersFromSet:(NSCharacterSet*)aSet options:(NSStringCompareOptions)mask range:(NSRange)range; 

// like the above, but return a string rather than a range 
-(NSString*)substringFromSet:(NSCharacterSet*)aSet; 
-(NSString*)substringFromSet:(NSCharacterSet*)aSet options:(NSStringCompareOptions)mask; 
-(NSString*)substringFromSet:(NSCharacterSet*)aSet options:(NSStringCompareOptions)mask range:(NSRange)range; 
@end 

RangeOfCharacters.m:

@implementation NSString (RangeOfCharacters) 
-(NSRange)rangeOfCharactersFromSet:(NSCharacterSet*)aSet { 
    return [self rangeOfCharactersFromSet:aSet options:0]; 
} 

-(NSRange)rangeOfCharactersFromSet:(NSCharacterSet*)aSet options:(NSStringCompareOptions)mask { 
    NSRange range = {0,[self length]}; 
    return [self rangeOfCharactersFromSet:aSet options:mask range:range]; 
} 

-(NSRange)rangeOfCharactersFromSet:(NSCharacterSet*)aSet options:(NSStringCompareOptions)mask range:(NSRange)range { 
    NSInteger start, curr, end, step=1; 
    if (mask & NSBackwardsSearch) { 
     step = -1; 
     start = range.location + range.length - 1; 
     end = range.location-1; 
    } else { 
     start = range.location; 
     end = start + range.length; 
    } 
    if (!(mask & NSAnchoredSearch)) { 
     // find first character in set 
     for (;start != end; start += step) { 
      if ([aSet characterIsMember:[self characterAtIndex:start]]) { 
#ifdef NOGOTO 
       break; 
#else 
       // Yeah, a goto. If you don't like them, define NOGOTO. 
       // Method will work the same, it will just make unneeded 
       // test whether character at start is in aSet 
       goto FoundMember; 
#endif 
      } 
     } 
#ifndef NOGOTO 
     goto NoSuchMember; 
#endif 
    } 
    if (![aSet characterIsMember:[self characterAtIndex:start]]) { 
    NoSuchMember: 
     // no characters found within given range 
     range.location = NSNotFound; 
     range.length = 0; 
     return range; 
    } 

FoundMember: 
    for (curr = start; curr != end; curr += step) { 
     if (![aSet characterIsMember:[self characterAtIndex:curr]]) { 
      break; 
     } 
    } 
    if (curr < start) { 
     // search was backwards 
     range.location = curr+1; 
     range.length = start - curr; 
    } else { 
     range.location = start; 
     range.length = curr - start; 
    } 
    return range; 
} 

-(NSString*)substringFromSet:(NSCharacterSet*)aSet { 
    return [self substringFromSet:aSet options:0]; 
} 

-(NSString*)substringFromSet:(NSCharacterSet*)aSet options:(NSStringCompareOptions)mask { 
    NSRange range = {0,[self length]}; 
    return [self substringFromSet:aSet options:mask range:range]; 
} 
-(NSString*)substringFromSet:(NSCharacterSet*)aSet options:(NSStringCompareOptions)mask range:(NSRange)range { 
    NSRange range = [self rangeOfCharactersFromSet:aSet options:mask range:range]; 
    if (NSNotFound == range.location) { 
     return nil; 
    } 
    return [self substringWithRange:range]; 
} 
@end 

Чтобы использовать новую категорию, чтобы проверить, что строка заканчивается цифрами или извлечь номер:

NSString* number = [string substringFromSet:[NSCharacterSet decimalDigitCharacterSet] 
          options:NSBackwardsSearch|NSAnchoredSearch]; 
if (number != nil) { 
    return [number intValue]; 
} else { 
    // string doesn't end with a number. 
} 

Наконец, вы можете использовать библиотеку регулярных выражений третьей стороны, такую ​​как RegexKit или RegexkitLite.

+0

Спасибо за ответ. Я думаю, что есть два опечатка во втором фрагменте. диапазон должен быть digitRange и == должен быть! = право? Кроме того, второй фрагмент находит 2 для значения 12. Я бы хотел найти все положительные числа, не касающиеся их количества шифров. Возможно ли это и с вашим вторым фрагментом, или я должен использовать библиотеки регулярных выражений? –

+0

@ Майкл: да. Первоначально у меня сначала была строка «строка не заканчивается числом»; по-видимому, я пренебрег инвертированием теста. Я обновляю свой ответ с помощью фрагмента, который извлекает все число на реальные, как только я отдохну. – outis

+0

Спасибо, что проверили это для меня. –

Смежные вопросы