我们知道输入函数或运算符(cin、scanf、gets….etc)等待从用户那里获取输入,这个时间没有限制。
现在,我会问一个问题,用户给出答案,到目前为止没有问题,但我的问题是“用户有时间(可能 30 或 40 秒)给出输入,如果他失败,那么输入语句将自动停用并执行下一条语句。”</p>
我想你明白我的问题。那么请在这种情况下帮助我。如果有人给我一些真正有效的示例代码会更好。
我在 Windows 7 中使用 codebolck 12.11。
*IX'ish 系统(包括 Windows 上的 Cygwin)的一种方法:
您可以使用alarm()
来安排 a SIGALRM
,然后使用read(fileno(stdin), ...)
.
当信号到达read()
时应返回-1
并设置errno
为EINTR
。
例子:
#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()
将在任何信号到达时中断。避免这种情况的代码留给读者执行...... :-)
另一种方法:
您可以使用 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)
#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";
}