2014-11-15 2 views
2

Я пытаюсь прочитать символ числа с символом, но я не знаю, пуст ли stdin пуст или нет.Проверка буфера stdin, если он пуст

Мое первое решение, которое нужно искать в символе '\ n' в буфере stdin, но это нехорошо, если мне нужно ввести несколько чисел, разделенных пробелом '' (пробел).

Как узнать, есть ли в буфере stdin у меня есть символы или нет?

Я не делаю это в C и не переношу.

+1

Try «Человек выберите» –

+0

Проверка на EOF. (Это не символ, но будет возвращено значение, если поток пуст.) – UncleO

ответ

1

Есть много soutions:

feof предпочтителен один для проверки, если буфер пуст.

if (!feof(stdin)) // Check if the stdin is empty 
    // read stuff 

poll или select с тайм-аут 0 - это будет немедленно вернуться и результат либо -1 с ERRNO EAGAIN если данные отсутствуют или количество дескрипторов с данными (один, так как вы проверяете только STDIN).

ioctl - швейцарский армейский нож с дескрипторами. Запрос вам нужно I_NREAD:

if (ioctl(0, I_NREAD, &n) == 0 && n > 0) 
    // we have exactly n bytes to read 

Однако правильное решение, чтобы прочитать все, что вы получили (с помощью scanf) в качестве линии, а затем обработать результат - и это работает достаточно хорошо с sscanf:

char buf[80]; // large enough 
scanf("%79s", buf); // read everything we have in stdin 
if (sscanf(buf, "%d", &number) == 1) 
    // we have a number 

... до тех пор, пока вы должным образом обрабатываете повторное чтение, строки, которые больше, чем ваш буфер, и другие реальные осложнения.

+1

если я пытаюсь что-то вроде этого 'while (! Feof (stdin)) { c = getchar(); putchar (c); } '}' , введя бесконечный цикл – Tandura

+0

Функции 'poll' /' select'/'ioctl' не будут работать, потому что я не располагаю новой библиотекой, которая не включена в стандартную среду IDE (Code :: Blocks, которые я использую в колледжа), поэтому решение остается третьим, читающим его с баффом и проверяющим, будет ли длина buf равна 80 (в данном случае), тогда я должен продолжать читать – Tandura

+1

Если ваш stdin читается с консоли, он будет в EOF, только если вы насколько мне известно, отправьте EOF-символ, который является 'ctrl + d'. 'poll',' select', 'ioctl' - все функции POSIX и ... было бы не по теме обсуждать, должно ли оно быть в любой системе.Решение 'sscanf' с другой стороны должно работать так, как есть. – aragaer

2

Для тех, кто приезжает сюда из Google - легко select решение проверить stdin: пустота

fd_set readfds; 
FD_ZERO(&readfds); 
FD_SET(STDIN_FILENO, &readfds); 
fd_set savefds = readfds; 

struct timeval timeout; 
timeout.tv_sec = 0; 
timeout.tv_usec = 0; 

int chr; 

if (select(1, &readfds, NULL, NULL, &timeout)) { 
    puts("Input:"); 
    while ((chr = getchar()) != EOF) putchar(chr); 
} 
readfds = savefds; 

Needs unistd.h, stdlib.h и stdio.h.

Пояснение может быть найдено here.

+0

работает на linux, но не на окнах (он должен быть портативным) – Tandura

+0

@Tandura на любой совместимой с POSIX системе. Обычно в Windows вы должны использовать специальные методы, которые не будут работать в других системах. Поэтому я думаю, что любой * nix лучше, чем просто Windows. Но да, это не полностью переносимо. Idk, как это сделать на Windows, может быть, вы знаете? – stek29

2

Я вдохновлен this, как ссылается @stek29's post на этой странице и подготовил простой пример следующим образом:

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

int main(void) 
{ 
    fd_set readfds; 
    FD_ZERO(&readfds); 

    struct timeval timeout; 
    timeout.tv_sec = 0; 
    timeout.tv_usec = 0; 

    char message[50]; 

    while(1) 
    { 
     FD_SET(STDIN_FILENO, &readfds); 

     if (select(1, &readfds, NULL, NULL, &timeout)) 
     { 
      scanf("%s", message); 
      printf("Message: %s\n", message); 
     } 

     printf("...\n"); 
     sleep(1); 
    } 

    return(0); 
} 
+0

работает для меня! я заменил sleep 'usleep (10);' и удалил 'printf (" ... \ n ");' – datahaki

Смежные вопросы