Как я могу переопределить stdin, чтобы он указывал на консоль после использования перенаправления файлов в Unix? - PullRequest
3 голосов
/ 22 сентября 2019

Я работаю в Unix, и я должен сначала прочитать текст с помощью перенаправления, а затем попросить пользователя ввести определенный символ и посчитать, сколько раз он находится в массиве символов.

const int MAX = 8000;
int input = 1;
int i = 0;
char text[MAX], letter;
while(input != 0)
{
    scanf("%c", &text[i]);
    if(text[i] == '0')
        input = 0;
    i++;
}
printf("\n%s",text);

printf("\nEnter a letter to search for in the text: ");
scanf("%c", &letter)

В настоящее время я печатаю правильный файл с помощью перенаправления, однако мой второй scanf пропускается.Я перенаправляю файл с помощью команды: ./a.out < filename.txt.

Если я попытаюсь напечатать символ letter, это ничего не даст.Он должен читать \n из пустых строк текстового файла.Как мне остановить scanf от чтения того же текстового файла и позволить мне ввести букву с моей клавиатуры в консоли?В качестве задания я должен использовать команду ./a.out < filename.txt.

Ответы [ 2 ]

3 голосов
/ 22 сентября 2019

Функция freopen() - это именно то, что вы ищете.Вам просто нужно использовать его, чтобы (повторно) открыть /dev/tty как stdin./dev/tty - это специальный файл, относящийся к терминалу, который запустил программу.

С страницы руководства :

Функция freopen() открывает файлимя которого является строкой, на которую указывает pathname, и связывает с ней поток, на который указывает stream.Исходный поток (если он существует) закрыт.Аргумент mode используется так же, как и в функции fopen().

[...]

Основное использование функции freopen() - изменение файла.связанный со стандартным текстовым потоком (stderr, stdin или stdout) .

Вот пример:

// ...

FILE *tty;

tty = freopen("/dev/tty", "r", stdin);
if (tty == NULL) {
    perror("Unable to open terminal for reading");
    exit(1);
}

printf("Enter a letter to search for in the text: ");

// Now scanf will read from the console where the process started.
scanf("%c", &letter);

ByКстати, у вашей программы есть некоторые проблемы.Вы можете читать после конца вашего text массива, неправильно завершать его символом NUL и также не проверять ошибки.Более правильная версия будет:

const size_t MAX = 8000;
char text[MAX];
size_t i;
int c;

for (i = 0; i < MAX; i++)
{
    c = fgetc(stdin);

    if (c == EOF)
        break;

    text[i] = (char)c;
}

text[i] = '\0';

puts(text);
1 голос
/ 22 сентября 2019

Есть несколько способов сделать это, вероятно, самый простой - просто открыть /dev/tty, которое является специальным устройством, относящимся к терминалу, подключенному к текущему процессу.Я не рекомендую заменять stdin, так как тогда вы потеряете доступ к вашему файлу, который там перенаправлен.Вместо этого просто используйте другой указатель файла и используйте такие функции, как fscanf и fgetc.Например:

FILE *tty = fopen("/dev/tty", "r");

// fopen will return NULL if there is no attached terminal
if(NULL == tty)
{
     fputs("Failed opening /dev/tty", stderr);
}
else
{
    printf("\nEnter a letter to search for in the text: ");

    // Read a character from the terminal
    char search = fgetc(tty);

    // Now you can still read from the file on stdin and search for
    // your letter without needing an array (which may not be large
    // enough for the whole file)
    char ch;
    int count = 0;
    while(EOF != (ch = getchar())
    {
        if(ch == search)
            ++count;
    }

    printf("%d occurrences of %c\n", count, search);
}

Для получения дополнительной информации о /dev/tty и других подобных специальных файлах см .: https://unix.stackexchange.com/questions/60641/linux-difference-between-dev-console-dev-tty-and-dev-tty0

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...