Check if last characters of an NSString are numbers
up vote
0
down vote
favorite
Is it possible to see of a string ends with a number which length is not known?
- "String 1" -> 1
- "String 4356" -> 4356
- "String" -> nil
If so, how can I determine that number?
cocoa nsstring numbers
add a comment |
up vote
0
down vote
favorite
Is it possible to see of a string ends with a number which length is not known?
- "String 1" -> 1
- "String 4356" -> 4356
- "String" -> nil
If so, how can I determine that number?
cocoa nsstring numbers
add a comment |
up vote
0
down vote
favorite
up vote
0
down vote
favorite
Is it possible to see of a string ends with a number which length is not known?
- "String 1" -> 1
- "String 4356" -> 4356
- "String" -> nil
If so, how can I determine that number?
cocoa nsstring numbers
Is it possible to see of a string ends with a number which length is not known?
- "String 1" -> 1
- "String 4356" -> 4356
- "String" -> nil
If so, how can I determine that number?
cocoa nsstring numbers
cocoa nsstring numbers
asked Apr 3 '10 at 9:57
Michael Matheus
3417
3417
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
up vote
11
down vote
accepted
To test that a string ends with numbers, you can use an NSPredicate, such as:
NSPredicate endsNumerically = [NSPredicate predicateWithFormat:@"SELF matches %@", @"\d+$"];
[endsNumerically evaluateWithObject:string]; // returns TRUE if predicate succeeds
NSScanner
is sometimes useful for extracting things from strings, but it doesn't scan backward. You could define a Gnirts (reverse string) class and use that with an NSScanner, but that's probably more hassle than it's worth.
NSString's rangeOfCharacterFromSet:options:
, which I had hope to use, only looks for a single character (it's like strchr
and strrchr
, if you're familiar with C), but we can roll our own that returns a contiguous range of characters from a set (a little like strspn
) as a category on NSString
. While we're at it, let's include methods that return substrings rather than ranges.
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
To use the new category to check that a string ends with digits or to extract the number:
NSString* number = [string substringFromSet:[NSCharacterSet decimalDigitCharacterSet]
options:NSBackwardsSearch|NSAnchoredSearch];
if (number != nil) {
return [number intValue];
} else {
// string doesn't end with a number.
}
Lastly, you can use a third party regular expression library, such as RegexKit or RegexkitLite.
Thanks for replying. I think there are two typos in your second snippet. range should be digitRange and the == should be != right? Also, the second snippet finds 2 for the value 12. I'd like to find all positive numbers not regarding their amount of ciphers. Is this also possible with your second snippet or should I go for the regex libraries?
– Michael Matheus
Apr 3 '10 at 11:59
@Michael: yep. Originally, I had the "string doesn't end with a number" branch first; apparently, I neglected to invert the test. I'll update my answer with a snippet that extracts the entire number for real once I've had some rest.
– outis
Apr 3 '10 at 13:14
Thanks for checking it out for me.
– Michael Matheus
Apr 3 '10 at 14:04
Thanks a super über giga million times! It contains a typo in substringFromSet:options:range: , range is declared twice there. Removing NSRange from that paragraph did the trick :D
– Michael Matheus
Apr 4 '10 at 7:05
+1 for the awesomeness of using goto AND making the code work without it
– Akku
Feb 22 '11 at 13:49
|
show 1 more comment
up vote
0
down vote
I couldn't get the NSPredicate
code above to work correctly, though it looks like it should. Instead I accomplished the same thing with
if ([string rangeOfString:@"\d+$" options:NSRegularExpressionSearch].location != NSNotFound) {
// string ends with a number
}
Hat-tip to this answer.
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
11
down vote
accepted
To test that a string ends with numbers, you can use an NSPredicate, such as:
NSPredicate endsNumerically = [NSPredicate predicateWithFormat:@"SELF matches %@", @"\d+$"];
[endsNumerically evaluateWithObject:string]; // returns TRUE if predicate succeeds
NSScanner
is sometimes useful for extracting things from strings, but it doesn't scan backward. You could define a Gnirts (reverse string) class and use that with an NSScanner, but that's probably more hassle than it's worth.
NSString's rangeOfCharacterFromSet:options:
, which I had hope to use, only looks for a single character (it's like strchr
and strrchr
, if you're familiar with C), but we can roll our own that returns a contiguous range of characters from a set (a little like strspn
) as a category on NSString
. While we're at it, let's include methods that return substrings rather than ranges.
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
To use the new category to check that a string ends with digits or to extract the number:
NSString* number = [string substringFromSet:[NSCharacterSet decimalDigitCharacterSet]
options:NSBackwardsSearch|NSAnchoredSearch];
if (number != nil) {
return [number intValue];
} else {
// string doesn't end with a number.
}
Lastly, you can use a third party regular expression library, such as RegexKit or RegexkitLite.
Thanks for replying. I think there are two typos in your second snippet. range should be digitRange and the == should be != right? Also, the second snippet finds 2 for the value 12. I'd like to find all positive numbers not regarding their amount of ciphers. Is this also possible with your second snippet or should I go for the regex libraries?
– Michael Matheus
Apr 3 '10 at 11:59
@Michael: yep. Originally, I had the "string doesn't end with a number" branch first; apparently, I neglected to invert the test. I'll update my answer with a snippet that extracts the entire number for real once I've had some rest.
– outis
Apr 3 '10 at 13:14
Thanks for checking it out for me.
– Michael Matheus
Apr 3 '10 at 14:04
Thanks a super über giga million times! It contains a typo in substringFromSet:options:range: , range is declared twice there. Removing NSRange from that paragraph did the trick :D
– Michael Matheus
Apr 4 '10 at 7:05
+1 for the awesomeness of using goto AND making the code work without it
– Akku
Feb 22 '11 at 13:49
|
show 1 more comment
up vote
11
down vote
accepted
To test that a string ends with numbers, you can use an NSPredicate, such as:
NSPredicate endsNumerically = [NSPredicate predicateWithFormat:@"SELF matches %@", @"\d+$"];
[endsNumerically evaluateWithObject:string]; // returns TRUE if predicate succeeds
NSScanner
is sometimes useful for extracting things from strings, but it doesn't scan backward. You could define a Gnirts (reverse string) class and use that with an NSScanner, but that's probably more hassle than it's worth.
NSString's rangeOfCharacterFromSet:options:
, which I had hope to use, only looks for a single character (it's like strchr
and strrchr
, if you're familiar with C), but we can roll our own that returns a contiguous range of characters from a set (a little like strspn
) as a category on NSString
. While we're at it, let's include methods that return substrings rather than ranges.
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
To use the new category to check that a string ends with digits or to extract the number:
NSString* number = [string substringFromSet:[NSCharacterSet decimalDigitCharacterSet]
options:NSBackwardsSearch|NSAnchoredSearch];
if (number != nil) {
return [number intValue];
} else {
// string doesn't end with a number.
}
Lastly, you can use a third party regular expression library, such as RegexKit or RegexkitLite.
Thanks for replying. I think there are two typos in your second snippet. range should be digitRange and the == should be != right? Also, the second snippet finds 2 for the value 12. I'd like to find all positive numbers not regarding their amount of ciphers. Is this also possible with your second snippet or should I go for the regex libraries?
– Michael Matheus
Apr 3 '10 at 11:59
@Michael: yep. Originally, I had the "string doesn't end with a number" branch first; apparently, I neglected to invert the test. I'll update my answer with a snippet that extracts the entire number for real once I've had some rest.
– outis
Apr 3 '10 at 13:14
Thanks for checking it out for me.
– Michael Matheus
Apr 3 '10 at 14:04
Thanks a super über giga million times! It contains a typo in substringFromSet:options:range: , range is declared twice there. Removing NSRange from that paragraph did the trick :D
– Michael Matheus
Apr 4 '10 at 7:05
+1 for the awesomeness of using goto AND making the code work without it
– Akku
Feb 22 '11 at 13:49
|
show 1 more comment
up vote
11
down vote
accepted
up vote
11
down vote
accepted
To test that a string ends with numbers, you can use an NSPredicate, such as:
NSPredicate endsNumerically = [NSPredicate predicateWithFormat:@"SELF matches %@", @"\d+$"];
[endsNumerically evaluateWithObject:string]; // returns TRUE if predicate succeeds
NSScanner
is sometimes useful for extracting things from strings, but it doesn't scan backward. You could define a Gnirts (reverse string) class and use that with an NSScanner, but that's probably more hassle than it's worth.
NSString's rangeOfCharacterFromSet:options:
, which I had hope to use, only looks for a single character (it's like strchr
and strrchr
, if you're familiar with C), but we can roll our own that returns a contiguous range of characters from a set (a little like strspn
) as a category on NSString
. While we're at it, let's include methods that return substrings rather than ranges.
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
To use the new category to check that a string ends with digits or to extract the number:
NSString* number = [string substringFromSet:[NSCharacterSet decimalDigitCharacterSet]
options:NSBackwardsSearch|NSAnchoredSearch];
if (number != nil) {
return [number intValue];
} else {
// string doesn't end with a number.
}
Lastly, you can use a third party regular expression library, such as RegexKit or RegexkitLite.
To test that a string ends with numbers, you can use an NSPredicate, such as:
NSPredicate endsNumerically = [NSPredicate predicateWithFormat:@"SELF matches %@", @"\d+$"];
[endsNumerically evaluateWithObject:string]; // returns TRUE if predicate succeeds
NSScanner
is sometimes useful for extracting things from strings, but it doesn't scan backward. You could define a Gnirts (reverse string) class and use that with an NSScanner, but that's probably more hassle than it's worth.
NSString's rangeOfCharacterFromSet:options:
, which I had hope to use, only looks for a single character (it's like strchr
and strrchr
, if you're familiar with C), but we can roll our own that returns a contiguous range of characters from a set (a little like strspn
) as a category on NSString
. While we're at it, let's include methods that return substrings rather than ranges.
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
To use the new category to check that a string ends with digits or to extract the number:
NSString* number = [string substringFromSet:[NSCharacterSet decimalDigitCharacterSet]
options:NSBackwardsSearch|NSAnchoredSearch];
if (number != nil) {
return [number intValue];
} else {
// string doesn't end with a number.
}
Lastly, you can use a third party regular expression library, such as RegexKit or RegexkitLite.
edited Apr 4 '10 at 2:18
answered Apr 3 '10 at 10:31
outis
58.2k13114173
58.2k13114173
Thanks for replying. I think there are two typos in your second snippet. range should be digitRange and the == should be != right? Also, the second snippet finds 2 for the value 12. I'd like to find all positive numbers not regarding their amount of ciphers. Is this also possible with your second snippet or should I go for the regex libraries?
– Michael Matheus
Apr 3 '10 at 11:59
@Michael: yep. Originally, I had the "string doesn't end with a number" branch first; apparently, I neglected to invert the test. I'll update my answer with a snippet that extracts the entire number for real once I've had some rest.
– outis
Apr 3 '10 at 13:14
Thanks for checking it out for me.
– Michael Matheus
Apr 3 '10 at 14:04
Thanks a super über giga million times! It contains a typo in substringFromSet:options:range: , range is declared twice there. Removing NSRange from that paragraph did the trick :D
– Michael Matheus
Apr 4 '10 at 7:05
+1 for the awesomeness of using goto AND making the code work without it
– Akku
Feb 22 '11 at 13:49
|
show 1 more comment
Thanks for replying. I think there are two typos in your second snippet. range should be digitRange and the == should be != right? Also, the second snippet finds 2 for the value 12. I'd like to find all positive numbers not regarding their amount of ciphers. Is this also possible with your second snippet or should I go for the regex libraries?
– Michael Matheus
Apr 3 '10 at 11:59
@Michael: yep. Originally, I had the "string doesn't end with a number" branch first; apparently, I neglected to invert the test. I'll update my answer with a snippet that extracts the entire number for real once I've had some rest.
– outis
Apr 3 '10 at 13:14
Thanks for checking it out for me.
– Michael Matheus
Apr 3 '10 at 14:04
Thanks a super über giga million times! It contains a typo in substringFromSet:options:range: , range is declared twice there. Removing NSRange from that paragraph did the trick :D
– Michael Matheus
Apr 4 '10 at 7:05
+1 for the awesomeness of using goto AND making the code work without it
– Akku
Feb 22 '11 at 13:49
Thanks for replying. I think there are two typos in your second snippet. range should be digitRange and the == should be != right? Also, the second snippet finds 2 for the value 12. I'd like to find all positive numbers not regarding their amount of ciphers. Is this also possible with your second snippet or should I go for the regex libraries?
– Michael Matheus
Apr 3 '10 at 11:59
Thanks for replying. I think there are two typos in your second snippet. range should be digitRange and the == should be != right? Also, the second snippet finds 2 for the value 12. I'd like to find all positive numbers not regarding their amount of ciphers. Is this also possible with your second snippet or should I go for the regex libraries?
– Michael Matheus
Apr 3 '10 at 11:59
@Michael: yep. Originally, I had the "string doesn't end with a number" branch first; apparently, I neglected to invert the test. I'll update my answer with a snippet that extracts the entire number for real once I've had some rest.
– outis
Apr 3 '10 at 13:14
@Michael: yep. Originally, I had the "string doesn't end with a number" branch first; apparently, I neglected to invert the test. I'll update my answer with a snippet that extracts the entire number for real once I've had some rest.
– outis
Apr 3 '10 at 13:14
Thanks for checking it out for me.
– Michael Matheus
Apr 3 '10 at 14:04
Thanks for checking it out for me.
– Michael Matheus
Apr 3 '10 at 14:04
Thanks a super über giga million times! It contains a typo in substringFromSet:options:range: , range is declared twice there. Removing NSRange from that paragraph did the trick :D
– Michael Matheus
Apr 4 '10 at 7:05
Thanks a super über giga million times! It contains a typo in substringFromSet:options:range: , range is declared twice there. Removing NSRange from that paragraph did the trick :D
– Michael Matheus
Apr 4 '10 at 7:05
+1 for the awesomeness of using goto AND making the code work without it
– Akku
Feb 22 '11 at 13:49
+1 for the awesomeness of using goto AND making the code work without it
– Akku
Feb 22 '11 at 13:49
|
show 1 more comment
up vote
0
down vote
I couldn't get the NSPredicate
code above to work correctly, though it looks like it should. Instead I accomplished the same thing with
if ([string rangeOfString:@"\d+$" options:NSRegularExpressionSearch].location != NSNotFound) {
// string ends with a number
}
Hat-tip to this answer.
add a comment |
up vote
0
down vote
I couldn't get the NSPredicate
code above to work correctly, though it looks like it should. Instead I accomplished the same thing with
if ([string rangeOfString:@"\d+$" options:NSRegularExpressionSearch].location != NSNotFound) {
// string ends with a number
}
Hat-tip to this answer.
add a comment |
up vote
0
down vote
up vote
0
down vote
I couldn't get the NSPredicate
code above to work correctly, though it looks like it should. Instead I accomplished the same thing with
if ([string rangeOfString:@"\d+$" options:NSRegularExpressionSearch].location != NSNotFound) {
// string ends with a number
}
Hat-tip to this answer.
I couldn't get the NSPredicate
code above to work correctly, though it looks like it should. Instead I accomplished the same thing with
if ([string rangeOfString:@"\d+$" options:NSRegularExpressionSearch].location != NSNotFound) {
// string ends with a number
}
Hat-tip to this answer.
answered Nov 20 at 1:10
jab
3,65822740
3,65822740
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f2570853%2fcheck-if-last-characters-of-an-nsstring-are-numbers%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown