while loop 卡在无限循环中,我不知道为什么
While loop is stuck in infinite loop and I don't know why
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
int main(int argc, char * argv[])
{
printf("This program tests your integer arithmetic skills.\n"
"You should answer the questions following the same \n"
"rules that computers do for integers arithmetic, not \n"
"floating-point arithmetic. Hit the 'Enter' key after \n"
"you have typed in your input. When you wish to finish \n"
"the test, enter -9876 as the answer to a question.\n"
"\n");
int n1, n2, answer, user_answer, a, b, int_per;
char op, c;
float per, count, count_r, count_w;
count = 0;
count_r = 0;
count_w = 0;
printf("What is your question? ");
scanf("%d %c %d", &n1, &op, &n2);
do
{
count++;
printf("What is %d %c %d ? ", n1, op, n2);
if (op == '+')
{
answer = n1 + n2;
}
else if (op == '-')
{
answer = n1 - n2;
}
else if (op == '%')
{
answer = n1 % n2;
}
else if (op == '/')
{
answer = n1 / n2;
}
else if (op == '*')
{
answer = n1 * n2;
}
c = scanf("%d", &user_answer);
if (user_answer == answer)
{
printf("Correct!\n\n");
count_r++;
}
else if (user_answer == -9876)
{
count = count - 1;
break;
}
else if (c != 1)
{
printf("Invalid input, it must be just a number\n\n");
printf("What is %d %c %d ? ", n1, op, n2);
}
else if (user_answer != answer)
{
printf("Wrong!\n\n");
count_w++;
}
} while(user_answer != -9876);
per = (count_r / count) * 100;
a = (int) count_r;
b = (int) count_w;
int_per = roundf(per);
printf("\nYou got %d right and %d wrong, for a score of %d%c\n", a,
b, int_per, 37);
return EXIT_SUCCESS;
}
上面的代码应该循环询问问题然后回答,直到用户输入 -9876 作为答案然后程序终止并给他们他们 score.This 所有工作除外!一方面。当用户在输入中输入非数字时。当发生这种情况时,应该说 "invalid input, please try again" 然后再问同样的问题。例如
你的问题是什么? 9+9
9 + 9 是多少? 嗯,8
输入无效,请重试
9 + 9 是多少?
SO.. 用户输入 "hmmm" 而不是再次提示用户相同的问题然后正确扫描它只是跳入无限 loop.I 想知道如何解决这个问题。
谢谢
当读取输入出错时,您应该清除错误状态并跳过该行的其余部分,然后再尝试读取更多用户输入。
替换行:
else if (c != 1)
{
printf("Invalid input, it must be just a number\n\n");
printf("What is %d %c %d ? ", n1, op, n2);
}
来自
else if (c != 1)
{
printf("Invalid input, it must be just a number\n\n");
// Clear the error states.
clearerr(stdin);
// Skip the rest of the line
skipRestOfLine(stdin);
printf("What is %d %c %d ? ", n1, op, n2);
}
其中 skipRestOfLine()
可以实现为:
void skipRestOfLine(FILE* stream)
{
int c;
while ( (c = fgetc(stream)) != '\n' && c != EOF );
}
scanf("%d%c%d",&n1, &op, &n2) use this code
通话中
c = scanf("%d", &user_answer);
%d
转换说明符期望看到十进制数字字符序列;它会告诉 scanf
跳过任何前导空格,然后读取十进制数字字符直到第一个非十进制数字字符,然后将结果转换并保存到 user_answer
。如果你输入 12aEnter, scanf
会读取并消费 '1'
和 '2'
字符,将值 12
赋值给 user_answer
和 return 1(一次成功转换和赋值) 在输入流中留下 'a'
和换行符。
当您键入 "hmmm"
时,第一个非空白字符不是十进制数字,因此 scanf
保留它,不向 user_answer
分配任何内容,并且returns 0
。使用 "%d"
转换说明符对 scanf
的所有剩余调用将执行相同的操作。
因此,您需要确保 scanf
成功,如果不成功,请在进行另一次读取之前清除输入流中的所有字符,如下所示:
if ( (c = scanf( "%d", &user_answer ) ) == 0 )
{
/**
* input matching failure, clear stray characters from input stream
* up to the next newline character
*/
while ( getchar() != '\n' )
; // empty loop
}
else if ( c == EOF )
{
// error occurred during input operation
}
else
{
// do something with user_answer
}
您会注意到在我的第一个示例中,%d
转换说明符接受了输入 "12a"
;它将 12
转换并赋值给 user_answer
,在输入流中留下 'a'
字符,从而扰乱下一次读取。理想情况下,您希望完全拒绝这种格式错误的输入。您可以执行以下操作:
/**
* Repeatedly prompt and read input until we get a valid decimal string
*/
for( ;; )
{
int c, dummy;
printf("What is %d %c %d ? ", n1, op, n2);
if ( ( c = scanf("%d%c", &user_answer, &dummy ) == 2 )
{
/**
* If the character immediately following our numeric input is
* whitespace, then we have a good input, break out of the read loop
*/
if ( isspace( dummy ) )
break;
else
{
fprintf( stderr, "Non-numeric character follows input, try again...\n" );
while ( getchar() != '\n' )
; // empty loop body
}
}
else if ( c == 1 )
{
/**
* No character following successful decimal input, meaning we
* hit an EOF condition before any trailing characters were seen.
* We'll consider this a good input for our purposes and break
* out of the read loop.
*/
break;
}
else if ( c == 0 )
{
/**
* User typed in one or more non-digit characters; reject the input
* and clear out the input stream
*/
fprintf( stderr, "Non-numeric input\n" );
/**
* Consume characters from the input stream until we see a newline.
*/
while ( ( getchar() != '\n' )
; // empty loop body
}
else
{
/**
* Input error or EOF on read; we'll treat this as a fatal
* error and bail out completely.
*/
fprintf( stderr, "Error occurred during read, panicking...\n" );
exit( 0 );
}
}
另一种选择是将您的输入读取为文本,然后使用 strtol
库函数将其转换为结果类型:
for ( ;; )
{
char input[SIZE]; // for some reasonable SIZE value, at least 12 to handle
// a 32-bit int (up to 10 digits plus sign plus
// string terminator
printf("What is %d %c %d ? ", n1, op, n2);
if ( fgets( input, sizeof input, stdin ) )
{
char *check; // will point to first non-digit character in input buffer
int tmp = (int) strtol( input, &check, 10 );
if ( isspace( *check ) || *check == 0 )
{
user_answer = tmp;
break;
}
else
{
fprintf( stderr, "%s is not a valid input, try again\n", input );
}
}
else
{
/**
* error or EOF on input, treat this as a fatal error and bail
*/
fprintf( stderr, "EOF or error while reading input, exiting...\n" );
exit( 0 );
}
}
这是我的首选方法。
这些混乱中的任何一个都会替换行
c = scanf("%d", &user_answer);
看完您可能在想的所有内容后,"interactive input in C sure is a pain in the ass"。你是对的。
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
int main(int argc, char * argv[])
{
printf("This program tests your integer arithmetic skills.\n"
"You should answer the questions following the same \n"
"rules that computers do for integers arithmetic, not \n"
"floating-point arithmetic. Hit the 'Enter' key after \n"
"you have typed in your input. When you wish to finish \n"
"the test, enter -9876 as the answer to a question.\n"
"\n");
int n1, n2, answer, user_answer, a, b, int_per;
char op, c;
float per, count, count_r, count_w;
count = 0;
count_r = 0;
count_w = 0;
printf("What is your question? ");
scanf("%d %c %d", &n1, &op, &n2);
do
{
count++;
printf("What is %d %c %d ? ", n1, op, n2);
if (op == '+')
{
answer = n1 + n2;
}
else if (op == '-')
{
answer = n1 - n2;
}
else if (op == '%')
{
answer = n1 % n2;
}
else if (op == '/')
{
answer = n1 / n2;
}
else if (op == '*')
{
answer = n1 * n2;
}
c = scanf("%d", &user_answer);
if (user_answer == answer)
{
printf("Correct!\n\n");
count_r++;
}
else if (user_answer == -9876)
{
count = count - 1;
break;
}
else if (c != 1)
{
printf("Invalid input, it must be just a number\n\n");
printf("What is %d %c %d ? ", n1, op, n2);
}
else if (user_answer != answer)
{
printf("Wrong!\n\n");
count_w++;
}
} while(user_answer != -9876);
per = (count_r / count) * 100;
a = (int) count_r;
b = (int) count_w;
int_per = roundf(per);
printf("\nYou got %d right and %d wrong, for a score of %d%c\n", a,
b, int_per, 37);
return EXIT_SUCCESS;
}
上面的代码应该循环询问问题然后回答,直到用户输入 -9876 作为答案然后程序终止并给他们他们 score.This 所有工作除外!一方面。当用户在输入中输入非数字时。当发生这种情况时,应该说 "invalid input, please try again" 然后再问同样的问题。例如
你的问题是什么? 9+9
9 + 9 是多少? 嗯,8
输入无效,请重试
9 + 9 是多少?
SO.. 用户输入 "hmmm" 而不是再次提示用户相同的问题然后正确扫描它只是跳入无限 loop.I 想知道如何解决这个问题。
谢谢
当读取输入出错时,您应该清除错误状态并跳过该行的其余部分,然后再尝试读取更多用户输入。
替换行:
else if (c != 1)
{
printf("Invalid input, it must be just a number\n\n");
printf("What is %d %c %d ? ", n1, op, n2);
}
来自
else if (c != 1)
{
printf("Invalid input, it must be just a number\n\n");
// Clear the error states.
clearerr(stdin);
// Skip the rest of the line
skipRestOfLine(stdin);
printf("What is %d %c %d ? ", n1, op, n2);
}
其中 skipRestOfLine()
可以实现为:
void skipRestOfLine(FILE* stream)
{
int c;
while ( (c = fgetc(stream)) != '\n' && c != EOF );
}
scanf("%d%c%d",&n1, &op, &n2) use this code
通话中
c = scanf("%d", &user_answer);
%d
转换说明符期望看到十进制数字字符序列;它会告诉 scanf
跳过任何前导空格,然后读取十进制数字字符直到第一个非十进制数字字符,然后将结果转换并保存到 user_answer
。如果你输入 12aEnter, scanf
会读取并消费 '1'
和 '2'
字符,将值 12
赋值给 user_answer
和 return 1(一次成功转换和赋值) 在输入流中留下 'a'
和换行符。
当您键入 "hmmm"
时,第一个非空白字符不是十进制数字,因此 scanf
保留它,不向 user_answer
分配任何内容,并且returns 0
。使用 "%d"
转换说明符对 scanf
的所有剩余调用将执行相同的操作。
因此,您需要确保 scanf
成功,如果不成功,请在进行另一次读取之前清除输入流中的所有字符,如下所示:
if ( (c = scanf( "%d", &user_answer ) ) == 0 )
{
/**
* input matching failure, clear stray characters from input stream
* up to the next newline character
*/
while ( getchar() != '\n' )
; // empty loop
}
else if ( c == EOF )
{
// error occurred during input operation
}
else
{
// do something with user_answer
}
您会注意到在我的第一个示例中,%d
转换说明符接受了输入 "12a"
;它将 12
转换并赋值给 user_answer
,在输入流中留下 'a'
字符,从而扰乱下一次读取。理想情况下,您希望完全拒绝这种格式错误的输入。您可以执行以下操作:
/**
* Repeatedly prompt and read input until we get a valid decimal string
*/
for( ;; )
{
int c, dummy;
printf("What is %d %c %d ? ", n1, op, n2);
if ( ( c = scanf("%d%c", &user_answer, &dummy ) == 2 )
{
/**
* If the character immediately following our numeric input is
* whitespace, then we have a good input, break out of the read loop
*/
if ( isspace( dummy ) )
break;
else
{
fprintf( stderr, "Non-numeric character follows input, try again...\n" );
while ( getchar() != '\n' )
; // empty loop body
}
}
else if ( c == 1 )
{
/**
* No character following successful decimal input, meaning we
* hit an EOF condition before any trailing characters were seen.
* We'll consider this a good input for our purposes and break
* out of the read loop.
*/
break;
}
else if ( c == 0 )
{
/**
* User typed in one or more non-digit characters; reject the input
* and clear out the input stream
*/
fprintf( stderr, "Non-numeric input\n" );
/**
* Consume characters from the input stream until we see a newline.
*/
while ( ( getchar() != '\n' )
; // empty loop body
}
else
{
/**
* Input error or EOF on read; we'll treat this as a fatal
* error and bail out completely.
*/
fprintf( stderr, "Error occurred during read, panicking...\n" );
exit( 0 );
}
}
另一种选择是将您的输入读取为文本,然后使用 strtol
库函数将其转换为结果类型:
for ( ;; )
{
char input[SIZE]; // for some reasonable SIZE value, at least 12 to handle
// a 32-bit int (up to 10 digits plus sign plus
// string terminator
printf("What is %d %c %d ? ", n1, op, n2);
if ( fgets( input, sizeof input, stdin ) )
{
char *check; // will point to first non-digit character in input buffer
int tmp = (int) strtol( input, &check, 10 );
if ( isspace( *check ) || *check == 0 )
{
user_answer = tmp;
break;
}
else
{
fprintf( stderr, "%s is not a valid input, try again\n", input );
}
}
else
{
/**
* error or EOF on input, treat this as a fatal error and bail
*/
fprintf( stderr, "EOF or error while reading input, exiting...\n" );
exit( 0 );
}
}
这是我的首选方法。
这些混乱中的任何一个都会替换行
c = scanf("%d", &user_answer);
看完您可能在想的所有内容后,"interactive input in C sure is a pain in the ass"。你是对的。