bash 中的 Ctrl+D 在 C 程序中显示意外结果

Ctrl+D in bash shows unexpected result inside a C program

我正在使用 this tutorial on building your own lisp 学习 c 编程。

现在我在第 4 章,他们在那里进行交互式提示。我做的第一步是制作一个重复打印用户输入的程序。

这是代码:

#include <stdio.h>

static char input[2048];

int main(int argc, char** argv) {
  puts("Went Version 0.0.0.0.1");
  puts("Press Ctrl+c to Exit\n");
  while(1){
    fputs("went> ", stdout);
    fgets(input, 2048, stdin);
    printf("%s", input);
  }
  return 0;
}

它按预期工作

~$ ./main
Went Version 0.0.0.0.1
Press Ctrl+c to Exit

went> hello
hello
went>

但是当我试图用 Ctrl+d 而不是 Ctrl+c 结束它时,它做了一些奇怪的事情。

went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went> went>^C

它一直这样运行,直到我用 Ctrl+C 杀死它。

这不是问题或其他问题,只是想知道为什么会这样。

这里基本上是这样的:

Ctrl+Dstdin 触发文件结束。之后,所有从 stdin 读取的尝试都将导致 fgets 返回 NULL(并且 feof(stdin) 返回 true,这与此处无关)。

由于您不检查循环中的任何内容,因此您的循环没有理由停止。这是发生了什么:

  1. 你按下 Ctrl+D 触发文件结束
  2. 您使用 fgetsstdin 读取,现在 returns NULL 并保持 input 缓冲区不变。
  3. 您显示 input 缓冲区的内容
  4. 你转到 2 等等

这与bash无关。

您需要检查 EOF(文件结尾)条件:

#include <stdio.h>

static char input[2048];

int main(int argc, char** argv) {
  puts("Went Version 0.0.0.0.1");
  puts("Press Ctrl+c to Exit\n");
  while(1){
    fputs("went> ", stdout);

    if (fgets(input, 2048, stdin) == NULL)  // change here
      break;                                //

    printf("%s", input);
  }
  return 0;
}