5

我们知道输入函数或运算符(cin、scanf、gets….etc)等待从用户那里获取输入,这个时间没有限制。

现在,我会问一个问题,用户给出答案,到目前为止没有问题,但我的问题是“用户有时间(可能 30 或 40 秒)给出输入,如果他失败,那么输入语句将自动停用并执行下一条语句。”</p>

我想你明白我的问题。那么请在这种情况下帮助我。如果有人给我一些真正有效的示例代码会更好。

我在 Windows 7 中使用 codebolck 12.11。

4

3 回答 3

10

*IX'ish 系统(包括 Windows 上的 Cygwin)的一种方法:

您可以使用alarm()来安排 a SIGALRM,然后使用read(fileno(stdin), ...).

当信号到达read()时应返回-1并设置errnoEINTR

例子:

#define _POSIX_SOURCE 1

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>

void handler_SIGALRM(int signo)
{
  signo = 0; /* Get rid of warning "unused parameter ‘signo’" (in a portable way). */

  /* Do nothing. */
}

int main()
{
  /* Override SIGALRM's default handler, as the default handler might end the program. */
  {
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));

    sa.sa_handler = handler_SIGALRM;

    if (-1 == sigaction(SIGALRM, &sa, NULL ))
    {
      perror("sigaction() failed");
      exit(EXIT_FAILURE);
    }
  }

  alarm(2); /* Set alarm to occur in two seconds. */

  {
    char buffer[16] = { 0 };

    int result = read(fileno(stdin), buffer, sizeof(buffer) - 1);
    if (-1 == result)
    {
      if (EINTR != errno)
      {
        perror("read() failed");
        exit(EXIT_FAILURE);
      }

      printf("Game over!\n");
    }
    else
    {
      alarm(0); /* Switch of alarm. */

      printf("You entered '%s'\n", buffer);
    }
  }

  return EXIT_SUCCESS;
}

注意:在上面的示例中,阻塞调用read()将在任何信号到达时中断。避免这种情况的代码留给读者执行...... :-)

于 2013-08-17T14:25:48.620 回答
2

另一种方法:
您可以使用 POSIX select()函数(和一些宏FD_ZERO, FD_SET, FD_ISSET)来检查哪些文件描述符(0在这种情况下是描述符编号,即标准输入)准备好在给定的时间间隔内读取。当它们准备好时,使用适当的函数来读取数据(scanf()在这种情况下)。
这段代码可能会帮助你理解我想说的:

#include <sys/select.h>
#include <sys/time.h>
#include <stdio.h>

#define STDIN    0    // Standard Input File Descriptor
int main()
{
    fd_set input;       // declare a "file descriptor set" to hold all file descriptors you want to check
    int fds, ret_val, num;  // fds: Number of file descriptors;

    struct timeval tv;      // structure to store Timeout value in the format used by select() function
    unsigned int timeout = 5;   // Your timeout period in seconds

    tv.tv_sec = timeout;    
    tv.tv_usec = 0;

    fds = STDIN + 1;            // Set number of file decriptors to "1 more than the greatest file descriptor"
                // Here, we are using only stdin which is equal to 0

    FD_ZERO(&input);        // Initialize the set with 0
    FD_SET(STDIN, &input);      // Add STDIN to set

    printf("Enter a number within %d secs\n", timeout);
    ret_val = select(fds, &input, NULL, NULL, &tv); 
                // We need to call select only for monitoring the "input file descriptor set"
                // Pass rest of them as NULL

    if (ret_val == -1)          // Some error occured
        perror("select()");
    else if (ret_val > 0)       // At least one of the file descriptor is ready to be read
    {
//      printf("Data is available now.\n");
        if(FD_ISSET(0, &input))     // Check if stdin is set, here its not necessary as we are using STDIN only
                // So ret_val>0 means STDIN is raedy to read 
        {
            scanf("%d", &num);
        }
    }
    else
        printf("No data within five seconds.\n");   // select returns zero on timeout

    return 0;
}

更多帮助: 选择(2)

您还可以尝试使用(同样是 POSIX 标准函数)中可用的 poll() 函数作为 select() 的替代方法。见民意调查()民意调查(2)

于 2013-08-17T18:36:04.057 回答
0
#include <cstddef>
#include <ctime>
#include <iostream>
#include <conio.h>

bool get_input ( char *buffer, std::size_t size, int timeout )
{
     std::time_t start = std::time ( 0 );
     std::size_t n = 0;

   for ( ; ; ) {
    if ( n == 0 && std::difftime ( std::time ( 0 ), start ) >= timeout )
     return false;

    if ( kbhit() ) {
  if ( n == size - 1 )
    break;

  char ch = (int)getche();

  if ( ch == '\r' ) {
    buffer[n++] = '\n';
    break;
  }
  else
    buffer[n++] = ch;
  }
}

 buffer[n] = '\0';

return true;
}

 int main()
{
char buffer[512] = {0};

if ( !get_input ( buffer, 512, 5 ) ) {
std::cout<<"Input timed out\n";
buffer[0] = '\n';
}

std::cout<<"input: \""<< buffer <<"\"\n";
}
于 2014-08-24T14:48:39.263 回答