при нажатии control + d fgets не перестает читать - PullRequest
0 голосов
/ 08 июня 2019

Когда вы читаете из stdin с помощью getchar, fgets или какой-либо подобной функции, если вы набираете некоторый текст, а затем вставляете eof (control + d в linux), вы не можете удалить предыдущий текст.Например, если я наберу «program», а затем введу eof, нажав control + d, я не смогу удалить то, что набрал ранее, то есть программу.

#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 ]

1 голос
/ 08 июня 2019

Когда fgets читает строку, произойдет то, что он будет читать символы из указанного потока, пока не встретит '\n' или EOF, пока не будет прочитан указанный максимальный размер для чтения или ошибка чтения. происходит. Он вообще не видит, что вы делаете на клавиатуре. Он видит только поток, но это терминал, который отправляет данные в поток.

То, что происходит при редактировании ввода, не имеет абсолютно никакого отношения к fgets. Это работа с терминалами.

Как писал в комментариях Эрик Постпищил:

Нажатие control-D в Linux не сигнализирует EOF. На самом деле это означает «завершить текущую операцию чтения». В этот момент, если символы были введены, они немедленно отправляются в программу, тогда как система обычно будет ждать, пока не будет нажата Enter. Если никакие символы не были введены, операция чтения завершается с нулевым чтением символов, которое некоторые процедуры ввода / вывода рассматривают как EOF, и именно поэтому программы могут казаться, что получают EOF, когда нажатие клавиши control-D в начале строки ввода. Поскольку данные отправляются в программу, отменить их, конечно, невозможно - они уже отправлены.

Я думаю, что есть какой-то способ изменить поведение нажатия C-d, но тогда вам нужно решить, что он должен делать вместо этого. Если вы хотите, чтобы он ничего не делал вместо отправки данных на stdin, я не вижу, что вы выиграли. Единственный вариант использования, который я вижу, это то, что у вас по какой-то причине возникают проблемы с случайным нажатием клавиши C-d время от времени.

Одна вещь, которую вы могли бы сделать, это получить полный контроль над каждым нажатием клавиши. Затем вам придется писать код для перемещения курсора каждый раз, когда пользователь нажимает клавишу, а также писать код для удаления символов, когда пользователь нажимает клавишу Backspace. Для этого вы можете использовать библиотеку типа ncurses.

1 голос
/ 08 июня 2019

Функция readline библиотеки GNU 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;
}

Чтобы использовать readline с gcc, вы должны передать его -lreadline

0 голосов
/ 08 июня 2019

Этого нельзя избежать. Проще говоря, Ctrl+D завершает текущую операцию чтения.

Если вы хотите игнорировать это, создайте собственный fgets на основе fgetc и сделайте так, чтобы он игнорировал конец файла.

...