【问题标题】:Recursion scanf deadloop递归scanf死循环
【发布时间】:2019-11-22 08:25:44
【问题描述】:

我试图征求意见。如果它不是整数,那么它应该再次要求输入,这就是我使用递归的原因,如下所示。

#include <stdio.h>


void hi() {
    int a;
    printf("Input a: ");
    if(scanf("%d", &a) == 0)
        a = -1;
    switch(a) {
        case 1:
            printf("Hello!");
            break;
        case 0:
            return;
        default:
            hi();
            return;
            break;
    }
}

int main()
{
    hi();

    return 0;
}

输出是

Input a: *asd* Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a: Input a:

当我输入非整数值时,为什么 hi() 中的 scanf 不工作 (它不会停止 printf 并询问我的输入) 我该如何解决?

【问题讨论】:

标签: c recursion


【解决方案1】:

对于需要处理无效输入的交互式程序,您不想使用scanf,因为它无法从解析错误中恢复。请改用 fgets/sscanf 的组合。

另外,最好不要使用递归来解决可以使用迭代解决的问题。更容易维护和调试。你也会得到更好的成绩!

   int a = 0 ;
   while ( 1 ) {
       char buff[200] ;
       printf("Enter ...") ;
       if ( !fgets(buff, sizeof(buff), stdin) ) { perror("EOF") ; exit(1) ; }
       if ( sscanf(buff, " %d", &a) == 1 ) break ; // All Good
   } ;      

原始代码“scanf”将在第一次解析错误时反复失败,递归导致所有堆栈被使用,程序崩溃。

【讨论】:

  • 次要:' '" %d" 中不需要。 "%d" 将跳过前导空格。
  • 我同意。我更喜欢添加一个明确的空间来向可能不熟悉确切细节的代码读者澄清这一点。对于多个字段,“%d %f %d”比“%d%f%d”更容易阅读。
  • NULL return from fgets 表示 EOF 错误。 perror("EOF") 将在 EOF 或 EOF: Some error message 上打印一条奇怪的错误消息,例如 EOF: Success 以防出现错误。 (您可以使用./program &lt; /tmp 重现错误情况。)我建议使用feof 和/或ferror 来区分EOF 和错误,并且仅在出现错误时使用perror("fgets(stdin)") 之类的内容。
【解决方案2】:

scanf 在您的示例中不起作用,因为它从缓冲的标准输入中读取。所以 scanf 认为你已经再次输入了一些东西,再次......再次......直到缓冲区被清除。清除缓冲区的时间取决于系统,并且可能因每个系统而异。

因此,最好的做法是像其他用户已经提到的那样使用 while 或 do-while 循环。

要让您的代码以某种方式工作,请在 if 之后添加 fflush(stdin)但请仅出于测试目的执行此操作,并尝试按照 as 循环中提到的方式实现它。

#include <stdio.h>    
void hi() {
    int a;
    printf("Input a: ");
    if(scanf("%d", &a) == 0){
        a = -1;            
    }
    fflush(stdin)
    switch(a) {
        case 1:
            printf("Hello!");
            break;
        case 0:
            return;
        default:
            hi();
            return;
            break;
    }
}

int main()
{
    hi();

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-27
    • 2017-01-21
    • 1970-01-01
    • 1970-01-01
    • 2013-08-12
    • 2011-02-09
    • 2023-04-02
    • 2011-08-11
    相关资源
    最近更新 更多