Checking input value - iphone

I am trying to check whether the user gives an input that is number but not letters. When a non-numeric value is given I want to print an alert error message like "incorrect format".
This is my source code:
-(IBAction)btnPressed{
NSString *firstString = textFiled1.text;
NSString *secondString = textFiled2.text;
NSString *thirdString = textFiled3.text;
int num1;
int num2;
int num3;
int output;
num1 = [firstString intValue];
num2 = [secondString intValue];
num3 = [thirdString intValue];
output = (num1 + num2) / num3;
lable1.text = [NSString stringWithFormat:#"%d",output];
}

Use NSNumberFormatter. If the input parameter is not a valid number, the number derived will be nil.
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
num1 = [f numberFromString:firstString];
[f release];
if (num1 == nil) {
// throw exception
}

This is how I would do it:
NSCharacterSet *nonNumbers = [[NSCharacterSet decimalDigitCharacterSet] invertedSet];
if ([firstString rangeOfCharacterFromSet:nonNumbers].location != NSNotFound) {
// firstString has non-number characters in it!
}

Related

NSString to int issue

When I want to convert NSString to int
I use:
[string intValue];
But how to determine if string is int value? for instance to avoid situations like this:
[#"hhhuuukkk" intValue];
int value;
NSString *s = #"huuuk";
if([[NSScanner scannerWithString:s] scanInt:&value]) {
//Is int value
}
else {
//Is not int value
}
Edit: added isAtEnd check according to Martin R's suggestion. This will make sure it is only digits in the whole string.
int value;
NSString *s = #"huuuk";
NSScanner *scanner = [NSScanner scannerWithString:s];
if([scanner scanInt:&value] && [scanner isAtEnd]) {
//Is int value
}
else {
//Is not int value
}
The C way: use strtol() and check errno:
errno = 0;
int n = strtol(str.UTF8String, NULL, 0);
if (errno != 0) {
perror("strtol");
// or handle error otherwise
}
The Cocoa way: use NSNumberFormatter:
NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
[fmt setGeneratesDecimalNumbers:NO];
NSNumber *num = nil;
NSError *err = nil;
NSRange r = NSMakeRange(0, str.length);
[fmt getObjectValue:&num forString:str range:&r error:&err];
if (err != nil) {
// handle error
} else {
int n = [num intValue];
}
NSString *yourStr = #"hhhuuukkk";
NSString *regx = #"(-){0,1}(([0-9]+)(.)){0,1}([0-9]+)";
NSPredicate *chekNumeric = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", regx];
BOOL isNumber = [chekNumeric evaluateWithObject:yourStr];
if(isNumber)
{
// Your String has only numeric value convert it to intger;
}
else
{
// Your String has NOT only numeric value also others;
}
For only integer value change Rgex pattern to ^(0|[1-9][0-9]*)$ ;
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber * amt = [f numberFromString:#"STRING"];
if(amt)
{
// convert to int if you want to like you have done in your que.
//valid amount
}
else
{
// not valid
}
NSString *stringValue = #"hhhuuukkk";
if ([[NSScanner scannerWithString:stringValue] scanInt:nil]) {
//Is int value
}
else{
//Is not int value
}
[[NSScanner scannerWithString:stringValue] scanInt:nil] will check if "stringValue" has an integer value.
It returns a BOOL indicating whether or not it found a suitable int value.

convert from string to int

i have this code:
NSString * firstdDigitTest = [numberString substringToIndex:1];
if (! [firstdDigitTest isEqualToString:#"0"])
{
numberString = [numberString substringFromIndex:1];
self.firstImageName = [namefile stringByAppendingString:firstdDigitTest];
}
self.number = [numberString integerValue];
i check if the first number is not 0 and if it's not 0 i need to insert it to the firstImageName. But when i do it (using the substringFromIndex) and i try to use integerValue it's dosent work!
without the substringFromIndex it's works! :(
NSString *str0 = #"XXX10098";
NSString *str1 = [str0 substringWithRange:NSMakeRange(4, str0.length-4)];
NSLog(#"%#", str1);
NSLog(#"%d", [str1 intValue]);
2012-10-28 10:52:07.309 iFoto[5652:907] 0098
2012-10-28 10:52:07.312 iFoto[5652:907] 98
check [numberString intValue];

Formatting a string containing a number with comma separation

I have a number stored in an NSMutableString instance which I want to auto format with comma delimiters and then display the result in a UITextField.
I've tried using NSNumberFormatter to format as currency, but I don't want it to show decimals if the original NSMutableString doesn't contain a decimal place.
For example:
If the NSMutableString contains "1234567", it should format as "1,234,567".
If the NSMutableString contains "1234567.1", it should format as "1,234,567.1"
If the NSMutableString contains "1234567.12", it should format as "1,234,567.12"
The maximum decimals that the NSMutableString will contain is 2.
Any help is greatly appreciated.
Thanks!
Keep in mind that you should really be localizing this if you are interacting with users on this, however here is one way to do it:
- (NSString *)formatString:(NSString *)string {
// Strip out the commas that may already be here:
NSString *newString = [string stringByReplacingOccurrencesOfString:#"," withString:#""];
if ([newString length] == 0) {
return nil;
}
// Check for illegal characters
NSCharacterSet *disallowedCharacters = [[NSCharacterSet characterSetWithCharactersInString:#"0123456789."] invertedSet];
NSRange charRange = [newString rangeOfCharacterFromSet:disallowedCharacters];
if ( charRange.location != NSNotFound) {
return nil;
}
// Split the string into the integer and decimal portions
NSArray *numberArray = [newString componentsSeparatedByString:#"."];
if ([numberArray count] > 2) {
// There is more than one decimal point
return nil;
}
// Get the integer
NSString *integer = [numberArray objectAtIndex:0];
NSUInteger integerDigits = [integer length];
if (integerDigits == 0) {
return nil;
}
// Format the integer.
// You can do this by first converting to a number and then back to a string,
// but I would rather keep it as a string instead of doing the double conversion.
// If performance is critical, I would convert this to a C string to do the formatting.
NSMutableString *formattedString = [[NSMutableString alloc] init];
if (integerDigits < 4) {
[formattedString appendString:integer];
} else {
// integer is 4 or more digits
NSUInteger startingDigits = integerDigits % 3;
if (startingDigits == 0) {
startingDigits = 3;
}
[formattedString setString:[integer substringToIndex:startingDigits]];
for (NSUInteger index = startingDigits; index < integerDigits; index = index + 3) {
[formattedString appendFormat:#",%#", [integer substringWithRange:NSMakeRange(index, 3)]];
}
}
// Add the decimal portion if there
if ([numberArray count] == 2) {
[formattedString appendString:#"."];
NSString *decimal = [numberArray objectAtIndex:1];
if ([decimal length] > 0) {
[formattedString appendString:decimal];
}
}
return formattedString;
}
// Test cases:
NSLog(#"%#", [self formatString:#"123456"]);
NSLog(#"%#", [self formatString:#"1234567."]);
NSLog(#"%#", [self formatString:#"12345678.1"]);
NSLog(#"%#", [self formatString:#"123456789.12"]);
// Output:
123,456
1,234,567.
12,345,678.1
123,456,789.12
I think this should do it -- I added an if statement to check if there is a decimal point in the typed in value. "Output" in this example is a property that I have bound to the value of a text field to show the result.
-(IBAction)doConversion:(id)sender{
NSNumberFormatter *formatter = [[NSNumberFormatter alloc]init];
[formatter setMaximumFractionDigits:2];
[formatter setUsesGroupingSeparator:YES];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
double entryFieldFloat = [entryField doubleValue];
if ([entryField.stringValue rangeOfString:#"."].length == 1) {
formatter.alwaysShowsDecimalSeparator = YES;
self.output =[formatter stringFromNumber:[NSNumber numberWithDouble:entryFieldFloat]];
}else{
formatter.alwaysShowsDecimalSeparator = NO;
self.output =[formatter stringFromNumber:[NSNumber numberWithDouble:entryFieldFloat]];
}
}
Just call this method to be simple:
public static String GetCommaSeparatedCount(this Int32 Count)
{
// Check for The less-than character (<) is converted to <
String result = String.Format("{0:#,##0}", Count);
return result;
}
You're looking for the -setMinimumFractionDigits: method on NSNumberFormatter. Set that to 0 and it'll only display the decimal point if there's anything to put after it.

How to convert Hex to Binary iphone

I need to convert a hex string to binary form in objective-c, Could someone please guide me?
For example if i have a hex string 7fefff78, i want to convert it to 1111111111011111111111101111000?
BR,
Suppi
Nice recursive solution...
NSString *hex = #"49cf3e";
NSUInteger hexAsInt;
[[NSScanner scannerWithString:hex] scanHexInt:&hexAsInt];
NSString *binary = [NSString stringWithFormat:#"%#", [self toBinary:hexAsInt]];
-(NSString *)toBinary:(NSUInteger)input
{
if (input == 1 || input == 0)
return [NSString stringWithFormat:#"%u", input];
return [NSString stringWithFormat:#"%#%u", [self toBinary:input / 2], input % 2];
}
Simply convert each digit one by one: 0 -> 0000, 7 -> 0111, F -> 1111, etc. A little lookup table could make this very concise.
The beauty of number bases that are powers of another base :-)
In case you need leading zeros, for example 18 returns 00011000 instead of 11000
-(NSString *)toBinary:(NSUInteger)input strLength:(int)length{
if (input == 1 || input == 0){
NSString *str=[NSString stringWithFormat:#"%u", input];
return str;
}
else {
NSString *str=[NSString stringWithFormat:#"%#%u", [self toBinary:input / 2 strLength:0], input % 2];
if(length>0){
int reqInt = length * 4;
for(int i= [str length];i < reqInt;i++){
str=[NSString stringWithFormat:#"%#%#",#"0",str];
}
}
return str;
}
}
NSString *hex = #"58";
NSUInteger hexAsInt;
[[NSScanner scannerWithString:hex] scanHexInt:&hexAsInt];
NSString *binary = [NSString stringWithFormat:#"%#", [self toBinary:hexAsInt strLength:[hex length]]];
NSLog(#"binario %#",binary);
I agree with kerrek SB's answer and tried this.
Its work for me.
+(NSString *)convertBinaryToHex:(NSString *) strBinary
{
NSString *strResult = #"";
NSDictionary *dictBinToHax = [[NSDictionary alloc] initWithObjectsAndKeys:
#"0",#"0000",
#"1",#"0001",
#"2",#"0010",
#"3",#"0011",
#"4",#"0100",
#"5",#"0101",
#"6",#"0110",
#"7",#"0111",
#"8",#"1000",
#"9",#"1001",
#"A",#"1010",
#"B",#"1011",
#"C",#"1100",
#"D",#"1101",
#"E",#"1110",
#"F",#"1111", nil];
for (int i = 0;i < [strBinary length]; i+=4)
{
NSString *strBinaryKey = [strBinary substringWithRange: NSMakeRange(i, 4)];
strResult = [NSString stringWithFormat:#"%#%#",strResult,[dictBinToHax valueForKey:strBinaryKey]];
}
return strResult;
}

ObjC Formatting Decimal places of Float to string

How do I format a float to string so that if the user enters a number that has 2 or less decimal places then it is formatted to have 2 decimal places, but if the user enters a float that has 2 or more decimal places then all decimal places are shown. e.g.
4.1 => 4.10
1 => 1.00
1.358484 => 1.358484
So therefore the formatting is to 2 decimal places or more if needed.
Hope I made sense.
Try something like this.
BOOL requiresExtraPrecision (double num) {
double roundedToHundredth = round(num * 100.0) / 100.0;
double diff = num - roundedToHundredth;
if (diff < 0) diff = 0.0 - diff;
if (diff < 0.0000001) {
return NO;
} else {
return YES;
}
}
NSString *formatted (double num) {
if (requiresExtraPrecision(num)) {
return [NSString stringWithFormat:#"%F", num];
} else {
NSNumberFormatter *formatter = [[[NSNumberFormatter alloc] init] autorelease];
[formatter setMaximumFractionDigits:2];
[formatter setMinimumFractionDigits:2];
return [formatter stringFromNumber:[NSNumber numberWithDouble:num]];
}
}
As #Carl wrote in a comment to the question, the hard part is deciding when a double needs all of its precision. In this code, I'm assuming that if the double is "close enough" to a rounded number (within a millionth), then we should just display the rounded number.
You might decide to make it stricter (a billionth?) but you'll always have to use some kind of approximation, because some decimals can't be stored precisely as a float. Even though the user may have typed "0.1" at input time, that information is lost when the number is stored as a float.
So, given that you'll have a float that's extremely close to a decimal but not exactly right, you'll have to decide when you think the float is "close enough" to the decimal.
If you need absolute precision (if you're working with money!) then you should consider using an NSDecimal or an NSDecimalNumber instead of a float.
this could work for you:
NSNumber *aFloat = [NSNumber numberWithFloat:1.2]; //try 1.234 ; 1.23 ; 1.2 ; 1. ; 1
NSString *numberString = [aFloat stringValue];
NSRange dot;
dot = [numberString rangeOfString:#"."];
NSString *finalString;
if (dot.location != NSNotFound) {
NSString *decimals = [numberString substringFromIndex:dot.location + dot.length];
if (decimals.length<1){ // ends with "."
finalString = [numberString stringByAppendingString:#"00"];
}else if (decimals.length<2){ // ends with ".n"
finalString = [numberString stringByAppendingString:#"0"];
}else { // 2 or more decimals: no changes
finalString = numberString;
}
}else { // no decimals
finalString = [numberString stringByAppendingString:#".00"];
}
NSLog(#"______._____finalString:%#", finalString );
EDIT (more flexible, it works with variable numbers of decimals):
NSNumber *aFloat = [NSNumber numberWithFloat:1.1235]; //try 1.234 ; 1.23 ; 1.2 ; 1. ; 1
NSString *numberString = [aFloat stringValue];
NSRange dot;
dot = [numberString rangeOfString:#"."];
if (dot.location == NSNotFound) { // no decimals, add a dot
numberString = [numberString stringByAppendingString:#"."];
NSLog(#"__added dot___ numberString:%#", numberString );
}
dot = [numberString rangeOfString:#"."];
NSString *decimals = [numberString substringFromIndex:dot.location + dot.length];
// int initialDecimals = decimals.length;
int numberOfDecimalsTerget = 2;
for (int initialDecimals = decimals.length; initialDecimals<numberOfDecimalsTerget; initialDecimals++) {
numberString = [numberString stringByAppendingString:#"0"];
}
NSLog(#"__END_._____numberString:%#", numberString );