Как я могу проверить, есть ли в моей программе данные - PullRequest
7 голосов
/ 02 апреля 2010

Я пишу программу, которая должна читать ввод через stdin, поэтому у меня есть следующий контракт.

FILE *fp=stdin;

Но это просто зависает, если пользователь ничего не передавал в программу, как я могу проверить, действительно ли пользователь передает данные в мою программу, например

gunzip -c file.gz |./a.out #should work
./a.out  #should exit program with nice msg.

спасибо

Ответы [ 6 ]

8 голосов
/ 02 апреля 2010

Поскольку вы используете файловые указатели, для этого вам понадобятся isatty() и fileno():

#include <unistd.h>
#include <stdio.h>

int main(int argc, char* argv[])
{
    FILE* fp = stdin;

    if(isatty(fileno(fp)))
    {
        fprintf(stderr, "A nice msg.\n");
        exit(1);
    }

    /* carry on... */
    return 0;
}

На самом деле, это долгий путь. Короткий путь - не использовать файловые указатели:

#include <unistd.h>

int main(int argc, char* argv[])
{
    if(isatty(STDIN_FILENO))
    {
        fprintf(stderr, "A nice msg.\n");
        exit(1);
    }

    /* carry on... */
    return 0;
}

Несколько стандартных программ Unix делают эту проверку, чтобы изменить свое поведение. Например, если вы настроили ls, чтобы дать вам красивые цвета, он отключит цвета, если вы передадите его стандартный вывод в другую программу.

3 голосов
/ 02 апреля 2010

Попробуйте "man isatty", я думаю, эта функция скажет вам, говорите ли вы с пользователем или нет.

3 голосов
/ 02 апреля 2010

Передача stdin для select () или poll () должна сообщить вам, ожидает ли ввод. Под многими операционными системами вы также можете определить, является ли stdin tty или pipe.

РЕДАКТИРОВАТЬ: я вижу, что мне придется подчеркнуть также часть теста tty. Fifo - это не tty, но может не быть готовых к вводу в течение неопределенного периода времени.

2 голосов
/ 02 апреля 2010

Используйте isatty, чтобы обнаружить, что стандартный ввод поступает с терминала, а не с перенаправления.

1 голос
/ 02 апреля 2010

См. Функцию "isatty" - если STDIN является терминалом, вы можете пропустить чтение с него. Если это не терминал, вы получаете данные по каналу или перенаправлены, и вы можете читать до EOF.

0 голосов
/ 02 апреля 2010

Дополнительная опция, которую вы получаете с помощью select (), устанавливает тайм-аут для чтения со стандартного ввода (относительно первого чтения со стандартного ввода или последовательных чтений со стандартного ввода).

Пример кода с использованием select on stdin см .:

Как проверить, открыт ли stdin без блокировки?

...