Objective C: calculator app - currentNumber = currentNumber * 10 + digit; - objective-c

I am reading "Programming in Objective-C" 4th Ed. by Stephen G. Kochan. In the book, there is a sample code for creating a Calculator application for the iPhone. I understand the code, at least 90% of it. - There is a Fraction class that has methods to store fraction objects and that describe how to perform different basic fraction arithmetic operations
- In addition to that, there is a calculator class that runs the appropriate methods from the Fraction class depending on whether the user is trying to sum, divide etc.
The view controller has the following method for when the user presses a number in the interface:
-(IBAction)clickDigit:(UIButton *)sender {
int digit = sender.tag; //sender or the argument inthis case is the button
[self processDigit:digit];
}
As you see this method is now called:
-(void) processDigit:(int)digit {
currentNumber = currentNumber * 10 + digit;
[displayString appendString:
[NSString stringWithFormat:#"%i", digit]];
display.text = displayString;
}
My ONLY question (and probably the one with the most simple answer) is: Why is currentNumber always multiplied by 10? The value of currentNumber is always 0 by the time the compiler enters the method above (I verified this using the debugger in XCode) so i dont get why we even have to multiply it by 10. I did delete that multiplication and the results are incorrect, i just cannot figure out why yet.
Thank you

Maybe the best way to think about this is with an example.
Imagine the user has clicked the following digits in order: 1, 2. Then, assuming the code is working, the numeric value of currentNumber should be 12.
Now imagine the user next clicks on '3'. Now you want the value to be 123. You can get this by multiplying the previous value (12) by 10 and then adding the 3. If they then click on a '4', the value should become 1,234, which is achieved by 10 * 123 + 4. And so on.

Imagine your calculator has "123" on the screen and you want to turn this into "1234". If it was a string you can add "4" to the end, and it works fine. But it's an integer, and if you add 4 to the integer value you get 127. So what you do is take 123, multiply by 10 to give you 1230, then add the 4 to get 1234.

The debugger must be misleading you, as it sometimes does.
Consider that if taking the multiplication out makes the result wrong then the multiplication obviously does something!
Try the following for debugging only:
int lastCurrentNumber = currentNumber;
currentNumber = 10 * lastCurrentNumber + digit;
Now in the debugger check the values of lastCurrentNumber, currentNumber and digit as you step through these two statements.

The *10 is used to move digits through the various places in decimal numbers (tens place, hundreds place, etc.)
It's kind of a "hack" to avoid having to use an array. Other calculator apps "pop" and "push" digits onto an array, this allows for more powerful operations as well as manipulation of non-decimal numbers (binary, hex, etc.)
The free iOS development course on iTunes U includes a calculator app that uses an array. If you'd like to compare the difference, you can download the source code here:
http://www.stanford.edu/class/cs193p/cgi-bin/drupal/
It also has a Fraction object but doesn't use the *10 method.

Related

Custom NSFormatter to accept only numbers

I have searched for an answer and tried a lot of user examples posted at SO, however they do not seem to answer my question.
In the UK the majority or area codes begin with zero, I have a single NSTextField and have created a customer NSNumberFormatter. I want my NSTextField to accept numbers beginning with zero, I dont want to use the NSNumberFormatter Padding option as the length of phone number may very but always start with zero.
- (BOOL)isPartialStringValid:(NSString*)partialString newEditingString:(NSString**)newString errorDescription:(NSString**)error {
if (partialString.length <= 0 || [partialString rangeOfCharacterFromSet:[[NSCharacterSet characterSetWithCharactersInString:#"0123456789."] invertedSet]].location != NSNotFound) {
NSLog(#"This is not a positive integer");
return NO;
}
return YES; } #end
The above example works and allows any number to be entered of any length but will always removes the leading zero upon moving focus away from the NSTextField.
Example numbers:
01202
01134
01103111345
How can I stop the leading zero being removed?
Thank you for reading.
Have you tried looking at a library to manage phone numbers such as
libPhoneNumber-iOS it's got most of this covered. Granted it maybe overkill if you're just looking at working with UK numbers.
I could copy the code here, but it probably more efficient to check out the framework. It's been around for years and years now so it well tested and I've used it many times when working for o2 in their apps. If you don't decide to use it, just look through the code, you'll find your answer there.
I see you're looking for mac you can do it but it's effort

Object to input the keyboard characters and numbers and dispaly the output in a text field in objective C

I am using NSMutableString object to read input digits from keypad. It is becoming cumbersome with some complex arithmetic operations using this object. Is there any other way to read the input data and display the data in a textfiled?
Below is the code currently being used.
digit = (int)sender.tag;
[displayString appendString: [NSString stringWithFormat:#"%i", digit]];
display.text = displayString;
currentnumber = currentnumber*10 + digit;
It is becoming cumbersome with some complex arithmetic operations using this object.
That's because you're doing things in a cumbersome way. Try this instead:
digit = (int)sender.tag;
currentNumber = currentNumber*10 + digit;
display.text = [NSString stringWithFormat:#"%d", currentNumber];
Don't try to derive the display string separately from the value that you're using for computation. The computation value, currentNumber, is like your data model -- it's the thing that your program is going to operate on. So instead of appending digits to the display string to try to cobble together the string to display, determine the string to display from the number you're working with (or going to work with). That way, if the user hits the √ button, you can do something like:
currentNumber = sqrt(currentNumber);
display.text = [NSString stringWithFormat:#"%d", currentNumber];
You probably should develop a more complete data model than just using a single numeric variable. You want a CalculatorModel class, or something like that, which you can give inputs when the user hits a key, and always get the current output. There's no generic version of that because every app does something different -- the model is a big part of what you bring to the party when you write an app.

Random Number Generator from input

I'm new to Xcode development, and i would like to know how can i generate random numbers from 2 inputs.
In IB i have 2 textfields (with Number pad) that indicate the interval of the numbers to generate (i.e. from 3 to 7). I would like to know how i get the inputs from the 2 textfields and do a method that generate random numbers from these inputs.
There are many issues involved in trying to generate a truly random number. Note, for instance, that functions like rand() and random() generate sequences of numbers based on a 'seed value'. That means that if the seed value is the same, the sequence of numbers generated will be the same. There are various ways to use 'random' seeds - ie., using the current date and time - but the reliability and security of these methods is questionable.
As the number generators evolve, these issues get addressed, and therefore the later generators are usually better than the earlier ones: rand is generally not as random as random, and random is not as random as arc4random.
The current problem with arc4random(), which is documented in their manual pages, is that using a modulus calculation - as in "arc4random() % UPPER_LIMIT" - can introduce statistical bias, if UPPER_LIMIT is not an even number. Because of this, a new function was added to the arc4random family, called arc4random_uniform. It produces evenly distributed random numbers, regardless of the upper limit - and it is quite simple to use.
Using your example above, I would recommend you try generating your random number like this:
int value = low_bound + arc4random_uniform(width + 1);
int low_bound = 3;
int high_bound = 7;
int width = high_bound - low_bound; // 4
int value = low_bound + arc4random() % (width + 1); // 3 + 0..4
Plus read the bounds from the fields, something like bound = [[field text] intValue].
If you have trouble connecting the input fields to the code, you should read some Cocoa tutorial. There are several ways to do it, one of the most straightforward is declaring properties for the text fields in the controller class:
#interface Controller : UIViewController {}
#property(retain) IBOutlet UITextField *lowerBoundField;
#property(retain) IBOutlet UITextField *upperBoundField;
#end
Then you can connect the text fields in the Interface Builder to these outlets and work with them in code like this:
- (void) generateNumber {
int lowerBound = [[lowerBoundField text] intValue];
…
}
This is assuming we are talking about Cocoa Touch. In desktop Cocoa the situation is similar, just the details would be different.

Add integers from 5 UITextFields to a UILabel in Cocoa Touch

I'm trying to sum the integers from five UITextFields and post them to a UILabel.
This is the code I have tried, but it doesn't work properly. The number that shows up in the label is not the sum of my textfields. I have also tried to post to a textfield instead of a label, with the same result. No errors or warnings when I build.
int val = [textfield1.text intValue]
val = val+[textfield2.text intValue];
val = val+[textfield3.text intValue];
val = val+[textfield4.text intValue];
val = val+[textfield5.text intValue];
NSString *labelStr = [[NSString alloc] initWithFormat:#"%i", val];
label.text = labelStr;
Something wrong with the code? Alternative code? Grateful for all answers!
The code looks more or less right to me, aside from the memory leak. You should review the memory management rules and fix your leak.
My guess is that the numbers you entered add up to a number that is outside the range of an int. Entering, say, 1000000000 (10**9) in each of the five fields would be one way to pull this off, on any machine where an int is 32 bits (including, currently, the iPhone-OS devices).
Depending on the purpose of your app, you may be able to simply cap the five input fields; if the highest value that makes any sense is less than one-fifth (for five fields, and that's assuming they all have the same cap) of the maximum int, overflow is impossible.
If a cap won't solve the problem completely, try a different type. If the values should never be negative, use an unsigned type. Otherwise, try long long, or either of the floating-point types, or use NSDecimalNumber objects.
Of course, I could be completely wrong, since you didn't say what numbers you entered or what the result was. If it was zero, make sure that you hooked up your outlets in IB; if you forgot to do that, they contain nil, which, when you ask it for text, will return nil, which, when you ask it for an intValue, will return 0, and 0 + 0 + 0 + 0 + 0 = 0.

Quick Multiplication Question - Cocoa

I'm still learning, and I'm just stuck. I want the user to enter any number and in result, my program will do this equation:
x = 5*y
(y is the number the user adds, x is outcome)
How would I do this? I'm not sure if I'm suppose to add in an int or NSString. Which should I use, and should I enter anything in the header files?
I'm not sure if I'm suppose to add in an int or NSString.
Well, one of these is a numeric type and the other is a text type. How do you multiply text? (Aside from repeating it.)
You need a numeric type.
I would caution against int, since it can only hold integers. The user wouldn't be able to enter “0.5” and get 2.5; when you converted the “0.5” to an int, the fractional part would get lopped off, leaving only the integral part, which is 0. Then you'd multiply 5 by 0, and the result you return to the user would be 0.
Use double. That's a floating-point type; as such, it can hold fractional values.
… should I enter anything in the header files?
Yes, but what you enter depends on whether you want to use Bindings or not (assuming that you really are talking about Cocoa and not Cocoa Touch).
Without Bindings, declare an outlet to the text field you're going to retrieve the multiplier from, and another to the text field you're going to put the product into. Send the input text field a doubleValue message to get the multiplier, and send the output text field a setDoubleValue: message with the product.
With Bindings, declare two instance variables holding double values—again, one for the multiplier and one for the product—along with properties exposing the instance variables, then synthesize the properties, and, finally, bind the text fields' value bindings to those properties.
If you're retrieving the NSString from a UI, then it's pretty simple to do:
NSString * answer = [NSString stringWithFormat:#"%d", [userInputString integerValue]*5];
This can be done without any objective C. That is, since Objective-C is a superset of C, the problem can be solved in pure C.
#include <stdio.h>
int main(void)
{
int i;
fscanf(stdin, "%d", &i);
printf("%d\n", i * 5);
}
In the above the fscanf takes care of converting the character(s) read on the standard input to a number and storing it in i.
However, if you had characters from some other source in a char* and needed to convert them to an int, you could create an NSString* with the – initWithCString:encoding: and then use its intValue method, but in this particular problem that simply isn't needed.