Test If An NSString Contains a Letter - iphone

I'm working on an iPhone project and I need to check if the user's input in a UITextfield contains a letter. More generally if an NSString contains a letter.
I tried this with a giant if loop with the rangeofstring:#"A".location == NSNotFound and then did OR rangeofstring:#"B".location == NSNotFound
and so on....
But:
It doesn't seem to work
There has to be a simple line of code to check if the NSString contains letters.
I have been searching this for hours... Can someone please answer this question???

Use an NSCharacterSet. Note that letterCharacterSet includes all things that are "letters" or "ideographs." So that includes é and 中, but usually that's what you want. If you want a specific set of letters (like English letters), you can construct your own NSCharacterSet with them using characterSetWithCharactersInString:.
if ([string rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet]].location == NSNotFound)

If you want to make sure the text has a certain letter in it (as opposed to just ANY letter), use the rangeOfString: message. For example, to ensure the text contains the letter "Q":
NSString *string = #"poQduu";
if ([string rangeOfString:#"Q"].location != NSNotFound) {
DLog (#"Yes, we have a Q at location %i", [string rangeOfString:#"Q"].location );
}
As others (Rob Napier) note, if you want to find ANY letter, use the rangeOfCharacterFromSet: message.
if ([string rangeOfCharacterFromSet:[NSCharacterSet letterCharacterSet]].location != NSNotFound) ...

Related

iPhone iOS how to programmatically check for characters like ✭ ♦ (and others from this set)?

I know that both ✭star and ♦ diamond are from the ASCII extended character set. But is there some NScharacterSet available on iOS that I can use to check for characters like these programmatically?
you can display these symbols using charsets ISO 8859-1 or UTF-8.
[ ★ ] star solid [ number: ★]
[ ♦ ] black diamond suit [name: ♦] [number: ♦]
This can be done with the NSString object method: rangeOfCharacterFromSet. It returns NSRange object.
From that,
Eg.:
NSCharacterSet *charSet = [[NSCharacterSet characterSetWithCharactersInString:#"0123456789"] invertedSet];
NSString *string = #"Stach✭Overflow";
NSRange range = [string rangeOfCharacterFromSet:charSet];
if(range.location != NSNotFound) {
// one of those characters is exists in the string.
}else{
//no specifiedcharacter not found.
}

NSScanner scanUpToCharactersFromSet gives BAD ACCESS

NSString*test=[NSString stringWithString:inputString];
NSScanner*scan;
BOOL pass= [scan scanUpToCharactersFromSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet] intoString:&test];
The last line crashes the app with bad access. Does it have something to do with the address symbol, &? I'm not clear on why it needs this type of syntax anyway.
I am trying to simply check with my BOOL if the inputString contains any non-alphanumeric characters. If it does, pass becomes YES.
UPDATE: I see I do not understand scanner entirely. I understand this output:
NSString*test=#"Hello"; // this should cause my BOOL to be NO since no characters are scanned
NSScanner*scanix=[NSScanner scannerWithString:test];
BOOL pass= [scanix scanUpToCharactersFromSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet] intoString:nil];
NSLog(#"pass is %i for %#",pass, test);
Result in log: pass is 1 for Hello
What I want is to know if in fact the test string contains non-alphanumeric characters. How would I factor such a test into this?
You are supposed to initialise your scanner with the string to parse,
NSScanner *scan =[NSScanner scannerWithString:mystring];
What I want is to know if in fact the test string contains
non-alphanumeric characters. How would I factor such a test into this?
You don't need to use NSScanner if this is your only goal. You can simply use NSString's -rangeOfCharacterFromSet: method:
NSCharacterSet *nonAlphanumeric = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
pass = ([test rangeOfCharacterFromSet:nonAlphanumeric].location != NSNotFound);
You are mixing up the destination string and the source string. Your source is test. Also, your scanner is not initialized.
NSScanner *scan = [NSScanner scannerWithString:test];
BOOL didScanCharacters = [scan scanUpToCharactersFromSet:
[[NSCharacterSet alphanumericCharacterSet] invertedSet]
intoString:nil];
The EXC_BAD_ACCESS error occurs because you are sending a message to a nonexistent object.

How to check if NSString is contains a numeric value?

I have a string that is being generate from a formula, however I only want to use the string as long as all of its characters are numeric, if not that I want to do something different for instance display an error message.
I have been having a look round but am finding it hard to find anything that works along the lines of what I am wanting to do. I have looked at NSScanner but I am not sure if its checking the whole string and then I am not actually sure how to check if these characters are numeric
- (void)isNumeric:(NSString *)code{
NSScanner *ns = [NSScanner scannerWithString:code];
if ( [ns scanFloat:NULL] ) //what can I use instead of NULL?
{
NSLog(#"INSIDE IF");
}
else {
NSLog(#"OUTSIDE IF");
}
}
So after a few more hours searching I have stumbled across an implementation that dose exactly what I am looking for.
so if you are looking to check if their are any alphanumeric characters in your NSString this works here
-(bool) isNumeric:(NSString*) hexText
{
NSNumberFormatter* numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];
NSNumber* number = [numberFormatter numberFromString:hexText];
if (number != nil) {
NSLog(#"%# is numeric", hexText);
//do some stuff here
return true;
}
NSLog(#"%# is not numeric", hexText);
//or do some more stuff here
return false;
}
hope this helps.
Something like this would work:
#interface NSString (usefull_stuff)
- (BOOL) isAllDigits;
#end
#implementation NSString (usefull_stuff)
- (BOOL) isAllDigits
{
NSCharacterSet* nonNumbers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
NSRange r = [self rangeOfCharacterFromSet: nonNumbers];
return r.location == NSNotFound && self.length > 0;
}
#end
then just use it like this:
NSString* hasOtherStuff = #"234 other stuff";
NSString* digitsOnly = #"123345999996665003030303030";
BOOL b1 = [hasOtherStuff isAllDigits];
BOOL b2 = [digitsOnly isAllDigits];
You don't have to wrap the functionality in a private category extension like this, but it sure makes it easy to reuse..
I like this solution better than the others since it wont ever overflow some int/float that is being scanned via NSScanner - the number of digits can be pretty much any length.
Consider NSString integerValue - it returns an NSInteger. However, it will accept some strings that are not entirely numeric and does not provide a mechanism to determine strings which are not numeric at all. This may or may not be acceptable.
For instance, " 13 " -> 13, "42foo" -> 42 and "helloworld" -> 0.
Happy coding.
Now, since the above was sort of a tangent to the question, see determine if string is numeric. Code taken from link, with comments added:
BOOL isNumeric(NSString *s)
{
NSScanner *sc = [NSScanner scannerWithString: s];
// We can pass NULL because we don't actually need the value to test
// for if the string is numeric. This is allowable.
if ( [sc scanFloat:NULL] )
{
// Ensure nothing left in scanner so that "42foo" is not accepted.
// ("42" would be consumed by scanFloat above leaving "foo".)
return [sc isAtEnd];
}
// Couldn't even scan a float :(
return NO;
}
The above works with just scanFloat -- e.g. no scanInt -- because the range of a float is much larger than that of an integer (even a 64-bit integer).
This function checks for "totally numeric" and will accept "42" and "0.13E2" but reject " 13 ", "42foo" and "helloworld".
It's very simple.
+ (BOOL)isStringNumeric:(NSString *)text
{
NSCharacterSet *alphaNums = [NSCharacterSet decimalDigitCharacterSet];
NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:text];
return [alphaNums isSupersetOfSet:inStringSet];
}
Like this:
- (void)isNumeric:(NSString *)code{
NSScanner *ns = [NSScanner scannerWithString:code];
float the_value;
if ( [ns scanFloat:&the_value] )
{
NSLog(#"INSIDE IF");
// do something with `the_value` if you like
}
else {
NSLog(#"OUTSIDE IF");
}
}
Faced same problem in Swift.
In Swift you should use this code, according TomSwift's answer:
func isAllDigits(str: String) -> Bool {
let nonNumbers = NSCharacterSet.decimalDigitCharacterSet()
if let range = str.rangeOfCharacterFromSet(nonNumbers) {
return true
}
else {
return false
}
}
P.S. Also you can use other NSCharacterSets or their combinations to check your string!
For simple numbers like "12234" or "231231.23123" the answer can be simple.
There is a transformation law for int numbers: when string with integer transforms to int (or long) number and then, again, transforms it back to another string these strings will be equal.
In Objective C it will looks like:
NSString *numStr=#"1234",*num2Str=nil;
num2Str=[NSString stringWithFormat:#"%lld",numStr.longlongValue];
if([numStr isEqualToString: num2Str]) NSLog(#"numStr is an integer number!");
By using this transformation law we can create solution
to detect double or long numbers:
NSString *numStr=#"12134.343"
NSArray *numList=[numStr componentsSeparatedByString:#"."];
if([[NSString stringWithFormat:#"%lld", numStr.longLongValue] isEqualToString:numStr]) NSLog(#"numStr is an integer number");
else
if( numList.count==2 &&
[[NSString stringWithFormat:#"%lld",((NSString*)numList[0]).longLongValue] isEqualToString:(NSString*)numList[0]] &&
[[NSString stringWithFormat:#"%lld",((NSString*)numList[1]).longLongValue] isEqualToString:(NSString*)numList[1]] )
NSLog(#"numStr is a double number");
else
NSLog(#"numStr is not a number");
I did not copy the code above from my work code so can be some mistakes, but I think the main point is clear.
Of course this solution doesn't work with numbers like "1E100", as well it doesn't take in account size of integer and fractional part. By using the law described above you can do whatever number detection you need.
C.Johns' answer is wrong. If you use a formatter, you risk apple changing their codebase at some point and having the formatter spit out a partial result. Tom's answer is wrong too. If you use the rangeOfCharacterFromSet method and check for NSNotFound, it'll register a true if the string contains even one number. Similarly, other answers in this thread suggest using the Integer value method. That is also wrong because it will register a true if even one integer is present in the string. The OP asked for an answer that ensures the entire string is numerical. Try this:
NSCharacterSet *searchSet = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
Tom was right about this part. That step gives you the non-numerical string characters. But then we do this:
NSString *trimmedString = [string stringByTrimmingCharactersInSet:searchSet];
return (string.length == trimmedString.length);
Tom's inverted character set can TRIM a string. So we can use that trim method to test if any non numerals exist in the string by comparing their lengths.

NSString: EOL and rangeOfString issues

Could someone please tell me if I am missing something here... I am trying to parse individual JSON objects out of a data stream. The data stream is buffered in a regular NSString, and the individual JSON objects are delineated by a EOL marker.
if([dataBuffer rangeOfString:#"\n"].location != NSNotFound) {
NSString *tmp = [dataBuffer stringByReplacingOccurrencesOfString:#"\n" withString:#"NEWLINE"];
NSLog(#"%#", tmp);
}
The code above outputs "...}NEWLINE{..." as expected. But if I change the #"\n" in the if-statement above to #"}\n", I get nothing.
Why don't you use - (NSArray *)componentsSeparatedByString:(NSString *)separator? You can give it a separator of #"\n" and the result will be a convenient array of strings representing your individual JSON strings which you can then iterate over.
if([dataBuffer rangeOfString:#"\n"].location != NSNotFound) {
NSArray* JSONstrings = [dataBuffer componentsSeparatedByString:#"\n"];
for(NSString* oneString in JSONstrings)
{
// here's where you process individual JSON strings
}
}
If you do mess with the terminating '}' you could make the JSON data invalid. Just break it up and pass it to the JSON library. There could easily be a trailing space after the '}' that is causing the problem you are observing.

check if(country == #"(null)" doesn't work

I got the problem that the if-statement doesn't work. After the first code line the variable contains the value "(null)", because the user who picked the contact from his iphone address book doesn't set the country key for this contact, so far so good.
but if I check the variable, it won't be true, but the value is certainly "(null)"... does someone have an idea?
NSString *country = [NSString [the dict objectForKey:(NSString *)kABPersonAddressCountryKey]];
if(country == #"(null)")
{
country = #"";
}
thanks in advance
sean
The correct expression would be:
if (country == nil)
which can be further shortened to:
if (!country)
And if you really want to test equality with the #"(null)" string, you should use the isEqual: method or isEqualToString:
if ([country isEqualToString:#"(null)"])
When you compare using the == operator, you are comparing object addresses, not their contents:
NSString *foo1 = [NSString stringWithString:#"foo"];
NSString *foo2 = [NSString stringWithString:#"foo"];
NSAssert(foo1 != foo2, #"The addresses are different.");
NSAssert([foo1 isEqual:foo2], #"But the contents are same.");
NSAssert([foo1 isEqualToString:foo2], #"True again, faster than isEqual:.");
That was a great answer I didn't know there was all those different ways of checking for nil or null string.