I have a UITextField and I only want a number greater than 0 ( I don't want non-numeric characters or the value 0 )
This is how I check to see if it is empty:
if(seizure.text.length==0)
This is how I check to see if it is equal to 0:
else if(seizure.text doubleValue]==0)
How can I check for non-numeric characters?
First check to see if you have any characters in the string, then check to make sure that it only contains numeric characters, and finally check to see if the value is greater than 0:
if (seizure.text.length > 0)
{
NSCharacterSet *nonNumbers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([seizure.text rangeOfCharacterFromSet:nonNumbers].location == NSNotFound)
{
if ([seizure.text doubleValue] > 0)
{
// Text Field contains a numeric value greater than 0
NSLog(#"Good number.");
return;
}
}
}
// If we make it to here, it does not meet your requirements.
NSLog(#"Bad Number.");
NSScanner will do the job nicely here. Unlike -[NSString doubleValue], its scanDouble: can parse and then also tell you whether it consumed the entire string, so you will know that there are non-numerical characters present.
Demonstration on some test cases. See the comments for descriptions of the expected results.
NSArray * texts = #[// First four unacceptable because non-numeric
#"", #"Hello, world!", #"1.0 excelsior", #"Jiminy 1.0 Crickets",
// These three unacceptable because 0 or less
#"0.0" #"0", #"-2048",
// Last three are good
#"3.14159", #"1", #"10000000000.0"];
for( NSString * text in texts ){
NSScanner * scanner = [NSScanner scannerWithString:text];
double val;
[scanner scanDouble:&val];
// Scanned the whole string and ended up with a positive value
if( [scanner isAtEnd] && val > 0 ){
NSLog(#"'%#'? I accept.", text);
}
else {
NSLog(#"'%#' is no good.", text);
}
}
[seizure.text doubleValue] == 0 will be true either if seizure.text is a textual representation of zero or if it doesn't contain a valid textual representation of a number (see the documentation for doubleValue).
In other words if this expression is false then you have a string value which starts with a number. However you still don't know if you string value contains only a number, e.g. [#"2.5 miles" doubleValue] has the value 2.5. If you need to handle strings like this you should look at NSScanner.
Related
This question already has an answer here:
NSString containing hex convert to ascii equivalent
(1 answer)
Closed 6 years ago.
I have a Hex string like "000000000100" and I am using the following logic to do ASCII conversion, the output I am receiving is only 1 byte (\x01) But I want the output in the 6 byte format as \x00\x00\x00\x00\x01\x00
-(NSString*) decode
{
string=#"000000000100";
NSMutableString * newString = [[NSMutableString alloc]init];
int i = 0;
while (i < [string length])
{
NSString * hexChar = [string substringWithRange: NSMakeRange(i, 2)];
int value = 0;
sscanf([hexChar cStringUsingEncoding:NSASCIIStringEncoding], "%x", &value);
[newString appendFormat:#"%c", (char)value];
i+=2;
}
return newString;
}
How to do that ?
Let's first directly address your bug: In your code you attempt to add the next byte to your string with:
[newString appendFormat:#"%c", (char)value];
Your problem is that %c produces nothing if the character is a null, so you are appending an empty string and as you found end up with a string with a single byte in it.
You can fix your code by testing for the null and appending a string containing a single null:
if (value == 0)
[newString appendString:#"\0"]; // append a single null
else
[newString appendFormat:#"%c", (char)value];
Second, is this the way to do this?
Other answers have shown you other algorithms, they might be more efficient than yours as they only convert to a C-String once rather than repeatedly extract substrings and convert each one individually.
If and only if performance is a real issue for you you might wish to consider such C-based solutions. You clearly know how to use scanf, but in such a simple case as this you might want to look at digittoint and do the conversion of two hex digits to an integer yourself (value of first * 16 + value of second).
Conversely if you'd like to avoid C and scanf look at NSScanner and scanHexInt/scanHexLongLong - if your strings are never longer than 16 hex digits you can convert the whole string in one go and then produce an NSString from the bytes of the resultant unsigned 64-bit integer.
HTH
I need to count characters in string before some string and after some string. For example, I have string "This is example string" and I need to know howmany characters are before word "example" (it is 8 chars in this case) and how many characters are after word "example" (7 in that case...). My idea was to loop that string and count every character, but how to stop it before that requied word? Thanks for every idea!
check this out
NSString *sample = #"This is example string";
NSRange b = [sample rangeOfString:#"example"];
if (b.location != NSNotFound) {
NSLog(#"%d characters before", b.location);
NSLog(#"%d characters after", [sample length] - b.location - b.length);
}
I have string as follows in objective c
NSString *str = #"access_token=E2JmCPLtVySGn-cGGJGGnQ&email=abc#gmail.com";
How can i get only E2JmCPLtVySGn-cGGJGGnQ ?
You can use a Regular Expression (RegEx) to find character patterns.
The pattern matching syntax can be found in the ICU User Guide Regular Expressions
In the example the pattern is: find the first "=" and all characters up to but not including the character "&". In the pattern '(?<=access_token=)" is a look-behind assertion meaning that the "access_token=" must precede the matched text, "[^&]+" the brackets the "[]" mean a character class, the "^" al but the following character, the "+" means one or more.
NSString *str = #"access_token=E2JmCPLtVySGn-cGGJGGnQ&email=abc#gmail.com";
NSString *regexPattern = #"(?<=access_token=)[^&]+";
NSString *found = nil;
NSRange range = [str rangeOfString:regexPattern options:NSRegularExpressionSearch];
if (range.location != NSNotFound) {
found = [str substringWithRange:range];
}
NSLog(#"Range: %#", NSStringFromRange(range));
NSLog(#"found: %#", found);
NSLog output if found:
Range: {13, 22}
found: E2JmCPLtVySGn-cGGJGGnQ
There is a method of the NSString class called rangeOfString: that returns an NSRange struct. If you know that your returned value always has the text access_token= and also includes &email and the format is always the same, you can use this rangeOfString: method to sniff out the token.
NSRange accessTokenRange = [str rangeOfString:#"access_token="];
//this would return (0,13) for index:0, length: 13
NSRange emailRange = [str rangeOfString:#"&email="];
//this would return (34,7)
NSInteger tokenLength = ( emailRange.location + 1 ) - accessTokenRange.length;
//the point where &email begins is at index 34, but it starts at 0
//so it's actually the 35th character
//the access_token= string is 13 characters long, so 35-13 = 22
//so you know that the actual token value is 22 characters long
NSRange trueTokenRange = NSMakeRange(accessTokenRange.length,tokenLength);
NSString *tokenSubstring = [str substringWithRange:trueTokenRange];
I don't think my math is off, zero indexing can introduce off by 1 errors if you're not careful, I usually have NSLog going on each range so I can double check where I need to add or subtract 1. But essentially you'll be starting at the 14th character, which is index 13 of the string, and reading the next 22 characters.
I have to count how many decimal digits are there in a double in Xcode 5. I know that I must convert my double in a NSString, but can you explain me how could I exactly do? Thanks
A significant problem is that a double has a fractional part which has no defined length. If you know you want, say, 3 fractional digits, you could do:
[[NSString stringWithFormat:#"%1.3f", theDoubleNumber] length]
There are more elegant ways, using modulo arithmetic or logarithms, but how elegant do you want to be?
A good method could be to take your double value and, for each iteration, increment a counter, multiply your value by ten, and constantly check if the left decimal part is really near from zero.
This could be a solution (referring to a previous code made by Graham Perks):
int countDigits(double num) {
int rv = 0;
const double insignificantDigit = 8;
double intpart, fracpart;
fracpart = modf(num, &intpart);
while ((fabs(fracpart) > 0.000000001f) && (rv < insignificantDigit))
{
num *= 10;
fracpart = modf(num, &intpart);
rv++;
}
return rv;
}
You could wrap the double in an instance of NSNumber and get an NSString representation from the NSNumber instance. From there, calculating the number of digits after the decimal could be done.
One possible way would be to implement a method that takes a double as an argument and returns an integer that represents the number of decimal places -
- (NSUInteger)decimalPlacesForDouble:(double)number {
// wrap double value in an instance of NSNumber
NSNumber *num = [NSNumber numberWithDouble:number];
// next make it a string
NSString *resultString = [num stringValue];
NSLog(#"result string is %#",resultString);
// scan to find how many chars we're not interested in
NSScanner *theScanner = [NSScanner scannerWithString:resultString];
NSString *decimalPoint = #".";
NSString *unwanted = nil;
[theScanner scanUpToString:decimalPoint intoString:&unwanted];
NSLog(#"unwanted is %#", unwanted);
// the number of decimals will be string length - unwanted length - 1
NSUInteger numDecimalPlaces = (([resultString length] - [unwanted length]) > 0) ? [resultString length] - [unwanted length] - 1 : 0;
return numDecimalPlaces;
}
Test the method with some code like this -
// test by changing double value here...
double testDouble = 1876.9999999999;
NSLog(#"number of decimals is %lu", (unsigned long)[self decimalPlacesForDouble:testDouble]);
results -
result string is 1876.9999999999
unwanted is 1876
number of decimals is 10
Depending on the value of the double, NSNumber may do some 'rounding trickery' so this method may or may not suit your requirements. It should be tested first with an approximate range of values that your implementation expects to determine if this approach is appropriate.
For an app I'm working on, I need to check if a text field contains only the letters A, T, C, or G. Furthermore, I would like to make specialized error messages for any other inputed characters. ex) "Don't put in spaces." or "The letter b isn't an accepted value." I have read a couple other posts like this, but they are alphanumeric, I only want specified characters.
One approach for you, far from unique:
NString has methods to find substrings, represented as an NSRange of location & offset, made up from characters in a given NSCharacterSet.
The set of what should be in the string:
NSCharacterSet *ATCG = [NSCharacterSet characterSetWithCharactersInString:#"ATCG"];
And the set of what shouldn't:
NSCharacterSet *invalidChars = [ATCG invertedSet];
You can now search for any range of characters consisting of invalidChars:
NSString *target; // the string you wish to check
NSRange searchRange = NSMakeRange(0, target.length); // search the whole string
NSRange foundRange = [target rangeOfCharacterFromSet:invalidChars
options:0 // look in docs for other possible values
range:searchRange];
If there are no invalid characters then foundRange.location will be equal to NSNotFound, otherwise you change examine the range of characters in foundRange and produce your specialised error messages.
You repeat the process, updating searchRange based on foundRange, to find all the runs of invalid characters.
You could accumulate the found invalid characters into a set (maybe NSMutableSet) and produce the error messages at the end.
You can also use regular expressions, see NSRegularExpressions.
Etc. HTH
Addendum
There is a really simple way to address this, but I did not give it as the letters you give suggest to me you may be dealing with very long strings and using provided methods as above may be a worthwhile win. However on second thoughts after your comment maybe I should include it:
NSString *target; // the string you wish to check
NSUInteger length = target.length; // number of characters
BOOL foundInvalidCharacter = NO; // set in the loop if there is an invalid char
for(NSUInteger ix = 0; ix < length; ix++)
{
unichar nextChar = [target characterAtIndex:ix]; // get the next character
switch (nextChar)
{
case 'A':
case 'C':
case 'G':
case 'T':
// character is valid - skip
break;
default:
// character is invalid
// produce error message, the character 'nextChar' at index 'ix' is invalid
// record you've found an error
foundInvalidCharacter = YES;
}
}
// test foundInvalidCharacter and proceed based on it
HTH
Use NSRegulareExpression like this.
NSString *str = #"your input string";
NSRegularExpression *regEx = [NSRegularExpression regularExpressionWithPattern:#"A|T|C|G" options:0 error:nil];
NSArray *matches = [regEx matchesInString:str options:0 range:NSMakeRange(0, str.length)];
for (NSTextCheckingResult *result in matches) {
NSLog(#"%#", [str substringWithRange:result.range]);
}
Also for the options parameter you have to look in the documentation to pick one that fits.
Look at the NSRegularExpression class reference.
Visit: https://developer.apple.com/library/mac/documentation/Foundation/Reference/NSRegularExpression_Class/Reference/Reference.html