I was doing a simple calculator with the following code. Right now it executes perfectly. When I tried to change things around, however, it doesn't work. I used BOOL program to check whether to continue asking for input from the person or finish the program.
If I change the expression of while statement to just (program) and change YES/NO in the program statements, why does the code fail to do what is inside the while?
// A simple printing calculator
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]
Calculator *deskCalc = [[Calculator alloc] init];
double value1;
char operator
BOOL program;
[deskCalc setAccumulator: 0];
while (!program) {
NSLog (#"Please type in your expression");
scanf (" %lf %c", &value1, &operator);
program = NO;
if (operator == '+') {
[deskCalc add: value1];
}
else if (operator == '-') {
[deskCalc subtract: value1];
}
else if (operator == '*' || operator == 'x') {
[deskCalc multiply: value1];
}
else if (operator == '/') {
if (value1 == 0)
NSLog (#"Division by zero!");
else
[deskCalc divide: value1];
}
else if (operator == 'S') {
[deskCalc set: value1];
}
else if (operator == 'E') {
[deskCalc accumulator];
program = YES;
}
else {
NSLog (#"Unknown operator");
}
}
NSLog (#"The result is %f", [deskCalc accumulator]);
[deskCalc release];
[pool drain];
return 0;
}
You haven't set the initial value of program, so it defaults to a garbage value which just happens to be non-zero.
Set the initial value of program when you declare it:
BOOL program = NO; // or YES, whichever is appropriate
It is always a good practice to initialize all your variables when you declare them.
Also using scanf for input may be overdoing it, if I were you I would use fgets and then extract the information from the string using strtok. That way even if the user puts his elbow on the keyboard you will not have to worry. Alternatively if you are fond of scanf use sscanf on that string instead of strtok.
Related
I am new in Objective C, and I need to do a basic math application within a 5 times loop. Users will need to state what operation will perform (+,-,*,/) and the program will generates two random numbers to do math operations. Then the user will do the math and the program will compare his input with the correct answer. At the end the user will receive a score % and a custom message according to right or wrong answer. I am a bit stuck. First I did the program which generates two random numbers and run nicely. However when I added the rest of the code I have a warning message that says that the implementation is incomplete. I am also unable to see what is happening whit the else structure within the case because I received errors indicating "Expected expression" in each one of them.
Any help is very much appreciated.
Here is my code:
#import <Foundation/Foundation.h>
#interface myMath : NSObject
//methods
-(int) getRandomNumber;
-(void) add: (double) result;
-(void) subtract: (double) result;
-(void) multiply: (double) result;
-(void) divide: (double) result;
#end
#implementation myMath
//returns a random number between 1 and 100
-(int) getRandomNumber{
return (arc4random()%(100-1))+1;
}
#end
#interface Calculator : NSObject
#property double setaccumulator, accumulator; //Synt all methods.
#end
#implementation Calculator{
double accumulator;
}
-(void) setAccumulator: (double) value;
{ accumulator = value; }
-(void) clear
{ accumulator = 0; }
-(double) accumulator
{ return accumulator; }
-(void) add: (double) value
{ accumulator += value; }
-(void) subtract: (double) value
{ accumulator -= value; }
-(void) multiply: (double) value
{ accumulator *= value; }
-(void) divide: (double) value
{ accumulator /= value; }
#end
int main(int argc, const char * argv[]) {
#autoreleasepool {
myMath *myMathStuff;
myMathStuff = [[myMath alloc] init];
int rnum1 = [myMathStuff getRandomNumber];
int rnum2 = [myMathStuff getRandomNumber];
double result;
char operator;
Calculator *myCalculator = [[Calculator alloc]init];
int n, right, wrong, cont;
n = 0, right, wrong, cont = 0;
NSLog(#"The random numbers are %i and %i", rnum1, rnum2);
while (n <= 5){
NSLog(#"What operation do you want to perform? (+ . - . * . / .");
scanf(" %c", &operator);
[myCalculator setAccumulator:(double) rnum1];
switch (operator) {
case '+':
[myCalculator add: rnum2];
NSLog(#"Please type the addition result: ");
scanf("%lf", &result);
if (result == rnum1)
right =+1;
NSLog(#"Congratulations, you did it right!");
else
wrong =+1;
NSLog(#"Sorry, the addition result is: %.2f", [myCalculator accumulator]);
break;
case '-':
[myCalculator subtract: rnum2]
NSLog(#"Please type the subtraction: ");
scanf("%lf", &result);
if (result == rnum1)
right =+1;
NSLog(#"Congratulations, you did it right!");
else
wrong =+1,
NSLog(#"Sorry, the subtraction result is: %.2f", [myCalculator accumulator]);
break;
case '*':
[myCalculator multiply: rnum2];
NSLog(#"Please type the multiplication result: ");
scanf("%lf", &result);
if (result == rnum1)
right =+1;
NSLog(#"Congratulations, you did it right!");
else
wrong =+1,
NSLog(#"Sorry, the multiplication result is: %.2f", [myCalculator accumulator]);
break;
case '/':
[myCalculator divide: rnum2];
NSLog(#"Please type the division result: ");
scanf("%lf", &result);
if (result == rnum1)
right =+1;
NSLog(#"Congratulations, you did it right!");
else
wrong =+1,
NSLog(#"Sorry, the division result is: %.2f", [myCalculator accumulator]);
break;
default:
break;
}
++n;
}
NSLog(#"You were right %i", right);
NSLog(#"You were wrong %i", wrong);
if (right == 4)
NSLog(#"Excellent you have a perfect 100 percent score");
else if (right == 3)
NSLog(#"Good job you have a 80 percent score");
else if (right == 2)
NSLog (#"Well, you have a 60 percent score");
else if (right ==1)
NSLog(#"Sorry, you have received a 20 percent score");
}
return 0;
}
I made some changes on the myMath implementation and I also changed the lines where the "else" appears as I show below. I am still getting the expected expression. If somebody else can see what I am not seeing I would appreciate your input.
Part of the code I changed:
switch (operator) {
case '+':
[myMathStuff add: rnum2];
NSLog(#"Please type the addition result: ");
scanf("%lf", &result);
if (result == rnum1)
right =+1;
NSLog (#"Congratulations, you did it right!");
else {
wrong =+1;
NSLog (#"Sorry, the addition result is: %.2f", [myMathStuff accumulator]);
}
break;
I was able to find the solution.
You are getting implementation is incomplete because in your MyMath class you are saying that you have 5 methods at the class level, and only one of those (GetRandomNumber) is actually implemented.
You need to finish the contract - that is - code out what the other four methods are going to do (add, subtract, multiply, divide).
I have the following code:
NSString *content = [[NSUserDefaults standardUserDefaults] stringForKey:#"mykey"];
NSLog(#"string is %#",content);
if ([content stringIsEmpty]){
NSLog(#"empty string");
}else{
NSLog(#"string is not empty");
}
stringIsEmpty is class category on NSString:
- (BOOL ) stringIsEmpty {
if ((NSNull *) self == [NSNull null]) {
return YES;
}
if (self == nil) {
return YES;
} else if ([self length] == 0) {
return YES;
}
return NO;
}
The output is:
string is (null)
string is not empty
How could it be null and not empty at the same time?
What happens is that:
[content stringIsEmpty:YES]
will return false (NO), when content is nil. So your code will take the
NSLog(#"string is not empty");
branch. This would be better:
if (content && [content stringIsEmpty:YES]){
...
A better way of doing this would be reversing the semantics of the method:
if ([content stringIsNotEmpty]) {
this would work finely because when content is nil it would return NO, when it is not nil, it would execute your method.
EDIT:
In Objective-C, sending a message to nil is legal and by definition will evaluate to nil. Google for "objective c sending message to nil".
In another language (C++), your code would crash (actually undefined behaviour, but to make things simple).
I use a small function to test for emptiness. It works on more than just strings:
static inline BOOL isEmpty(id thing) {
return thing == nil
|| ([thing respondsToSelector:#selector(length)]
&& [(NSData *)thing length] == 0)
|| ([thing respondsToSelector:#selector(count)]
&& [(NSArray *)thing count] == 0);
}
I usually import it in my pch file - you can see it along with attribution: https://gist.github.com/325926
As #sergio has already pointed out - when your string is nil you can't send it messages that test it for nil-ness - as sending messages to nil will do nothing for void methods, and return nil where the method returns something.
also
you are calling your method with a parameter
if ([content stringIsEmpty:YES])
but your method declaration doesn't take one:
- (BOOL ) stringIsEmpty {
What's that all about?
You have to check for the 'content == nil' case outside of the method.
If you want to be able to call just one method, change the method to something that tests for a positive, such as "stringHasContent", returning YES if self.length > 0.
Can someone explain this code
- (IBAction)backspacePressed {
self.display.text =[self.display.text substringToIndex:
[self.display.text length] - 1];
if ( [self.display.text isEqualToString:#""]
|| [self.display.text isEqualToString:#"-"]) {
self.display.text = #"0";
self.userIsInTheMiddleOfEnteringNumber = NO;
}
}
I don't get what the 2 lines mean in objective c. || Also, I don't get the meaning of substringToIndex. How does a programmer know to use substringToIndex out of all the different methods in the documentation I saw substringFromIndex etc. There are so many. Is this saying that the strings in the index are counted and -1 means it deletes a string? How would the meaning in the apples documentation relate to deleting a character ?
Comments supplied with explanation of code...
- (IBAction)backspacePressed
{
// This is setting the contents of self.display (a UITextField I expect) to
// its former string, less the last character. It has a bug, in that what
// happens if the field is empty and length == 0? I don't think substringToIndex
// will like being passed -1...
self.display.text =[self.display.text substringToIndex:
[self.display.text length] - 1];
// This tests if the (now modified) text is empty (better is to use the length
// method) or just contains "-", and if so sets the text to "0", and sets some
// other instance variable, the meaning of which is unknown without further code.
if ( [self.display.text isEqualToString:#""]
|| [self.display.text isEqualToString:#"-"]) {
self.display.text = #"0";
self.userIsInTheMiddleOfEnteringNumber = NO;
}
}
|| is an OR operator. At least one of the statements has to be true.
Look at Apple's documentation for the substringToIndex: method
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSString_Class/Reference/NSString.html
This is stuff you could find easily with a google search.
I am practicing some bool functions and I seem to be stuck any help will be appreciated. I must be making some little mistake.
-(BOOL) checkForWin
{
if ([[dictionary valueForKey:[cowsShuffled objectAtIndex:cowsCard]] intValue] == 2{
return YES;
}
}
-(void) moo
{
if (checkForWin == YES) {
NSLog (#"foo");
}
}
You need to call the method (not function), and you don't need to compare to YES. The if statement does that implicitly:
if ([self checkForWin]) …
Also note that checkForWin has a problem: it doesn't return anything if the if statement fails. It should be simply:
- (BOOL)checkForWin{
return [[dictionary valueForKey:[cowsShuffled objectAtIndex:cowsCard]] intValue] == 2;
}
Footnote: Strictly speaking, if (x) … isn't exactly the same as if (x == YES) …. It's actually closer to if (x != NO) …, but of course that's the same thing for most intents and purposes (and those for which it isn't are largely pathological).
Your method call is wrong. You call a method like this: [object method].
In your case [self checkForWin].
I'm trying to get the calculator app I've built to trigger some simple code if it detects I pushed the decimal point button (to only allow one decimal point per value). However, for some reason, these if statements regarding digit aren't being triggered. I've NSLogged the output of it and it is indeed showing as "." so I can't quite figure out why. I've changed the . to any other value too, nothing seems to trigger 'em.
NSString *digit = [sender currentTitle];
if (self.userIsInTheMiddleOfEnteringANumber) {
self.display.text = [[[self display] text] stringByAppendingString:digit]; // All in one line!
NSLog(#"Digit is equal to %#",digit);
if (digit == #".") NSLog(#"That was a decimal point!");
} else {
self.display.text = digit;
if (digit == #".") NSLog(#"You can't begin a number with a decimal!");
self.userIsInTheMiddleOfEnteringANumber = YES; // If they aren't typing, now they are!
}
Dont compare strings with ==. Use isEqualToString:
if ([digit isEqualToString:#"."])
== checks for pointer equality, not string equality.
== doesn't work:
if (digit == #".")
For string use:
if([digit isEqualToString:#".")