【问题标题】:Character input with %d causing infinite loop [closed]带有%d的字符输入导致无限循环[关闭]
【发布时间】:2021-08-03 20:06:52
【问题描述】:
 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 之外的任何内容,我想提示用户再次输入。

【问题讨论】:

  • 第一步:查看scanf("%d", &c);的返回值。是 1 吗?
  • kerbx4,如果选择是空行会发生什么?等待更多输入或提示,然后等待新输入?
  • @WilliamPursell:非常好。归档以备将来参考。
  • 你似乎把c(在if)和choice(在else if)搞混了......但你没有显示任何一个的声明。请发布我们可以实际测试的代码。

标签: c loops io scanf


【解决方案1】:

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

【讨论】:

    【解决方案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
    

    【讨论】:

    猜你喜欢
    • 2014-06-18
    • 1970-01-01
    • 2012-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-13
    相关资源
    最近更新 更多