Why my do
/ while
loop repeats 2 times before it checks condition?
int main() {
char quit;
quit = getchar();
do {
printf("Next state: ");
clock_t start = clock();
count_values(a, b);
clock_t end = clock();
float seconds = (float)(end - start) / CLOCKS_PER_SEC;
print_state(b);
printf("\nTime: %f\n", seconds);
swap(a, b);
printf("Press enter to print next generation. To quit, enter 'q'.");
quit = getchar();
} while(quit != 'q');
return 0;
}
Only after loop has repeated 2 times, getchar()
waits for input, why? How to fix it?
CodePudding user response:
You are probably giving the input manually, therefore when you press the Enter
key, a newline character is left behind which is then consumed by the second getchar()
call.
To bypass this, you can use fgets()
.
char quit[100];
fgets(quit, sizeof(quit), stdin);
do {
printf("Next state: ");
clock_t start = clock();
clock_t end = clock();
float seconds = (float)(end - start) / CLOCKS_PER_SEC;
printf("\nTime: %f\n", seconds);
printf("Press enter to print next generation. To quit, enter 'q'.");
fgets(quit, sizeof(quit), stdin);
} while(quit[0] != 'q');
While the above code should do the job, one can easily trick the program, by typing anything that starts with q
.
The solution would be to use strcmp()
to check that the string only contains "q"
.
Note that fgets()
also stores the newline character in the buffer, to bypass that you need to replace it with a NULL byte.
char quit[100];
do {
printf("Next state: ");
clock_t start = clock();
clock_t end = clock();
float seconds = (float)(end - start) / CLOCKS_PER_SEC;
printf("\nTime: %f\n", seconds);
printf("Press enter to print next generation. To quit, enter 'q'.");
fgets(quit, sizeof(quit), stdin);
quit[strcspn(quit, "\n")] = '\0'; /* get rid of \n */
} while(strcmp(quit, "q") != 0);
CodePudding user response:
It does not repeat twice before checking the condition. You can check that by slightly modifying your code, which also makes it a minimal reproducible example:
#include <stdio.h>
int test(char c) {
printf("Testing input: %d\n", c);
return c != 'q';
}
int main() {
char quit;
quit = getchar();
do {
printf("Press enter to print next generation. To quit, enter 'q'.\n");
quit = getchar();
} while(test(quit));
return 0;
}
You can see that the input is already being tested after the first loop. It is not 'q'
, if you type q
then [enter]
. The q
will be consumed by the quit = getchar();
before the loop. Then the newline character (decimal 10) will be checked in the condition, and it is not q
.
So your assumption was wrong.