按住Ctrl + D时fgets不会停止阅读

时间:2019-06-08 19:02:58

标签: c fgets

当您使用getchar,fgets或类似功能从stdin中读取内容时,如果键入一些文本然后放入eof(在Linux中为control + d),则无法删除前一个文本。例如,如果我键入“程序”,然后通过按Ctrl + d输入eof,则无法删除之前输入的内容,即程序。

#include<string.h>
#include<stdlib.h>

int main() {

    char buffer[1024] = "";
    printf("> ");
    if(fgets(buffer,sizeof(buffer),stdin) == NULL){
        puts("eof");
    }
    else{
        puts(buffer);
    }

    return 0;
}

如何避免这种情况?

3 个答案:

答案 0 :(得分:1)

fgets读取一行时,将发生以下情况:它将从指定的流中读取字符,直到遇到'\n'EOF,直到读取了指定的最大大小为止。读取或发生读取错误。它根本看不到您在键盘上正在做什么。它只能看到流,但是是终端将数据发送到流。

编辑输入时发生的事情与fgets完全无关。那是码头的工作。

正如Eric Postpischil在评论中写道:

  

在Linux中按Control-D不会发出EOF信号。实际上,它的意思是“完成当前的读取操作。”这时,如果键入了字符,它们将立即发送到程序,而系统通常会等到按下Enter键。如果未键入任何字符,则读取操作将以零个字符读取完成,某些I / O例程将其视为EOF,这就是为什么在行首按Ctrl-D时程序似乎会接收到EOF的原因输入。由于数据已发送到程序,因此当然无法撤消,因为它已经发送。

我猜想有某种方法可以改变按C-d的行为,但是您需要决定它应该怎么做。如果您希望它“不执行任何操作”而不是将数据发送到stdin,那么我真的看不到您赢得了什么。我可以看到的唯一用例是,如果您由于某种原因而偶尔不小心按下C-d时遇到问题。

您可以做的一件事就是完全控制每个按键。然后,您将不得不编写代码以在用户每次按下键时移动光标,并且还必须编写代码以在用户按下Backspace时删除字符。您可以为此使用ncurses之类的库。

答案 1 :(得分:1)

我认为,GNU Readline库的readline函数是我最好的选择。使用起来非常简单,但是它使用动态内存来托管字符串,因此您必须使用free函数来释放内存。您可以通过打开终端并键入“ man readline”来查找更多信息。
代码如下:

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <readline/readline.h>

int main() {

    char *ptr = readline("> ");
    if(!ptr){
        puts("eof");
    }
    else{
        puts(ptr);
    }
    free(ptr);

    return 0;
}

要在gcc中使用readline,必须将其传递给-lreadline

答案 2 :(得分:0)

这是不可避免的。简而言之,Ctrl+D结束当前的读取操作。

如果要忽略此内容,请基于fgets制作自己的fgetc,并忽略文件结尾。