%d 字符输入导致无限循环

时间:2021-05-13 14:24:57

标签: c loops io scanf

 int valid=0, running=1;
    printf("\n1. Generate\n2. Retrieve");
    while(!valid){
        printf("\n\nEnter choice> ");
        scanf("%d", &c);
        if(c==1){
            valid=1;
            generate();
            while(running){
                printf("\n\nPress Y to generate again. Press N to retrieve> ");
                scanf(" %c", retry);
                if(retry == 'Y' || retry == 'y'){
                    idx++;
                    generate();
                }else if(retry == 'N' || retry == 'n')
                    running = 0;
                else
                    printf("Invalid input. Try again.");
            }
            retrieve();
        }else if(choice==2){
            valid = 1;
            retrieve();
        }else
            printf("Invalid input. Try again");
    }

这里用户应该输入 1 或 2。如果用户输入任何其他数字或字符,那么我想请用户再次输入。如果用户输入任何其他数字,如 5/6/7 等,程序运行良好。但如果用户输入一个字符,程序将进入无限循环。我可以通过 scanf 状态检查来打破循环,但程序会停止。相反,如果用户输入了 1 或 2 以外的任何内容,我想提示用户再次输入。

2 个答案:

答案 0 :(得分:2)

scanf 返回成功输入分配的数量,或在文件末尾或错误时返回 EOF。你应该养成检查这个返回值的习惯。在 scanf( "%d", &c ) 的这种情况下,您应该期望成功输入时返回值 1

%d 转换说明符告诉 scanf 跳过任何前导空格,然后读取字符直到第一个不是十进制数字的字符,留下那个字符在输入流中。

示例 - 假设您输入 "12.3" 作为输入。 scanf( "%d", &c ) 将读取、转换输入的 "12" 部分并将其分配给 c 并返回 1。输入的 ".3" 部分留在输入流中。

如果再次调用 scanf( "%d", &c ),它首先看到的是 '.' 字符,因此它会立即停止读取(匹配失败)。

由于实际上没有读取任何输入,因此没有分配给 c 并且 scanf 返回 0。这种情况会一直发生,直到您使用其他输入操作(例如 '.'getchar() 等)删除该 scanf( "%*c" ) 字符。

您应该始终检查 scanf 的结果,以确保您阅读的项目与您预期的一样多:

int r = 0;
do
{
  r = scanf( "%d", &c );
  if ( r == EOF )
  {
    // end of file or error signaled on the input stream; in this case we
    // just exit the program
    exit( 0 );
  }
  else if ( r == 0 )
  {
    // matching failure - there's a bad character in the input stream
    // remove it with getchar and try again
    getchar();
  }
} while( r != 1 );

// at this point we either have good input or have already exited the program

答案 1 :(得分:-2)

显然,将 scanf%d 一起使用,但输入字符会导致缓冲区问题。有关避免该问题的一种方法,请参阅下面的代码:

#include <stdio.h>
#include <stdlib.h>

void generate(){
    printf("generate\n");
}

void retrieve(){
    printf("retrieve\n");
}

int main(){
    int valid=0, running=1, idx=0, c=-100;
    char retry;
    char s[25];
    printf("\n1. Generate\n2. Retrieve");
    while(!valid){
        printf("\n\nEnter choice> ");
        scanf("%s", s);
        c = atoi(s);
        if(c==1){
            valid=1;
            generate();
            while(running){
                printf("\n\nPress Y to generate again. Press N to retrieve> ");
                while(scanf(" %c", &retry)==0);
                if(retry == 'Y' || retry == 'y'){
                    idx++;
                    generate();
                }else if(retry == 'N' || retry == 'n')
                    running = 0;
                else
                    printf("Invalid input. Try again.");
            }
            retrieve();
        }else if(c==2){
            valid = 1;
            retrieve();
        }else
            printf("Invalid input. Try again");
    }
    
    return(0);
}

一种可能的执行如下所示:

1. Generate
2. Retrieve

Enter choice> Bad
Invalid input. Try again

Enter choice> Worse
Invalid input. Try again

Enter choice> 1
generate


Press Y to generate again. Press N to retrieve> Y
generate


Press Y to generate again. Press N to retrieve> n
retrieve
相关问题