【问题标题】:Scanf is skipped in while loop, causing infinite loop在while循环中跳过scanf,导致无限循环
【发布时间】:2016-06-05 16:26:41
【问题描述】:

此代码的目的是,如果用户输入格式不正确的输入,程序同时要求用户重试。出于某种原因,虽然在我的代码中,第一次迭代后不断跳过 scanf,导致无限循环

#include <stdio.h>
int main() {
double A1;
int n1, loopchck, i=0;
while (i==0) {
    printf("Enter a real number and inerger (A n): ");
    fflush(stdin);
    loopchck=scanf_s(" %lf %d", &A1, &n1);
    if (loopchck == 2) {
        i = 1;
    }
    else {
        i = 0;
    } 
} 
return 0;
}

【问题讨论】:

  • fflush(stdin); 是 UB,删除它。
  • 在失败的情况下,你需要清理标准输入......
  • 您调用的不是标准函数scanf,而是scanf_s,它必须是自定义函数。该问题可能与该函数的作用有关。
  • 还相关:您知道标准输出通常在终端上进行行缓冲,对吧?所以很有可能你的 printf 实际上不会导致任何东西出现在屏幕上。你可能想fflush(stdout)
  • scanf() 在第一次迭代后不断被跳过,因为错误的输入仍然存在。如果输入对scanf() 不利,为什么您认为再次调用相同的代码会返回不同的结果。?您需要额外的代码来使用有问题的输入。

标签: c while-loop scanf


【解决方案1】:

首先,让我们想想你想让fflush(stdin); 做什么。 fflush 仅对已写入的流进行操作;它会导致所有未写入(缓存)的数据被完全写入,并且在 stdin 的上下文中没有任何意义。

这是一个常见的错误。当您告诉scanf 读取整数(或浮点数,等等)时,它会在不再看到任何数字时停止读取。这意味着您至少可能会在流中留下剩余的'\n'。用户可能还输入了您想要丢弃的其他(错误)输入。

丢弃用户输入的想法太可怕了!您应该考虑接受不同形式的输入(例如,在int main(int argc, char **argv) 中使用argv),以使他们不舒服的生活更加舒适。

如果您不能这样做(或者您不想这样做),您可以使用以下代码之一来丢弃(包括)下一个 '\n'

void fdiscardline(FILE *f) {
    int c;
    do {
        c = fgetc(f);
    } while (c != EOF && c != '\n');
}

void fdiscardline(FILE *f) {
    fscanf(f, "%*[^\n]");
    fgetc(f);
}

您应该在您的输入之后使用这个,而不是之前。此外,您需要考虑i 应该是什么。当可以读取更多输入时它应该为零(例如while (i==0)),或者当输入未被正确读取时为零?您需要保持一致,因为这是您的循环终端条件。例如:

#include <stdio.h>
int main() {
    double A1;
    int n1, loopchck, i=0;
    while (i==0) {
        printf("Enter a real number and inerger (A n): ");
        loopchck=scanf_s(" %lf %d", &A1, &n1);
        fdiscardline(stdin);
        if (loopchck == 2) {
            i = 0;
        }
        else {
            i = 1;
        }
    } 
    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-12-27
    • 2012-10-05
    • 1970-01-01
    • 2013-12-20
    • 1970-01-01
    • 2012-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多