Add integers from 5 UITextFields to a UILabel in Cocoa Touch - objective-c

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.

Related

NSString intValue returns 0 if I substring it from the beginning of a string taken from a byte buffer

NSString *counter = [[NSString alloc] initWithBytes:buffer+1 length:11 encoding:NSUTF8StringEncoding]; //#"003{of}004"
NSString *c1Str = [counter substringToIndex:4];
NSString *c2Str = [counter substringFromIndex:8];
int c1Int = [c1Str intValue];
int c2Int = [c2Str intValue];
NSLog(#"c1Str=%#; c2Str=%#; c1Int=%i; c2Int=%i", c1Str, c2Str, c1Int, c2Int);
//The output is
//c1Str=003; c2Str=004; c1Int=0; c2Int=4
So I get 0 (zero) for c1Int while c2Int is fine.
Absolutely the same result is if I use:
NSArray *counterValues = [counter componentsSeparatedByString:#"{of}"];
int c1Int = [[counterValues objectAtIndex:0] intValue];
int c2Int = [[[counterValues objectAtIndex:1] intValue];
I get the counter from a byte buffer that I read from NSInputStream. Defining *counter directly as #"003{of}004" works properly.
Why is it so? What is so special in *c1Str that intValue treats it as zero? How can I combat it?
Thanks
EDIT:
The question is not actual anymore for me. But it may be useful for others.
I couldn't understand and resolve my task in terms as it was set. I had to re-think and change my workflow.
I'd like to give more details of where the problem roots from.
I transfer png files via network and receive the data on the ios. The idea was to send a byte array read from a file, with leading special tags been attached to notify that the file is coming and what the counter is.
So the structure sent would look like:
[6][003{of}004][file data package], where "[" and "]" brackets are only for you here to understand the structure.
As I mentioned the data comes to NSInputStream, and I can catch [6], and I can catch [003{of}004], and I can catch the rest of the data. NSLog shows it clearly. But something is really odd with the counter string, i would say something with the beginning of the string is odd.
First of all, yes, if I try to retrieve the parts by substring'ing them then I have to use strange indexes.
intValue returns 0 whatever method I use to retrieve 003 and 004, with 004 been treated always correctly as expected!
If someone can give an explanation of why this may happen (and ideally a working solution) that would be definitely useful and much appreciated.
Thanks a lot to all who responded.
P.S. I work around this by sending the counter separately as a string, with different notify tag been attached in the beginning. As I don't need a fixed length of the counter now, my values coming are just numbers as is: 3{of}4, or 121{of}784 etc. (no leading zeros)
You have wrong output, if your string is #"003{of}004" you have to use another indexes!
NSString *c1Str = [counter substringToIndex:3];
NSString *c2Str = [counter substringFromIndex:7];
I don't know why your c1Str print as 003 in log.
Change
[counter substringToIndex:4];
to
[counter substringToIndex:3];
if your counter string is 003{of}004

NSNumber limit?

What is the highest int that NSNumber allows? I've seen the answer elsewhere on these forums hence why I'm deeply confused here.
int miles = 35000;
vehicle.mileage = [NSNumber numberWithInt:miles];
NSLog(#"int value = %d", miles);
NSLog(#"mileage = %#", vehicle.mileage);
The output is:
int value = 35000
mileage = -30536
I must be missing some terrible easy here, but can someone explain to me why this is not working correctly?
UPDATE:
After looking further, vehicle.mileage is getting set correctly to 35000 but when I display this via NSLog(#"%#", vehicle.mileage) it is outputting it incorrectly. I have yet to find the "magic" value when this stops working because as of now, it works for values up to ~30,000.
NSNumber is just a wrapper so it goes in overflow when the wrapped primitive type goes in overflow.
So if you use numberWithInt the maximum number allowed is INT_MAX (defined in limits.h), if you use a numberWithFloat the maximum number allowed is FLOAT_MAX, and so on.
So in this case you aren't going in overflow, I doubt that INT_MAX would be so low.
Overview
NSNumber is a subclass of NSValue that offers a value as any C scalar
(numeric) type. It defines a set of methods specifically for setting
and accessing the value as a signed or unsigned char, short int, int,
long int, long long int, float, or double or as a BOOL. (Note that
number objects do not necessarily preserve the type they are created
with.) It also defines a compare: method to determine the ordering of
two NSNumber objects.
So NSNumber is as big as what it wraps. For your unexpected result you can check comment bellow your qestion from #sjs.
+numberWithInt: interprets the value as signed int. Mileage would never be negative, so I suggest using [NSNumber numberWithUnsignedInt:]
The limit NSNumber integer can have is known as INT_MAXbut 35, 000 is nowhere close to that. The problem must be with vehicle object or the mileage property in the vehicle, either of them may be nil
So, go ahead and log with this conditional statement:
if (!vehicle) {
NSLog(#"Vehicle is nil");
}
else if (!vehicle.mileage) {
NSLog(#"Vehicle's mileage is nil");
}
Tell me your result

Why is the row property of NSIndexPath a signed integer?

Why is the row property of NSIndexPath a signed integer?
Could it ever take on a "valid" negative value?
edit
I haven't thought about this until today when I set LLVM to check sign comparison. This made the compiler spew out warnings whenever there was indexPath.row <= [someArray count] or similar.
What happens if you use negative numbers?
It isn't wise to use negative values, if you do, you'll get crazy results
NSIndexPath* path = [NSIndexPath indexPathForRow:-2 inSection:0];
The above results in a section of 0, and a row of 4294967294 (which looks like underflow of an NSUInteger to me!) Be safe in the knowledge that this only occurs within the UIKit Additions category, and not within NSIndexPath itself. Looking at the concept behind NSIndexPath, it really doesn't make sense to hold negative values. So why?
(Possible) Reason for why it is so
The core object NSIndexPath from OS X uses NSUIntegers for its indices, but the UIKit Addition uses NSInteger. The category only builds on top of the core object, but the use of NSInteger over NSUInteger doesn't provide any extra capabilities.
Why it works this way, I have no idea. My guess (and I stipulate guess), is it was a naive API slipup when first launching iOS. When UITableView was released in iOS 2, it used NSIntegers for a variety of things (such as numberOfSections). Think about it: This conceptually doesn't make sense, you can't have a negative number of sections. Now even in iOS 6, it still uses NSInteger, so not to break previous application compatibility with table views.
Alongside UITableView, we have the additions to NSIndexPath, which are used in conjunction with the table view for accessing it's rows and such. Because they have to work together, they need compatible types (in this case NSInteger).
To change the type to NSUInteger across the board would break a lot of things, and for safe API design, everything would need to be renamed so that the NSInteger and NSUInteger counterparts could work safely side by side. Apple probably don't want this hassle (and neither do the developers!), and as such they have kept it to NSInteger.
One possible reason is that unsigned types underflow very easily. As an example, I had an NSUInteger variable for stroke width in my code. I needed to create an “envelope” around a point painted with this stroke, hence this code:
NSUInteger width = 3;
CGRect envelope = CGRectInset(CGRectZero, -width, -width);
NSLog(#"%#", NSStringFromCGRect(envelope));
With an unsigned type this outputs {{inf, inf}, {0, 0}}, with a signed integer you get {{-3, -3}, {6, 6}}. The reason is that the unary minus before the width variable creates an underflow. This might be obvious to somebody, but will surprise a lot of programmers:
NSUInteger a = -1;
NSUInteger b = 1;
NSLog(#"a: %u, b: %u", a, -b); // a: 4294967295, b: 4294967295
So even in situations where it doesn’t make sense to use a negative value (stroke width can’t be negative) it makes sense to use the value in a negative context, causing an underflow. Switching to a signed type leads to less surprises, while still keeping the range reasonably high. Sounds like a nice compromise.
I think UIKit Additions on NSIndexPath use NSInteger type intentionally. If for some reason negative row would be passed as parameter to any method (I see none at the moment, though...), autocast to NSIntegerMax + parameter value would not happen and any possible object would not look for a ridiculously large parameter that does not exist. Still, there are other ways to prevent this, so it might be just a matter of taste.
I, for example, would not take NSUInteger as parameters in NSIndexPath class, but rather NSInteger and checked for a sign and wouldn't create NSIndexPath at all, if any parameter was negative.

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

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.

How can i convert CGFloat to an Integer Value (iPhone SDK)

My problem is: I'm trying to convert my CGFloat Values to an integer value and than add them to an NSMutableArray.
For Example;
CGFloat x=ship.center.x
//convert x to integer
?
P.S.:After that, I will send these values to another iPhone with bluetooth. But first I must solve this problem. İf anyone knows how to send an array data to another iPhone with bluetooth, it also works :)
Firstly, why do you want to convert to int? CGfloat is just a typedef for float, and can be sent as-is, especially if you know that your sending iPhone to iPhone, since they will use the same memory representation for floats. If you still need to do this for some reason...
// Choose constants m and c so that the resulting integers
// span as much of the range (INT_MIN, INT_MAX) as possible,
// thus minimising aliasing effects. Also consider using
// long long (64-bit integers).
int x = (int)(m*ship.center.x+c)
NSMutableArray only stores objects, so you might want to use a simple array instead:
int* arr = malloc(sizeof(x)*ships.length);
for (int i = 0; i < ships.length; i++) {
arr[i] = (int)ships[i].center.x;
}
send_data(arr, sizeof(x)*ships.length);
I've never programmed with a Bluetooth stack, so I can't help you there. Sorry.