I’m doing the foundation calculator homework from the cs193p course, and my
+evaluateExpression:usingVariables: method doesn’t work. It always returns 0.
Here’s my method:
+ (double)evaluateExpression: (id)anExpression usingVariablevalues: (NSDictionary *)variables {
CalculatorBrain *worker = [[[CalculatorBrain alloc] init] autorelease];
double returnValue = 10.0;
if ([anExpression isKindOfClass:[NSMutableArray class]]) {
for (id term in anExpression) {
NSLog(@"%f", returnValue); // breakpoint
if ([term isKindOfClass:[NSString class]]) { // string
if ([term hasPrefix:@"%"] && [term length] == 2) { // variable
double value = [(NSNumber *)[variables objectForKey:[term substringFromIndex:1]] doubleValue];
NSLog(@"Variable: %@, value: %d", [term substringFromIndex:1], value);
[worker setOperand:value];
}
else if ([term length] == 1) { // operation
returnValue = [worker performOperation:term];
}
else {
NSLog(@"Invalid expression.\n\tMultiple character operation found: %@", term);
}
}
else if ([term isKindOfClass:[NSNumber class]]) { // operand
double value = [term doubleValue];
[worker setOperand:value];
}
else {
NSLog(@"Invalid expression.\n\tWrong type in expression: %@, The value is: %@.",[term class], term); // Wrong type in expression
}
}
}
else {
NSLog(@"Invalid expression.\n\tThe expression is of the wrong type: %@.", [anExpression class]); // expression is of wrong type
}
//returnValue = worker.operand;
return returnValue;
}
Any hints? it always returns 0.
/* Ouput from Console */
2012-06-27 20:01:05.487 Calculator[2823:207] 0
2012-06-27 20:01:05.488 Calculator[2823:207] 0
2012-06-27 20:01:05.489 Calculator[2823:207] 0
2012-06-27 20:01:05.490 Calculator[2823:207] Variable: x, value: 0
2012-06-27 20:01:05.490 Calculator[2823:207] 0
2012-06-27 20:01:05.491 Calculator[2823:207] 0
2012-06-27 20:01:05.491 Calculator[2823:207] 0
Note: I set returnValue to 10.0 at the beginning to check if it is getting changed at all.
Update:
I found out that it gets 0 from the dictionary. I think the calling code is the cause:
- (IBAction) performSampleExpression {
NSMutableArray *expr = [[NSMutableArray alloc] init];
[expr addObject:[NSNumber numberWithDouble:3.0]];
[expr addObject:@"+"];
[expr addObject:@"%x"];
[expr addObject:@"*"];
[expr addObject:[NSNumber numberWithDouble:4.0]];
NSDictionary *varsdict = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithDouble:10.0], @"x", nil];
double result = [CalculatorBrain evaluateExpression:expr usingVariablevalues:varsdict];
if (!result) NSLog(@"result = nil");
NSLog(@"%f", result);
display.text = [NSString stringWithFormat:@"%f", result];
[expr release];
}
Result isn’t nil though.
Update 2:
Using the debugger (nice hint. This might solve it.) I found something strange:
On this line: (first time)
returnValue = worker.operand;
It says returnValue is still 10, and not three (worker.operand IS).
Is the assignment failing, or is this how it should be? (Just wondering).
UPDATE 3:
Okay there is something very strange going on here: I set a breakpoint on the return statement, the last line of +evaluateExpression:usingVariables:, and it says
returnValue = 4.
This means, the actual problem lies in -performSampleExpression. What am I doing wrong?
UPDATE 4:
Changing @"%d", double into @"%f", double helped a lot. That explains the strange Console output. But, it solved it, because I updated the display like display [setText:@"%d", result]; what caused my double to be displayed as 0 due to a wrong cast.
I discovered this by using the debugger, so the one who suggested that practically solved it. (And I asked for hints, not for solutions. After all, homework is to learn from).
The possible issues can shown in:
and
You should stop debugger in this line (or line below) and watch how to your value of
returnValuechange.You stop app clicking on position where it is on the screen, app stops, and then jump to next line with F6 (or Fn+F6). Below (in console) you can see the value.
EDIT
You could try this solution – Change allocation to:
And delete line:
This release right before return may couse the problem without NSCopying @protocol.
Autorelease and NSCopying
For better understanding compile this code:
So you may consider how you assign a variable. In above example releasing memory shouldn’t effect return values, but by using autorelease with return object you don’t have to assign anything.