【问题标题】:Reading a number from stdin in C从 C 中的标准输入读取数字
【发布时间】:2014-12-03 11:58:46
【问题描述】:

我有一个函数可以从 C 中的 stdin 获取一个数字。

int io_get_num(const char *q, const size_t min, const size_t max, int * num)
{ /* Get a number from the command line */
    int ret = 0;

    do {
        printf(q);
        ret = scanf(" %d", num);
        if (ret == EOF)
            return EOF;
        else if (ret == 0)
            printf("Please provide a valid number ..\n%s", q);
        else if (*num > max || *num < min)
            printf("Number must be smaller than %u and larger than %u\n%s", (unsigned int)max+1, (unsigned int)min-1, q);
        else
            break;
        /* Flushing stdin */
        int ch;
        while ( (ch = fgetc(stdin)) != EOF && ch != '\n' );
    } while (1);

    return ret;
}

它在第一次循环运行时运行良好,之后(我注意到在与 gdb 中断时)循环运行两次,除了它不等待我的输入或检查任何条件(这可能与冲洗有关流)..

我能解决这个问题吗?

【问题讨论】:

  • 你为什么要完全刷新输入?你希望这段代码做什么?
  • 首先," %d"scanf 中的那个空间的用途是什么?那里完全是多余的。其次,我没有看到任何证据表明您的循环在输入错误后重复了两次。出于某种原因,您在错误消息之后再次打印q,这可能会产生循环迭代两次的错觉,而实际上它不会发生。第三,如果min 为零,您将下限范围打印为(unsigned int)min-1 的想法将产生一个非常奇怪的(从用户的角度来看)输出。第四,不清楚您究竟想从这里的输入中“刷新”什么以及为什么。
  • 什么是stream?。我认为应该是stdin
  • @Rustam:更正了。
  • @AndreyT:首先,为什么" %d" 是多余的?它应该强制scanf 忽略空白。其次,我说我用 gcc 跟踪了代码流,所以我绝对确定它运行了两次。第三,你是对的,我更新了上面的代码。第四,这种行为试图实现非标准功能fflush。它会尝试删除 scanf 未捕获的用户空间缓冲数据(以防用户未提供有效输入来替换“%d”。尝试删除它以查看会发生什么......

标签: c validation input stream flush


【解决方案1】:

由于某种原因,您每次迭代都会打印两次q:在开始时一次,然后在错误消息之后再次打印。这可能会产生循环每个输入迭代两次的错觉,而实际上它不会发生。在我的实验中,我无法重现这种双重迭代。

另外,scanf(" %d", num)%d 之前的空格是多余的。这不是错误,它会使scanf 跳过任何前导空格,但%d 已经在内部自己跳过前导空格。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-28
    • 1970-01-01
    相关资源
    最近更新 更多