Getting numbers from a string in iPhone programming - iphone

I have a string. It's always 3 letters long, and it can be counted on to only contain three integers. Say it looks like this:
NSString * numberString = #"123";
Now, I want to extract those numbers from it. 1, 2 and 3. In any other language I'd just fetch the character for each position and parse it, or even cast it.
However, Objective-C doesn't seem to have that. I found some other answer recommending that i use the characterAtIndex method, use numberWithChar on that, and then subtract the number "48" from it, leaving even myself scratching my head at the apparent stupidity of it all.
Is there no other, more elegant way to do this?
I tried using substringWithRange, but apparently there's no method for creating an NSRange, and it's incompatible with CFRangeMake for some reason.

How about [[numberString substringWithRange:NSMakeRange(0,1)] intValue]?

int n=[#"123" intValue];
From this you can get the individual numbers by n/100, n/10 and n%10.

How about this?
NSString * numberString = #"123";
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
NSNumber *number = [formatter numberFromString:numberString];
int n = [number intValue];
(Don't forget to release the formatter after you finish your conversions.)

NSString *numberString = #"123";
int firstDigit = [numberString characterAtIndex:0] - '0';
int secondDigit = [numberString characterAtIndex:1] - '0';
int thirdDigit = [numberString characterAtIndex:2] - '0';
NSLog(#"Your digits are %d, %d, %d", firstDigit, secondDigit, thirdDigit);
If you want to cheat:
char *numberString = [#"123" cStringUsingEncoding:NSASCIIStringEncoding];
printf(#"Your digits are %d, %d, %d\n", numberString[0] - '0',
numberString[1] - '0',
numberString[2] - '0');

Related

Elegant method to omit fraction formatting number if number is an integer

I am formatting floating point numbers and right now I have the %0.2f formatter, but I'd like to omit the .00 if the floating point number is an even integer.
Of course I can think of string replacing the .00, but that's crude.
I found that the description of NSNumber also does something similar:
NSNumber *number = [NSNumber numberWithFloat:_paragraphSpacing];
[retString appendFormat:#"margin-bottom:%#px;", number];
This this does hover not limit the post comma digits. if the number is 1234.56789 then the description will output that.
So my question is, is there a just as simple way - possibly without having to create an NSNumber object - to achieve this result?
Since floating-point numbers aren't exact, there's no guarantee that your number will actually be an integer. You can, however, check if it's within a reasonably small distance from an integer value. And of course you don't need an NSNumber for this. (Generally speaking, NSNumber is not used for formatting, its purpose is representing a primitive C type, either integral or floating-point types, using an Objective-C object.)
#include <math.h>
- (NSString *)stringFromFloat:(float)f
{
const float eps = 1.0e-6;
if (abs(round(f) - f) < eps) {
// assume an integer
return [NSString stringWithFormat:#"margin-bottom: %.0fpx", round(f)];
} else {
// assume a real number
return [NSString stringWithFormat:#"margin-bottom: %.2fpx", f];
}
}
Use a formatter:
NSNumberFormatter* formatter= [NSNumberFormatter new];
formatter.numberStyle= NSNumberFormatterDecimalStyle;
formatter.maximumFractionDigits=2;
NSNumber *number = [NSNumber numberWithFloat:_paragraphSpacing];
[retString appendFormat:#"margin-bottom:%#;", [formatter stringFromNumber: number]];
You can use an NSNumberFormatter for this:
static NSNumberFormatter *numberFormatter = nil;
if (numberFormatter == nil) {
numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.minimumFractionDigits = 0;
numberFormatter.maximumFractionDigits = 2;
numberFormatter.usesGroupingSeparator = NO;
}
NSString *formattedNumberString = [numberFormatter
stringForNumber:[NSNumber numberWithDouble: _paragraphSpacing]];
You can use C function modff to get the fraction part and test it:
float fractionPart = 0.;
modff(_paragraphSpacing, &fractionPart);
if( fabsf(fractionPart) < 0.01 ) {
// format as integer
[retString appendFormat:#"margin-bottom:%d", (int)_paragraphSpacing];
} else {
// format as float
[retString appendFormat:#"margin-bottom:%0.2f", _paragraphSpacing];
}

NSNumberFormatter to show a maximum of 3 digits

I would like to make it so one of my UILabels only shows a maximum of 3 digits. So, if the associated value is 3.224789, I'd like to see 3.22. If the value is 12.563, I'd like to see 12.5 and if the value is 298.38912 then I'd like to see 298. I've been trying to use NSNumberFormatter to accomplish this, but when I set the maximum significant digits to 3 it always has 3 digits after the decimal place. Here's the code:
NSNumberFormatter *distanceFormatter = [[[NSNumberFormatter alloc] init] autorelease];
[distanceFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[distanceFormatter setAlwaysShowsDecimalSeparator:NO];
[distanceFormatter setMaximumSignificantDigits:3];
I always thought 'significant digits' meant all the digits, before and after the decimal point. Anyway, is there a way of accomplishing this using NSNumberFormatter?
Thanks!
I believe that
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
formatter.usesSignificantDigits = YES;
formatter.maximumSignificantDigits = 3;
will do exactly what you want, i.e. it will always show exactly 3 digits, be it 2 before the decimal and 1 after or 1 before the decimal and 2 after.
Perhaps you also have to set (not sure though):
[distanceFormatter setUsesSignificantDigits: YES];
But in your case it's probably much easier to just use the standard string formatting:
CGFloat yourNumber = ...;
NSString* stringValue = [NSString stringWithFormat: #"%.3f", yourNumber];
(note: this will round the last digit)
Heres a small function I wrote:
int nDigits(double n)
{
n = fabs(n);
int nDigits = 0;
while (n > 1) {
n /= 10;
nDigits++;
}
return nDigits;
}
NSString *formatNumber(NSNumber *number, int sigFigures)
{
double num = [number doubleValue];
int numDigits = nDigits(num);
NSString *format = [NSString stringWithFormat:#"%%%i.%ilf", sigFigures -= numDigits, sigFigures];
return [NSString stringWithFormat:format, num];
}
In my tests, this worked fine.

iphone NSString stringWithFormat and float

I have an input with UIKeyboardTypeDecimalPad and I need my user to input a float (with unlimited characters after a dot). After the input I filter the string with :
NSString *newValue = [NSString stringWithFormat:#"%.f",[textField.text floatValue]]
But that gives me a lot of unnecessary digits after a dot (for example for 2.25 it gives 2.249999).
All I need is to filter the input so it'll be a legal float (digits and not more than one dot).
How do I do that?
NSString *newValue = [NSString stringWithFormat:#"%0.1f", [textField.text floatValue]];
the number after the dot is the number of decimal places you want.
UPDATE:
You could use string manipulation to determine the number of decimal places the user typed in (don't forget to check for edge cases):
NSInteger numberOfDecimalPlaces = textString.length - [textString rangeOfString:#"."].location - 1;
and then if you want to create a new string with a new float to the same level of display precision you could use:
NSString *stringFormat = [NSString stringWithFormat:#"%%0.%if", numberOfDecimalPlaces];
NSString *newString = [NSString stringWithFormat:stringFormat, newFloat];
Not sure if this is what you want but try something like the following:
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
// set to long number of decimals to accommodate whatever a user might enter
[nf setMaximumFractionDigits:20];
NSString *s = [nf stringFromNumber:
[NSNumber numberWithDouble:[userEnteredNumberString doubleValue]]
];
NSLog(#"final:%#",s);
Try using a double instead of float. I think the double removes all trailing zero's.

Unexpected result from "stringWithFormat:"

What would be the expected result from the following Objective C code?
int intValue = 1;
NSString *string = [NSString stringWithFormat:#"%+02d", intValue];
I thought the value of string would be "+01", it turns out to be "+1". Somehow "0" in format string "+01" is ignored. Change code to:
int intValue = 1;
NSString *string = [NSString stringWithFormat:#"%02d", intValue];
the value of string is now "01". It does generate the leading "0". However, if intValue is negative, as in:
int intValue = -1;
NSString *string = [NSString stringWithFormat:#"%02d", intValue];
the value of string becomes "-1", not "-01".
Did I miss anything? Or is this a known issue? What would be the recommended workaround?
Thanks in advance.
#Mark Byers is correct in his comment. Specifying '0' pads the significant digits with '0' with respect to the sign '+/-'. Instead of '0' use dot '.' which pads the significant digits with '0' irrespective of the sign.
[... stringWithFormat:#"%+.2d", 1]; // Result is #"+01"
[... stringWithFormat:#"%.2d", -1]; // Result is #"-01"
NSString *string = [NSString stringWithFormat:#"+0%d", intValue];
NSString *string = [NSString stringWithFormat:#"-0%d", intValue];

What is a better way to check if a string is an integer on iPhone?

The following code will identify if a string is an integer - that is, the string contains only digits. But, I hate this code. What is a better way?
NSString *mightBeAnInteger = fooString;
int intValue = [fooString intValue];
if (intValue > 0
&& [[NSString stringWithFormat:#"%d",intValue] isEqualToString:mightBeAnInteger]) {
NSLog(#"mightBeAnInteger is an integer");
}
[fooString rangeOfCharacterFromSet:[[NSCharacterSet decimalDigitCharacterSet] invertedSet]].location == NSNotFound will be YES if the string only has number characters in it.
Note that this doesn't catch negative numbers, so you'll have to add in the negative sign (probably by grabbing a mutableCopy and adding the sign).
-(BOOL) stringIsNumeric:(NSString *) str {
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
NSNumber *number = [formatter numberFromString:str];
[formatter release];
return !!number; // If the string is not numeric, number will be nil
}
source: Objective c: Check if integer/int/number