2014-12-23 1 views
0

Чтобы более четко объяснить, что я хочу делать, я хочу, чтобы мой код проверял, вводит ли пользователь что-то (или если другой файловый дескриптор, чем 0, имеет данные для чтения) каждые (скажем) 2,5 секунды и так до тех пор, пока программа не остановится.Переключение между операторами, если пользователь вводит что-то: бесконечно и с таймаутом

Если пользователь вводит что-либо, простой printf() уведомит его, а затем программа снова проверит, вводит ли пользователь что-то в течение следующих 2,5 секунд.

Else, он должен просто распечатать, что время закончилось, а затем снова проверить вход пользователя в течение следующих 2,5 секунд.

А вот фрагмент кода я украл из Beej's Guide to Network Programming и модифицирована, чтобы (попытаться) выполнить мои требования:

#include <stdio.h> 
#include <sys/time.h> 
#include <sys/types.h> 
#include <unistd.h> 

#define STDIN 0 // file descriptor for standard input 

int main(void){ 
    struct timeval tv; 
    fd_set readfds; 

    FD_ZERO(&readfds); 
    FD_SET(STDIN, &readfds); 

    tv.tv_sec = 2; 
    tv.tv_usec = 500000; 

    while(1){ 
     select(STDIN+1, &readfds, NULL, NULL, &tv); 

     if (FD_ISSET(STDIN, &readfds)){ 
      printf("A key was pressed!\n"); 
      tv.tv_sec = 2; 
      tv.tv_usec = 500000; 

     }else{ 
      printf("Timed out.\n"); 
      tv.tv_sec = 2; 
      tv.tv_usec = 500000; 

     } 

    } 
    return 0; 
} 

Пока я не нажимать клавиши, это работает отлично и печатает «тайм-аут. " каждые 2,5 секунды. Но если я что-то введу, то кажется, чтобы игнорировать ввод пользователя и сохраняет печать «Timed out».

С другой стороны, если я объявляю fd_set и struct timevalвнутри бесконечного цикла, когда я ввожу что-то, это печатает бесконечно, что клавиша была нажата , как будто она игнорирует тайм-аут.

Я понятия не имею, почему такой простой код не работает. Наверное, мне не хватает информации о дескрипторах файлов, о которых я не знаю.

+0

Повторяющийся вопрос - я отслежу его. В принципе, вы должны установить 'readfds' на каждой итерации; 'select()' zaps it. –

+0

@JonathanLeffler, что вы подразумеваете под «настройкой' readfds' на каждой итерации »? Что-то вроде решения @iharob? Я уже пробовал это, но в этом случае программа печатает «ключ был нажат» бесконечно. – TheReader

+0

Что сказал iharob в своем ответе, и что дублирует вопрос в его ответах. После вызова 'select', значение в' readfds' было изменено 'select', в общем, поэтому вам нужно правильно инициализировать его на каждой итерации цикла. –

ответ

1

Потому что вы должны сбросить ->FD_ZERO(&readfds) ваших readfds и добавить файл desciptor ->FD_SET(STDIN, &readfds) каждый раз select возвращается, так как по истечению времени ожидания дескриптор файла удаляются из набора

#include <stdio.h> 
#include <sys/time.h> 
#include <sys/types.h> 
#include <unistd.h> 

#define STDIN 0 // file descriptor for standard input 

int main(void){ 
    struct timeval tv; 
    fd_set readfds; 

    while (1) { 
     int count; /* how many descriptors are contained in the set. */ 

     FD_ZERO(&readfds); 
     FD_SET(STDIN, &readfds); 

     tv.tv_sec = 2; 
     tv.tv_usec = 500000; 

     count = select(STDIN + 1, &readfds, NULL, NULL, &tv); 
     if ((count > 0) && (FD_ISSET(STDIN, &readfds) != 0)) { 
      printf("A key was pressed!\n"); 
     } else if (count == -1) 
      /* check for the error here */ 
     } else { 
      printf("Timed out.\n"); 
     } 
    } 
    return 0; 
} 

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

+0

Вы уверены, что это работает? В любом случае, спасибо за напоминание о том, как поймать возможные ошибки. – TheReader

+0

Я абсолютно уверен. :) –

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