Проверьте, являются ли последние символы строки NSString числами - PullRequest
0 голосов
/ 03 апреля 2010

Можно ли увидеть, что строка заканчивается числом, длина которого неизвестна?

  1. «Строка 1» -> 1
  2. "String 4356" -> 4356
  3. "Строка" -> ноль

Если так, как я могу определить это число?

Ответы [ 2 ]

11 голосов
/ 03 апреля 2010

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

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

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

NSString's rangeOfCharacterFromSet:options:, который я надеялся использовать, ищет только один символ (это как strchr и strrchr, если вы знакомы с C), но мы можем бросить наш собственный, который возвращает непрерывный диапазон символов из набора (немного похоже на strspn) как категорию на 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 голосов
/ 20 ноября 2018

Я не могу заставить код NSPredicate выше работать правильно, хотя, похоже, так и должно быть. Вместо этого я сделал то же самое с

if ([string rangeOfString:@"\\d+$" options:NSRegularExpressionSearch].location != NSNotFound) {
    // string ends with a number
}

Шляпник к этому ответу .

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