Reputation: 65
Simple program and simple oversight. Generate two random numbers (0-20) and perform math operations on them. Check user's answer. Everything works fine except for keeping track of number of right answers.
Initialized int correctAnswers = 1
and tried int correctAnswers
outside of the loop as the placeholder. Correct answers should increment it by one. ++correctAnswers
, correctAnswers++
and correctAnswers += 1
all give the exact same answer of 1, regardless how many of the five tries were actually correct.
main.m
int main(int argc, const char * argv[])
{
@autoreleasepool {
// MathTutor's myMath libraries for creating two random numbers, each between 1 and 20.
myMath *myMathStuff;
myMathStuff = [[myMath alloc] init];
int randomNumberOne = [myMathStuff getRandomNumber];
int randomNumberTwo = [myMathStuff getRandomNumber];
// Calculate the expected answers and create a scoring variable.
float answerMultiplication = (randomNumberOne * randomNumberTwo);
float answerDivision = (randomNumberOne / randomNumberTwo);
float answerAddition = (randomNumberOne + randomNumberTwo);
float answerSubtraction = (randomNumberOne - randomNumberTwo);
int correctAnswers = 0;
// Initialize the string and answer variables for scanf().
char operation;
float answer;
// Loop for five iterations.
for (int i = 0; i < 5; i++) {
// Ask what type of operation.
NSLog(@"Please select an operation: \n M. Multiplication \n D. Division \n A. Addition \n S. Subtraction");
scanf("%s", &operation);
// Check for the selected operation.
switch (operation) {
case 'M':
NSLog(@"What is: (%i x %i)?", randomNumberOne, randomNumberTwo);
scanf("%f", &answer);
if (answer == answerMultiplication) {
NSLog(@"Correct!");
++correctAnswers;
}
else { NSLog(@"Incorrect! The correct answer is: %f!", answerMultiplication); }
break;
case 'D':
NSLog(@"What is: (%i / %i)?", randomNumberOne, randomNumberTwo);
scanf("%f", &answer);
if (answer == answerDivision) {
NSLog(@"Correct!");
++correctAnswers;
}
else { NSLog(@"Incorrect! The correct answer is: %f!", answerDivision); }
break;
case 'A':
NSLog(@"What is: (%i + %i)?", randomNumberOne, randomNumberTwo);
scanf("%f", &answer);
if (answer == answerAddition) {
NSLog(@"Correct!");
++correctAnswers;
}
else { NSLog(@"Incorrect! The correct answer is: %f!", answerAddition); }
break;
case 'S':
NSLog(@"What is: (%i - %i)?", randomNumberOne, randomNumberTwo);
scanf("%f", &answer);
if (answer == answerSubtraction) {
NSLog(@"Correct!");
++correctAnswers; }
else { NSLog(@"Incorrect! The correct answer is: %f!", answerSubtraction); }
break;
default:
NSLog(@"Sorry, but that is not a valid operation.");
// Reduce the loop counter by one to offset the invalid choice.
i--;
break;
}
}
// Calculate the score percentage and display the score.
NSLog(@"You correctly answered %i out of 5 questions!", correctAnswers);
NSLog(@"Your grade for this challenge is %i%%", correctAnswers * 20);
// Reset the answers counter.
correctAnswers = 0;
}
return 0;
}
Thanks.
Upvotes: 0
Views: 61
Reputation: 100622
YarGnawh beat me to the correct answer, but to supply fuller detail, this:
scanf("%s", &operation);
Asks for a full, NULL-terminated string to be deposited at the address of operation
. So if you enter the letter 'M' then two bytes will be written to that address: the character code for the letter 'M' and then a terminating NULL
.
That's a buffer overrun because you've declared operation as char operation;
. So there's only a single byte of storage there. The terminating NULL
will therefore be written to storage that isn't safe.
In practice it appears to be written to the lowest byte of correctAnswers
. So that variable gets zeroed. Compilers are free to arrange variables in any order they like so there'd be no reason either to guess that correctAnswers
would be affected or to be surprised that it is.
So: your code has undefined behaviour. In this specific case that undefined behaviour happens relatively harmlessly to zero out part of one of your other variables.
Upvotes: 3
Reputation: 4654
It problem is in the scanf for operation. Scan for character instead.
scanf(" %c", &operation);
Upvotes: 2