NSString intValue not working for retrieving phone number - objective-c

I have a phone number formatted as an easy to read phone number, i.e., (123) 123-4567
However, when I want to use that phone number in code, I need to parse that string into a number variable (such as an int)
However, [string intValue]; doesn't work - I've used intValue about a million times in previous projects, all with no problem, however here, every string I pass in, I get the same, random int back out:
- (int)processPhoneNumber:(NSString *)phoneNumber {
NSMutableString *strippedString = [NSMutableString stringWithCapacity:10];
for (int i=0; i<[phoneNumber length]; i++) {
if (isdigit([phoneNumber characterAtIndex:i])) {
[strippedString appendFormat:#"%c",[phoneNumber characterAtIndex:i]];
}
}
NSLog(#"clean string-- %#", strippedString);
int phoneNumberInt = [strippedString intValue];
NSLog(#"**** %d\n &i", phoneNumberInt, phoneNumberInt);
return phoneNumberInt;
}
Then when I call this method:
NSLog(#"%i", [self processPhoneNumber:self.phoneNumberTextField.text]);
I get: 2147483647. Every input I give this method returns: 2147483647

As CRD has already explained, you're trying to convert that string to a type that's too small to hold the value, and you're getting back the maximum possible value for that type.
Your real problem is deeper, however. A phone "number" isn't really a number. It doesn't represent a quantity. You would never perform arithmetic on one. It's actually a string of digits, and you should handle it that way. Don't convert it; just operate on the string.
See also What's the right way to represent phone numbers?

2147483647 is INT_MAX which is returned on overflow. How large is your phone number, will it fit into an int? Maybe you should use longLongValue?

Related

Count number of arbitrary repeating decimal numbers in NSString

In my code, I'm dealing with an NSString that contains an NSNumber value. This NSNumber value could possibly be a repeating decimal number (e.x. 2.333333333e+06) that shortens to "2.333333" in a string format. It could also be a terminating number (e.x. 2.5), negative, or irrational number (2.398571892858...) (only dealing with decimals here)
I need to have a way to figure out if there are the repeating numbers in the string (or the NSNumber, if necessary). In my code, I would have no way to know what the repeating number would be, as it's a result of computations started by the user. I have tried this for loop (see below) that doesn't work the way I want it to, due to my inexperience with string indexing/ranges/lengths.
BOOL repeat = NO; //bool to check if repeating #
double repNum, tempNum; //run in for loop
NSString *repeating = [numVal stringValue]; //string that holds possible repeating #
for (int i = 3; i <= [repeating length]-3; i++) { //not sure about index/length here
if (i == 3) {
repNum = [repeating characterAtIndex:i];
}
tempNum = [repeating characterAtIndex:i];
if (tempNum == repNum) {
repeat = YES;
} else {
repeat = NO;
}
}
This code doesn't work as I'd like it to, mainly because I also have to account for negative dashes in the string and different amounts of numbers (13 1/3 vs. 1 1/3). I've used the modffunction to separate the integers from the decimals, but that hasn't worked well for me either.
Thank you in advance. Please let me know if I can clarify anything.
EDIT:
This code works with the finding of different solutions for polynomials (quadratic formula). Hope this helps put it into context. See here. (Example input)
NSNumber *firstPlusSolution, *secondMinusSolution;
NSString *pValueStr, *mValueStr;
firstPlusSolution = -(b) + sqrt(square(b) - (4)*(a)*(c)); //a, b, c: "user" provided
firstPlusSolution /= 2*(a);
secondMinusSolution = -(b) - sqrt(square(b) - 4*(a)*(c));
secondMinusSolution /= 2*(a);
pValueStr = [firstPlusSolution stringValue];
mValueStr = [secondMinusSolution stringValue];
if ([NSString doesString:pValueStr containCharacter:'.']) { //category method I implemented
double fractionPart, integerPart;
fractionPart = modf(firstPlusSolution, &integerPart);
NSString *repeating = [NSString stringWithFormat:#"%g", fractionPart];
int repNum, tempNum;
BOOL repeat = NO;
//do for loop and check for negatives, integers, etc.
}
if ([NSString doesString:mValueStr containCharacter'.']) {
//do above code
//do for loop and check again
}
Use C. Take the fractional part. Convert to a string with a known accuracy. If length of string indicates that last digits are missing, then it does not repeat. Use NSString-UTF8String to convert a string. Get rid of the last digit (may be rounding or actual floating point arithmetic error). Use function int strncmp ( const char * str1, const char * str2, size_t num ) to perform comparison within the string itself. If the result is 8 characters long and the last 2 characters match the first 2 characters, then shall the first 6 characters be considered repeating?
Assuming that fraction knowledge your desire:
• Possibility 1: Use fractions. Input fractions. Compute with fractions. Output fractions. Expand upon one of the many examples of a c++ fraction class if necessary and use it.
• Possibility 2: Choose an accuracy which is much less than double. Make a fraction from the result. Reduce the fraction allowing rounding based upon accuracy.
I suggest use not optimal but easy to write solution
Create NSMutableDictionary that will contain number as key and count of occurrence as value.
You can use componentsSeparatedByString: if numbers in string delimited by known symbol
In loop check valueForKey in dictionary and if need increase value
Last step is analyzing our dictionary and do anything you need with numbers

Concatenating an int to a string in Objective-c

How do I concatenate the int length to the string I'm trying to slap into that array so it is "C10" given length == 10, of course. I see #"%d", intVarName way of doing it used else where. In Java I would of done "C" + length;. I am using the replaceObjectAtIndex method to replace the empty string, "", that I have previously populated the MSMutableArray "board" with. I am getting an error though when I add the #"C%d", length part at the end of that method (second to last line, above i++).
As part of my homework I have to randomly place "Chutes" (represented by a string of format, "C'length_of_chute'", in this first assignment they will always be of length 10 so it will simply be "C10") onto a game board represented by an array.
-(void)makeChutes: (int) length {// ??Change input to Negative number, Nvm.
//??Make argument number of Chutes ??randomly?? across the board.
for(int i = 0; i < length;){
int random = arc4random_uniform(101);
if ([[board objectAtIndex:random] isEqual:#""]) {
//[board insertObject:#"C%d",length atIndex:random];
[board replaceObjectAtIndex:random withObject:#"C%d",length];
i++;
}
}
}
Please ignore the extra and junk code in there, I left it in for context.
In Objective-C the stringWithFormat method is used for formatting strings:
NSString *formattedString = [NSString stringWithFormat:#"C%d", length];
[someArray insertObject:formattedString];
It's often easier to create your formatted string on a line of its own in Objective-C, since as you can see the call can be fairly verbose!

How to compare size of string in Objective-C?

I have an NSString in Objective-C that I want to find the size of and then compare it to some number; however, I'm not sure what the proper way to do this is?
What I have so far is a property called display which is a UILabel * and what I'm thinking of doing is the following:
NSUInteger size = [self.display.text length];
However, now I want to compare this size with a 0. But I'm not sure what the proper way to do this? I've thought of doing the following, but for some reason this doesn't seem right:
if(size == 1) { doSomething};
Any help? Thanks
Yes, that is the proper way to do it. If you want to check if there is a string whose length is greater than 0 i.e. not just #"", compare it with zero like this
NSUInteger size = [self.display.text length];
if(size>0) {
//do something
};
You can just use -[NSString length]. This just returns the number of characters in the string. NSString abstracts the encoding of its underlying buffer, but length should abtract that from you! This is different from std::string.size() or strlen, which will return the byte count, independent of encoding.
Thus, you may write 0 == str.length to determine if the string is empty, or 1 == str.length to determine if it is one character (encoding-safe).

Converting NSString to a decimal

I need to change the code below to make "intAmount" a decimal or an integer (i.e. a person can enter .10 or 1) in my uitextfield. The last line "myProduct" has to be a decimal not an integer and return the product in the format "18.00" for example. Can someone help someone help me alter my code snippit for this?
//amt has to be converted into a decimal value its a NSString now
NSInteger intAmount = [amt intValue];
//where total gets updated in the code with some whole (integer) value
NSInteger total=0;
//Change myProduct to a decimal with presicion of 2 (i.e. 12.65)
NSInteger myProduct=total*intAmount;
THIS DOESN'T WORK
NSDecimalNumber intAmount = [amt doubleValue];
//Keep in mind totalCost is an NSInteger
NSDecimalNumber total=totalCost*intAmount;
Use doubleValue instead of intValue to get the correct fractional number out of your text field. Put it in a variable of type double rather than NSInteger. Then use the format %.2g when you print it out and it will look like you want it to.
If you need to track decimal values explicitly, you can use NSDecimalNumber. However, if all you're doing is this one operation, Carl's solution is most likely adequate.
If you have a string representation of a real number (non-integer), you can use an NSScanner object to scan it into a double or float, or even an NSDecimal structure if that is your true intention (the NSDecimal struct and NSDecimalNumber class are useful for containing numbers that can be exactly represented in decimal).
NSString *amt = #"1.04";
NSScanner *aScanner = [NSScanner localizedScannerWithString:amt];
double theValue;
if ([aScanner scanDouble:&theValue])
{
// theValue should equal 1.04 (or thereabouts)
}
else
{
// the string could not be successfully interpreted
}
The benefit to using a localised NSScanner object is that the number is interpreted based on the user's locale, because “1.000” could mean either one-thousand or just one, depending on your locale.

Problem while converting NSData to int

Using foundation and cocoa frameworks on Mac, I am trying to convert an NSData object in humanly understandable number.
Let say the NSData object is an image of NPIXEL. I know the binary data are coded in big endian and represent 32 bit integer (to be more precise 32 bit two complements integer). I write the piece of code bellow to convert the NSData into an int array. But the value I got are completely wrong (this does not means the measurement are bad, I used a special software to read the data and the value given by the software are different from the one I got with my code).
-(int *) GetArrayOfLongInt
{
//Get the total number of element into the Array
int Nelements=[self NPIXEL];
//CREATE THE ARRAY
int array[Nelements];
//FILL THE ARRAY
int32_t intValue;
int32_t swappedValue;
double Value;
int Nbit = abs(BITPIX)*GCOUNT*(PCOUNT + Nelements); Nbit/=sizeof(int32_t);
int i=0;
int step=sizeof(int32_t);
for(int bit=0; bit < Nbit; bit+=step)
{
[Img getBytes:&swappedValue range:NSMakeRange(bit,step)];
intValue= NSSwapBigIntToHost(swappedValue);
array[i]=intValue;
i++;
}
return array;
}
This piece of code (with minor change) work perfectly when the binary data represent float or double, but I dont when it is 16,32 or 64 bit integer. I also tried changingNSSapBigIntToHostintoNSSwapLittleInttoHost`. I even tried with long, but the results is still the same, I got bad values. What wrong I am doing ?
PS: Some of the variable in my code are already set elsewhere in my program. BITPIX is the bit size of each pixel. In this case 32. GCOUNT is equal to 1, PCOUNT 0 and Nelements is the total number of pixel I should have in my image.
Returning a pointer to a local variable is a very bad idea. array could get overwritten at any time (or if you were to write through the pointer, you could corrupt the stack). You probably want something like:
// CREATE THE ARRAY
int *array = malloc(Nelements * sizeof(int));
Your algorithm seems a bit overkill, too. Why not just copy out the whole array from the NSData object, and then byteswap the entries in place? Something like:
int32_t length = [Img length];
int32_t *array = malloc(length);
[Img getBytes:array length:length];
for (i = 0; i < length/sizeof(int32_t); i++)
{
array[i] = NSSwapBigIntToHost(array[i]);
}