为什么scanf()会在代码中导致无限循环?
我有一个小C程序,它只从标准输入中读取数字,每个循环一个。如果用户输入了一些NaN,则应将错误打印到控制台,并再次返回输入提示。输入“0”时,循环应结束,给定的正/负数值应打印到控制台。节目如下:为什么scanf()会在代码中导致无限循环?,c,gcc,scanf,C,Gcc,Scanf,我有一个小C程序,它只从标准输入中读取数字,每个循环一个。如果用户输入了一些NaN,则应将错误打印到控制台,并再次返回输入提示。输入“0”时,循环应结束,给定的正/负数值应打印到控制台。节目如下: #include <stdio.h> int main() { int number, p = 0, n = 0; while (1) { printf("-> "); if (scanf("%d", &number) ==
#include <stdio.h>
int main()
{
int number, p = 0, n = 0;
while (1) {
printf("-> ");
if (scanf("%d", &number) == 0) {
printf("Err...\n");
continue;
}
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
#包括
int main()
{
整数,p=0,n=0;
而(1){
printf(“->”);
如果(scanf(“%d”,&number)==0){
printf(“Err…\n”);
继续;
}
如果(数字>0)p++;
如果(数字<0)n++;
else中断;/*0给定*/
}
printf(“读取%d个正数和%d个负数\n”,p,n);
返回0;
}
我的问题是,在输入一些非数字(如“a”)时,会导致一个无限循环反复写入“->Err…”。我想这是一个scanf()问题,我知道这个函数可以被一个更安全的函数代替,但这个例子是给初学者的,他们只知道printf/scanf、if-else和循环
我已经阅读了其他问题的答案并略读了其他问题,但没有什么真正回答这个特定问题。scanf()
将“a
”保留在输入缓冲区中,以备下次使用。您可能应该使用getline()
来读取一行内容,然后使用strtol()
或类似的方法来解析它
(是的,
getline()
是特定于GNU的,而不是POSIX。那又怎样?问题被标记为“gcc”和“linux”。getline()
也是读取一行文本的唯一明智选择,除非您想手动完成。)我认为您只需在继续循环之前刷新缓冲区即可。类似的东西可能会起作用,尽管我无法测试我在这里写的东西:
int c;
while((c = getchar()) != '\n' && c != EOF);
扫描前刷新输入缓冲区:
while(getchar() != EOF) continue;
if (scanf("%d", &number) == 0) {
...
我本打算建议使用fflush(stdin)
,但显然这会导致错误
作为对您的评论的响应,如果您希望显示提示,则必须刷新输出缓冲区。默认情况下,只有在打印换行符时才会发生这种情况。比如:
while (1) {
printf("-> ");
fflush(stdout);
while(getchar() != EOF) continue;
if (scanf("%d", &number) == 0) {
...
scanf
只使用与格式字符串匹配的输入,返回使用的字符数。任何与格式字符串不匹配的字符都会导致其停止扫描,并将无效字符保留在缓冲区中。正如其他人所说,在继续之前,您仍然需要将无效字符从缓冲区中清除。这是一个相当肮脏的修复程序,但它将从输出中删除有问题的字符
char c = '0';
if (scanf("%d", &number) == 0) {
printf("Err. . .\n");
do {
c = getchar();
}
while (!isdigit(c));
ungetc(c, stdin);
//consume non-numeric chars from buffer
}
编辑:修复了一次性删除所有非数字字符的代码。不再为每个非数字字符打印多个“错误”
是SncF.
< P>的一个很好的概述,由于其他代码所指出的<代码> SCANF的问题,您应该真正考虑使用另一种方法。我总是发现scanf
对于任何认真的输入读取和处理来说都太有限了。使用fgets
读取整行代码,然后使用strtok
和strtol
等函数处理这些代码(顺便说一句,它们将正确解析整数并告诉您无效字符的确切起始位置)。而不是使用scanf()
并且必须处理具有无效字符的缓冲区,请使用fgets()
和sscanf()
我也有类似的问题。我只用scanf解决了这个问题
输入“abc123”
查看其工作原理
#include <stdio.h>
int n, num_ok;
char c;
main() {
while (1) {
printf("Input Number: ");
num_ok = scanf("%d", &n);
if (num_ok != 1) {
scanf("%c", &c);
printf("That wasn't a number: %c\n", c);
} else {
printf("The number is: %d\n", n);
}
}
}
#包括
int n,num_ok;
字符c;
main(){
而(1){
printf(“输入编号:”);
num_ok=scanf(“%d”&n);
如果(num_ok!=1){
scanf(“%c”、&c);
printf(“那不是一个数字:%c\n”,c);
}否则{
printf(“编号为:%d\n”,n);
}
}
}
在某些平台(特别是Windows和Linux)上,您可以使用fflush(stdin)代码>:
#包括
内部主(空)
{
整数,p=0,n=0;
而(1){
printf(“->”);
如果(scanf(“%d”,&number)==0){
fflush(stdin);
printf(“Err…\n”);
继续;
}
fflush(stdin);
如果(数字>0)p++;
如果(数字<0)n++;
else中断;/*0给定*/
}
printf(“读取%d个正数和%d个负数\n”,p,n);
返回0;
}
我也有同样的想法,我找到了一个有点老套的解决方案。我使用fgets()
读取输入,然后将其馈送到sscanf()
。对于无限循环问题,这是一个不错的解决方案,通过一个简单的for循环,我告诉C搜索任何非数字字符。下面的代码不允许像123abc
这样的输入
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(int argc, const char * argv[]) {
char line[10];
int loop, arrayLength, number, nan;
arrayLength = sizeof(line) / sizeof(char);
do {
nan = 0;
printf("Please enter a number:\n");
fgets(line, arrayLength, stdin);
for(loop = 0; loop < arrayLength; loop++) { // search for any none numeric charcter inisde the line array
if(line[loop] == '\n') { // stop the search if there is a carrage return
break;
}
if((line[0] == '-' || line[0] == '+') && loop == 0) { // Exculude the sign charcters infront of numbers so the program can accept both negative and positive numbers
continue;
}
if(!isdigit(line[loop])) { // if there is a none numeric character then add one to nan and break the loop
nan++;
break;
}
}
} while(nan || strlen(line) == 1); // check if there is any NaN or the user has just hit enter
sscanf(line, "%d", &number);
printf("You enterd number %d\n", number);
return 0;
}
#包括
#包括
#包括
int main(int argc,const char*argv[]{
字符行[10];
int循环,数组长度,数字,nan;
arrayLength=sizeof(行)/sizeof(字符);
做{
nan=0;
printf(“请输入一个数字:\n”);
fgets(线、排列长度、标准尺寸);
对于(loop=0;loop
嗨,我知道这是一条老线索,但我刚刚完成一项学校作业,在那里遇到了
#include <stdio.h>
int main(void)
{
int number, p = 0, n = 0;
while (1) {
printf("-> ");
if (scanf("%d", &number) == 0) {
fflush(stdin);
printf("Err...\n");
continue;
}
fflush(stdin);
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(int argc, const char * argv[]) {
char line[10];
int loop, arrayLength, number, nan;
arrayLength = sizeof(line) / sizeof(char);
do {
nan = 0;
printf("Please enter a number:\n");
fgets(line, arrayLength, stdin);
for(loop = 0; loop < arrayLength; loop++) { // search for any none numeric charcter inisde the line array
if(line[loop] == '\n') { // stop the search if there is a carrage return
break;
}
if((line[0] == '-' || line[0] == '+') && loop == 0) { // Exculude the sign charcters infront of numbers so the program can accept both negative and positive numbers
continue;
}
if(!isdigit(line[loop])) { // if there is a none numeric character then add one to nan and break the loop
nan++;
break;
}
}
} while(nan || strlen(line) == 1); // check if there is any NaN or the user has just hit enter
sscanf(line, "%d", &number);
printf("You enterd number %d\n", number);
return 0;
}
#include <stdio.h>
int main()
{
int number, p = 0, n = 0;
char unwantedCharacters[40]; //created array to catch unwanted input
unwantedCharacters[0] = 0; //initialzed first byte of array to zero
while (1)
{
printf("-> ");
scanf("%d", &number);
gets(unwantedCharacters); //collect what scanf() wouldn't from the input stream
if (unwantedCharacters[0] == 0) //if unwantedCharacters array is empty (the user's input is valid)
{
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
else
printf("Err...\n");
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
if (scanf("%d", &number) == 0) {
printf("Err...\n");
break;
}
#include <stdio.h>
int n;
char c[5];
main() {
while (1) {
printf("Input Number: ");
if (scanf("%d", &n)==0) { //if you type char scanf gets null value
scanf("%s", &c); //the abovementioned char stored in 'c'
printf("That wasn't a number: %s\n", c);
}
else printf("The number is: %d\n", n);
}
}
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int p = 0, n = 0;
while (1)
{
char c;
int number;
int success;
printf("-> ");
success = scanf("%d%c", &number, &c);
if ( success != EOF )
{
success = success == 2 && isspace( ( unsigned char )c );
}
if ( ( success == EOF ) || ( success && number == 0 ) ) break;
if ( !success )
{
scanf("%*[^ \t\n]");
clearerr(stdin);
}
else if ( number > 0 )
{
++p;
}
else if ( number < n )
{
++n;
}
}
printf( "\nRead %d positive and %d negative numbers\n", p, n );
return 0;
}
-> 1
-> -1
-> 2
-> -2
-> 0a
-> -0a
-> a0
-> -a0
-> 3
-> -3
-> 0
Read 3 positive and 3 negative numbers
fgetc(stdin); /* to delete '\n' character */
#include <stdio.h>
int main()
{
int number, p = 0, n = 0;
while (1) {
printf("-> ");
if (scanf("%d", &number) == 0) {
fgetc(stdin); /* to delete '\n' character */
printf("Err...\n");
continue;
}
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
int c;
while ((c = fgetc(stdin)) != '\n' && c != EOF);
#include <stdio.h>
int main()
{
int number, p = 0, n = 0;
while (1) {
printf("-> ");
if (scanf("%d", &number) == 0) {
fflush(stdin);
printf("Err...\n");
continue;
}
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}
// all you need is to clear the buffer!
#include <stdio.h>
int main()
{
int number, p = 0, n = 0;
char clearBuf[256]; //JG:
while (1) {
printf("-> ");
if (scanf("%d", &number) == 0) {
fgets(stdin, 256, clearBuf); //JG:
printf("Err...\n");
continue;
}
if (number > 0) p++;
else if (number < 0) n++;
else break; /* 0 given */
}
printf("Read %d positive and %d negative numbers\n", p, n);
return 0;
}