Why do I lose my variable values at each iteration of my loop in my C program?
The p2ConsecutivePasses variable turns to 0 at each iteration of the main loop in the code below, even after it was incremented to 1 in a previous iteration of the loop. What is setting p2ConsecutivePasses to 0 repeatedly during this loop? The other variable, p1ConsecutivePasses, does not have this problem
#include <stdio.h>#include <time.h>#include <stdlib.h>#include <string.h>int main() { int authorizedPlayerNumber = 0, secretNumber = 0, playerSelfID= 0; int p1PassesLeft=3, p2PassesLeft=3; int secretNumberGuess = 1; int p1ConsecutivePasses = 0; int p2ConsecutivePasses = 0; char secretNumberGuessString[4] = {0}; srand(time(NULL)); authorizedPlayerNumber = 1 + rand() % 2; /* Random number is generated */ srand(time(NULL)); secretNumber = 0 + rand() % 10; /* Random number is generated */ while (secretNumber!=secretNumberGuess) { printf("\nIt's player's %d turn", authorizedPlayerNumber);//playerID prompt printf("\nPlayer Number? "); scanf("%d", &playerSelfID); while (playerSelfID != 1 && playerSelfID != 2) { //playerID validity test printf("\n%d is not a valid player number. \nPlayer number? ", playerSelfID); scanf("%d", &playerSelfID); } while (authorizedPlayerNumber != playerSelfID) { printf("\nWait your turn."); //alert and playerID reprompt printf("\nIt's player's %d turn.", authorizedPlayerNumber); printf("\nPlayer number? "); scanf("%d", &playerSelfID); } printf("Enter Your Guess, 0 - 10 or pass: "); scanf("%s", secretNumberGuessString); secretNumberGuess = atoi(secretNumberGuessString); //converts string to int if (strcmp(secretNumberGuessString, "pass") == 0){ //test if user entered pass as his guess if (authorizedPlayerNumber == 1){ if(p1PassesLeft<1){ printf("\nPlayer 1, you cannot pass because you have no passes left."); goto endOfLoop; //skip to end of iteration of loop, w/out changing p-turn or incrementing pass variables } if(p1ConsecutivePasses>=2){ printf("\nPlayer 1, you cannot pass more than 2 times in a row."); goto endOfLoop; } p1PassesLeft--; p1ConsecutivePasses++; printf("Player 1 has %d passes remaining.\n", p1PassesLeft); } else if(authorizedPlayerNumber == 2){ if(p2PassesLeft<1){ printf("\nPlayer 2, you cannot pass because you have no passes left."); goto endOfLoop; } if(p2ConsecutivePasses>=2){ printf("\nPlayer 2, you cannot pass more than 2 times in a row."); goto endOfLoop; } p2PassesLeft--; p2ConsecutivePasses++; printf("Player 2 has %d passes remaining.\n", p2PassesLeft); } } else if (secretNumberGuess <= 10 && secretNumberGuess >= 0 ){ if (authorizedPlayerNumber == 1){ p1ConsecutivePasses = 0; //reset player2's consecutive passes } if (authorizedPlayerNumber == 2){ p2ConsecutivePasses = 0; //reset player1's consecutive passes } if(secretNumberGuess < secretNumber) printf("Your guess was too low.\n "); else if(secretNumberGuess > secretNumber) printf("Your guess was too high.\n "); else printf("Good job Player %d! You are correct.\n", authorizedPlayerNumber); } else{ printf("You did not enter a valid number. You lose your turn.\n "); } if (authorizedPlayerNumber == 1) { //could have added a boolean turnComplete variable to this test authorizedPlayerNumber = 2; } else if (authorizedPlayerNumber == 2) { authorizedPlayerNumber = 1; } endOfLoop: ; //players who exceed 2 passes in a row get sent here } return 0;}
When you execute
scanf("%s", secretNumberGuessString);
and enter 4 characters,
the terminating null overflows the allocated
char secretNumberGuessString[4]
which caused undefined behavior
jmcg
You should initialize secretNumberGuess to a value that is outside the range of possible secretNumber values or you will sometimes skip the main loop entirely.
On what basis are you thinking that p2ConsecutivePasses gets reset to 0 on every iteration?
shampouya
ASKER
On my x-code compiler, for some reason, p2ConsecutivePasses gets reset to 0 every time scanf("%s", secretNumberGuessString) executes. Why is secretNumberGuessString[4] being overflowed, as ozo stated? How do I prevent that?
In any case, ozo identified the reason for the problem being asked about, ozo should get credit.
shampouya
ASKER
I tried the scanf("%4s%*[^\n ]", secretNumberGuessString) that ozo recommended, but I still got the same problem with p2ConsecutivePasses resetting to 0 erroneously. I noticed that this happened in the x-code compiler, but not the gcc compiler. Any idea why that is?
ozo
Did you also modify
char secretNumberGuessString[5];
?
Different compilers may lay out the variables in a different order, leading to different behavior when a program contains opportunities for buffer overflow, uninitialized variables, null pointers, etc.
ozo
Undefined Behavior means behavior for which [the language standard] imposes no requirements
Permissible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment to terminating a translation or execution.
If a "shall" or "shall not" requirement is violated, the behavior is undefined.
s Matches a sequence of non-white-space characters
... the corresponding argument shall be a
pointer to the initial element of a character array large enough to accept the
sequence and a terminating null character, which will be added automatically.
shampouya
ASKER
Yep the char secretNumberGuessString[5]; by itself seemed to do the trick. Just changing the 4 to a 5 in my original code made it work, why is hat?
Changing [4] to [5] by itself may resolve the problem when a user enters exactly 4 characters, but it won't resolve the undefined behavior if a user enters 5 characters.
scanf("%s", secretNumberGuessString);
and enter 4 characters,
the terminating null overflows the allocated
char secretNumberGuessString[4]
which caused undefined behavior