2016-01-08 3 views
1

Итак, я сделал эту функцию, которая действует как обратный отсчет. Я хочу прочитать команду, пока обратный отсчет уменьшается. Моя большая проблема заключается в том, что read() ждет ввода во время обратного отсчета. Как вы можете видеть, я попытался использовать select(), но после первого printf("timeout.\n"); он перестает читать. Я сделал шоу только один раз timeout, иначе он пойдет, пока обратный отсчет не достигнет 0. Мне нужно попробовать снова прочитать.Как сделать read() неблокирование и сброс read()

int timer(int seconds) 
{ 
    time_t start, end; 
    double elapsed; 
    int opened=0; 
    char command[10]; 
    struct timeval tv; 
    int fd_stdin,rv; 
    fd_set rd; 

    fd_stdin=fileno(stdin); 

    FD_ZERO(&rd); 
    FD_SET(fileno(stdin),&rd); 

    tv.tv_sec=5; 
    tv.tv_usec=0; 

    time(&start); /* start the timer */ 

    do 
    { 
     time(&end); 

     elapsed = difftime(end, start); 

     if(fmod(elapsed,5)==0) 
     { 
      printf("Time remaining: %f minutes.\n", (seconds-elapsed)/60); 
      sleep(1); 
      if(opened==0) 
      { 
       printf("Use opentest to open your test.\n"); 
       opened=1; 
      } 
      fflush(stdout); 
     } 
     int c; 
     rv=select(fd_stdin+1,&rd,NULL,NULL,&tv); 
     if(rv==-1) 
     { 
      perror("Error on select.\n"); 
      exit(1); 
     } 
     else if (rv==0 && c!=1) 
     { 
      printf("timeout.\n"); 
      rv=select(fd_stdin+1,&rd,NULL,NULL,&tv); 
      c=1; 
     } 
     else 
     { 
      c=0; 
      read(fd_stdin,command,10); 
     } 
    } 
    while(elapsed < seconds); 
    return 0; 
} 

EDIT: использовать функцию fmod(), я составляю так: gcc client.c -lm -o client.exe. Я не думаю, что это проблема, но я не уверен.

ответ

1

select() изменяет fd_set после выхода, чтобы отразить, какие дескрипторы были сигнализированы. Вы не сбрасываете fd_set после каждого таймаута.

Кроме того, на некоторых платформах, select() изменяет timeval структуру, чтобы отразить, сколько времени осталось, так что вам придется сбросить timeval каждый раз, когда вы называете select() на этих платформах.

Кроме того, ваша переменная c объявлена ​​внутри цикла и неинициализирована. Переместите его за пределы цикла.

Попробуйте что-то больше, как это:

int timer(int seconds) 
{ 
    time_t start, end; 
    double elapsed; 
    int opened = 0; 
    char command[10]; 
    struct timeval tv; 
    int fd_stdin, rv; 
    fd_set rd; 
    int c = 0; 

    fd_stdin = fileno(stdin); 

    time(&start); /* start the timer */ 

    do 
    { 
     time(&end); 

     elapsed = difftime(end, start); 

     if (fmod(elapsed, 5) == 0) 
     { 
      printf("Time remaining: %f minutes.\n", (seconds-elapsed)/60); 
      sleep(1); 
      if (opened == 0) 
      { 
       printf("Use opentest to open your test.\n"); 
       opened = 1; 
      } 
      fflush(stdout); 
     } 

     FD_ZERO(&rd); 
     FD_SET(fd_stdin, &rd); 

     tv.tv_sec = 5; 
     tv.tv_usec = 0; 

     rv = select(fd_stdin+1, &rd, NULL, NULL, &tv); 
     if (rv == -1) 
     { 
      perror("Error on select.\n"); 
      exit(1); 
     } 
     else if (rv == 0) 
     { 
      if (c != 1) 
      { 
       printf("timeout.\n"); 
       c = 1; 
      } 
     } 
     else 
     { 
      c = 0; 
      read(fd_stdin, command, 10); 
     } 
    } 
    while (elapsed < seconds); 
    return 0; 
} 
+0

Спасибо. Это сделал трюк. – user2907139

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