Quick Multiplication Question - Cocoa - objective-c

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.

Related

Objective-C: Type casting object to integer_t

integer_t is a typedef of int32_t as defined here, and after some checking, integer_t has a size of 4 bytes, and so does int (intValue) as per mentioned is this doc. My question is, is casting like this produce valid result?
integer_t value = 100;
id anObject = #(value);
integer_t aValue = [anObject intValue];
Is aValue always equal to value? Will this cause any issue in the long run? Should I do long value = [anObject longValue] instead? Thanks in advance.
Short and specific answer - YES those values are equal since integer_t and int both (according to you - here's the catch) have the same size AND the same signedness. If one was e.g. some type of unsigned int then it would not work. Neither would it work if one was e.g. 8 bytes (long) and the other 4 (int).
The long and general answer is - it depends. Yes, here you think it is equal but there are always funny cases you need to watch out for. I already mentioned the size and signedness but the real trip can be over the system architecture. So you might assume they are the same and then one day you compile for 64b arch and all breaks down as int there has 8 bytes length and integer_t still is 4 e.g. You could also run into endianness troubles. Thus if you get a bunch of ints from a mainframe they could be stored BADC where A, B, C and D are the 4 bytes of the int.
As you can see, it is easy to scare anybody working with these, and in practice that is why there are things such as NSInteger - Objective-C's attempt to protect you from these. But don't be scared, these are toothless monsters, unless you work at a low level, and then your work will be to work with them. Doesn't that sound poetic.
Back to the code - don't worry too much about these. If you work in Objective-C, maybe try to use the NSInteger and NSUInteger types for now. If you store these and need to load it again later then you need to think about the possibility that you store it from a 32b arch and restore it on a 64b arch and work around that somehow.

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

Pointer to specified number of values

How can I specify that a method should take as parameter a pointer to a location in memory that can hold a specified number of values? For example, if I have:
- (void)doSomethingWith:(int *)values;
I'd like to make it clear that the int * passed in should point to an allocated space in memory that's able to hold 10 such values.
To directly answer your question, use an array argument with a bounds, e.g.:
- (void)takeTenInts:(int[10])array
Which specifies that the method takes an array of 10 integers.
Only problem is the C family of languages do not do bounds checking, so the following is valid:
int a[10], b[5];
[self takeTenInts:a]; // ok
[self takeTenInts:b]; // oops, also ok according to the compiler
So while you are specifying the size, as you wish to do, that specification is not being enforced.
If you wish to enforce the size you can use a struct:
typedef struct
{
int items[10];
} TenInts;
- (void)takeTenInts(TenInts)wrappedArray
Now this doesn't actually enforce the size at all[*], but its as close a you can get with the C family (to which the word "enforcement" is anathema).
If you just wish to know the size, either pass it as an additional argument or use NSArray.
[*] It is not uncommon to see structures in C following the pattern:
typedef struct
{
// some fields
int data[0];
} someStruct;
Such structures are dynamically allocated based on their size (sizeof(someStruct)) plus enough additional space to store sufficient integers (e.g. n * sizeof(int)).
In other words, specifying an array as the last field of a structure does not enforce in anyway that there is space for exactly that number of integers; there may be space for more, or fewer...
Why use "(int *)" when you have the power (and "count") of "NSArray" to work with?
But anyways, looking at this potentially related question, couldn't you just do a "sizeof(values)" to get the size of a statically/globally allocated pointer?
If that doesn't work (which would be in the case of a dynamically allocated array), you really would probably need some kind of "count:" parameter in your "doSomethingWith:" method declaration.
There are a several ways. You could just name the method appropriately:
- (void)doSomethingWithTenInts:(int *)tenInts;
Or you could use a struct:
typedef struct {
int values[10];
} TenInts;
- (void)doSomethingWithTenInts:(TenInts *)tenInts;
Or you could make the user tell you how many ints he is giving you:
- (void)doSomethingWithInts:(int *)ints count:(int)count;

Explanation of Objective-C properties

I'm reading a book about iOS (it calls Programming iOS 4, by Matt Neuburg) and in the paragraph where he explains properties he said these words:
Objective-C uses dot-notation for properties, and C uses dot-notation for structs; these can be chained. So, for example, UIView’s frame is a property whose value is a struct (a CGRect); thus, you can say myView.frame.size.height, where frame is a property that returns a struct, size is a component of that struct, and height is a component of that struct. But a struct is not a pointer, so you cannot (for example) set a frame’s height directly through a chain starting with the UIView, like this:
myView.frame.size.height = 36.0; // compile error
Instead, if you want to change a component of a struct property, you
must fetch the property value into a struct variable, change the
struct variable’s value, and set the entire property value from the
struct variable:
CGRect f = myView.frame;
f.size.height = 0;
myView.frame = f;
I don't understand well, why I can't use the line below?
myView.frame.size.height = 36.0;
Background
A variable in a programming language is a box which has a name (sometimes termed a "reference" or a "pointer' depending on the language). This box contains a value of some type. Values don't change, the contents of boxes do. E.g in the following code:
int a = 4;
a = 5;
The second line doesn't change 4, it changes what is in box a.
Types in programming languages fall into two categories: value types and reference types.
For value types what gets passed around and stored in boxes is a representation of the actual value, e.g. in the code:
double a = 9.0;
double b = sqrt(a);
The function sqrt is not passed a but the value that is stored in a - which is some sequence of bits which represent the number 9.0; what is returned by sqrt is some sequence of bits which represent 3.0, and these are stored into b. The bits that are passed around, you use your words in one of your comments, are the "real value".
For reference types what gets passed around and stored in boxes is some representation of the name of the box (chunk of memory) which contains the actual value. In Objective-C reference types are distinguished by using * in their declaration (other languages don't require a *, e.g. Java & C# - they know which types are reference types based on their kind). E.g in the code:
NSWindow *main = [NSApp mainWindow];
the method call doesn't return a window value itself but the name of a box containing the window value. Again to use your words, the "real value" is never passed around rather the name of a box containing that value is passed around.
Traditionally "small" types were represented by value types - integers, floating point numbers, characters, etc.; while "large" values by reference types. However each programming languages makes its own choices - some are even defined to only operate with reference types.
Answer
In your example myView.frame is a property, and a property is implemented using a method. In Objective-C (and C, C++) a struct type is a value type - it is treated just like integers and floating point numbers, it's value is passed around and stored in boxes. So what is returned by the property is, using your words, the "real struct" - it's as "real" as the bits representing 3.0 in the above example.
What isn't being returned is the name of the box containing a struct value, and without access to a box you can't change its contents. Which is why myView.frame.size.height = 36.0; is incorrect - you're trying to change part of a value, and values don't change.
However given an NSRect box you can change part of its contents. E.g. in the code:
NSRect aRect;
aRect.size.height = 36.0;
The .size.height is identifying which part of the box aRect to change, and the representation of 36.0 is stored into that part of the box.
HTH
Because if you broke it all out, myView.frame is the same as saying
CGRect aFrame = [myView frame]
which gives you back a copy of the struct, not a pointer back to the "real" struct. Thus the compiler is helping you by not letting you set a value in a temporary struct that will not reflect in the "real" struct.
myView.frame
will return you a struct which is a Rvalue not Lvalue. For rvalue and lvalue read this
Now myView.frame will return rvalue which is a data not a pointer.

Objective-C Converting an integer to a hex value

I've got a dictionary initialized like so...
keyDictionary = [[NSDictionary dictionaryWithObjects:values forKeys:keys]retain];
where keys is an NSArray of the alphabet and other characters and values is an NSArray of unsigned chars, which are the USB hex keycodes for those characters.
The USB key codes are hex values that range from 0x04 to 0xE7. I'm trying to create a map between these two depending on what key is pressed on the keyboard.
The values array is created like so...
NSArray *values = [NSArray arrayWithObjects:
[NSNumber numberWithUnsignedChar:0x04]/*A*/,
[NSNumber numberWithUnsignedChar:0x05]/*B*/, /*ETC*/];
So ideally when I run this code...
where character == #"I"
- (uint8) getUSBCode:(NSString *)character
{
NSNumber *val = [keyDictionary objectForKey:character];
return (uint8)[val unsignedCharValue];
}
I would expect to get back 0x0C, but I'm getting 12 back as an int (which after I thought about it, makes sense). I need the hex value preserved. I do NOT need a string value. I need a straight conversion to the hex value or a better way to store
uint8 is just a typedef unsigned char.
EDIT I was not clear when I posted this earlier. Here's what I need.
I need the hex value of these codes because they are being sent over the internal company network. In addition, the pressed key's value is being converted from big endian (or little, it's escaping me right now which one it is) to the other, then being transmitted over an internal network. I understand that these values are stored in binary, but I need to transmit them in hex.
Also, I stated I was getting 12 back from the function. I was reading 12 from the debugger, not actually getting the value. That might be why I was getting confused.
12 (in base 10) is 0x0c.
If you want to print it out in hex, use the %x format specifier e.g.
NSLog(#"Hex value of char is 0x%02x", (unsigned int) c);
If you want to see it in hex in the debugger (assuming Xcode 3.2.x) right click on the variable and select hexadecimal as the format.
You know that an int is stored in binary (i.e. the 'hex' value is always and never preserved), so I'm interpreting your question as pertaining to printing to the screen.
You should be able to use a format specifier for that -- something like %0x.
The value that's returned from your -getUSBCode: method isn't two decimal digits, it's one eight-bit byte. Both "12" and "0x0C" are strings that represent that byte's value, so saying you want "0x0C" but don't want a string is a contradiction.