当您使用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;
}
如何避免这种情况?
答案 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
,并忽略文件结尾。