【问题标题】:Stopping user input after Ctrl+D requires 2 presses; why?Ctrl+D 后停止用户输入需要按 2 次;为什么?
【发布时间】:2018-04-18 09:56:17
【问题描述】:

用户可以输入各种不同数量的数字(只要他们输入的数字不超过 5000 个)。但是,当用户按下 CTRL+D 时,程序应该停止请求用户输入。到目前为止我已经做到了。但是,我必须按两次 CTRL+D 才能停止。有人可以帮我解决它吗?

int input_array[MAX_NUMBERS] = {0};

scanf("%d", &input_array[0]);

int eof_detector = getchar();

int i = 0;
while ((i < 5000) && (eof_detector != EOF)) {
    i++;
    scanf("%d", &input_array[i]);
    eof_detector = getchar();
}

【问题讨论】:

  • @user3121023 我收到编译器错误。也许我理解错了?你能完整地告诉我你的意思吗?

标签: c while-loop scanf eof


【解决方案1】:

这里有一个更简单的解决方案。

// When the person presses CTRL+D, scanf will return EOF.
// Since the return value is EOF and not 1, it will break
// out of the scanning while loop.
// Also note, you can scan numbers as a while loop
// condition.
int input_array[MAX_NUMBERS] = {0};

int i = 0;
while (
       (scanf("%d", &input_array[0]) == 1) &&
       (i < MAX_NUMBERS)
      ) {
    i++;
}

【讨论】:

    【解决方案2】:

    您不需要单独使用getchar 来检查是否已达到 EOF。 scanf 如果遇到数据结尾,它本身会返回一个 EOF。你的循环会像这样工作

      do {
          ret = scanf("%d", &input_array[i]);
          i++;
         } while ((i < 5000) && (ret != EOF));
    

    【讨论】:

    • 我不能使用像 do 这样的函数。我不知道 ret 是否是一个函数,但我不能使用它。我可以使用 if 语句之类的东西吗?
    • ret 是一个 int 变量。 do 不是函数。它是C 的一部分,是while 的变体,测试在末尾而不是开头。你也可以像以前那样做。将一个额外的scanfif 测试放在循环之外。然后你可以改用while
    • 如果我使用 fgets,fgets 可以将整数读取为整数吗?然后以某种方式使用 atoi 函数?
    • @ZoeyMalkov Don't use atoi().
    • @ZoeyMalkov 底线是避免使用getchar 并依赖scanf 的返回值。剩下的就看你自己了。
    【解决方案3】:

    您在scanf 中可能会遇到EOF,因此您应该测试scanf 的返回值,并在失败时调用feof(stdin) 以查看失败是否是由于EOF 或错误。

    for(i=1;i<4999;i++){
       if(EOF==scanf("%d", &input_array[i])){
          if(feof(stdin)) /*EOF*/; else /*error*/;
          break;
       }
    }
    

    正如scanf(3) 手册页所示,scanf 会在错误(在这种情况下,errno 设置为手册页中列出的值之一)或EOF 时返回EOF

    【讨论】:

    • 对不起,我对编程有点陌生。 scanf 失败时返回或显示什么值(所以我可以为它执行 if 语句)。我也不能使用 feof(stdin) 因为我们还没有在课堂上学习过。我们只能使用我们学到的东西,比如 if 语句
    • @ZoeyMalkov scanf 在错误/EOF 时返回 EOF。它在手册页(或标准)中。我已将详细信息添加到答案中。
    • 感谢您的帮助,但我无法使用 feof 或 break 之类的东西,因为我还没有学会它们。有没有其他办法?
    • 如果 Scanf 也返回 EOF,我该如何为此编写 if 语句?会不会像if (input_array[i] != EOF)
    【解决方案4】:

    您无需在循环和内循环之前单独使用getchar()。在条件中使用getchar(),如果遇到输入结束scanf() 也将返回EOF,因此请检查scanf()返回值。这样做

    int main() {
            int input_array[MAX_NUMBERS] = {0};
            int i = 0,ret;
    
            do {
                    ret = scanf("%d", &input_array[i]);/* if you pressed
                                                  CTRL+D, scanf return EOF */
                    if(ret == EOF)/* if ctrl+d pressed,condition becomes true */
                            break;
                    i++;
            }while ((i < 5000) && (getchar() != EOF));/* it won't check this
                                                 bcz of break statement if CTRL+d pressed */
            return 0;
    }
    

    【讨论】:

    • 正如预期的那样。 scanf 将读取一次,getchar 将读取第二次。如果你只想读一次,你需要去掉getchar
    • @NoufalIbrahim 如果我摆脱 getchar 如何检测 EOF?
    • 检查我的回答和对您问题的第一条评论。 scanf本身会在遇到输入结束时返回EOF
    • 我修改了我的答案@ZoeyMalkov 检查。正如 Noufal 所说,Scanf() 本身会在遇到输入结束时返回 EOF
    • @achal 我无法使用该功能。我也不知道是什么。有没有办法使用 if 语句或其他东西来做到这一点?
    猜你喜欢
    • 2017-12-03
    • 2023-03-16
    • 2011-11-14
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 2015-01-21
    • 2019-08-26
    • 1970-01-01
    相关资源
    最近更新 更多