所以我想要一种方法来控制输入提示等待用户输入内容的时间。
例如在以下代码中:
#include <stdio.h>
int main(void){
int i, value;
for (i=0;i<10;i++){
scanf(" %d", &value);
}
}
如果用户在 5 秒后没有输入任何输入,我如何让程序打破 for 循环?
这是 , 的通用版本scanf
,sync_scanf
女巫应该等待您选择的秒数,否则将返回-2
超时:
int sync_scanf(time_t sec, const char *format, ...);
例子:
#include <stdio.h>
#include <stdarg.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int sync_scanf(time_t sec, const char *format, ...);
int main(int argc, char **argv) {
int i;
int value;
int ret;
for (i = 0 ; i < 10 ; i++ ) {
ret = sync_scanf(3, "%d", &value);
if( ret > 0 ) {
printf("OK %d\n", value);
} else if( ret == -2 ) {
printf("3 seconds passed and you typed nothing!\n");
break;
} else {
printf("No enough arguments\n");
break;
}
}
return 0;
}
int sync_scanf(time_t sec, const char *format, ...) {
int re;
va_list arg;
fd_set readfds;
struct timeval timeout = {0};
timeout.tv_sec = sec;
FD_ZERO(&readfds);
FD_SET(0, &readfds);
re = select(1, &readfds, NULL, NULL, &timeout);
if( re == -1 ) {
perror("Error");
return -1;
}
else if( re == 0 ) {
return -2;
}
va_start(arg, format);
re = vfscanf(stdin, format, arg);
va_end(arg);
return re;
}
演示:
$ gcc -Wall sample.c
$ ./a.out
232
OK 232
3 seconds passed and you typed nothing!
$ ./a.out
32
OK 32
fewf
No enough arguments
$
它的工作原理是,scanf
但您首先在几秒钟内通过超时:
int sync_scanf(time_t sec, const char *format, ...);
它返回:
-1
关于失败。-2
超时。scanf
会按原样返回。您可以使用select(监视标准输入一段时间以检查输入是否可用于读取)、fgets(安全地将输入数据读取到缓冲区)和strtol(如果可能,将缓冲区字符串转换为长整数)来实现您想要的。
下面给出了示例代码(检查手册页,例如扩展错误处理):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
int main(int argc, char *argv[])
{
fd_set rfds;
struct timeval tv;
int i, val, retval;
char *endptr, buff[255];
for (i=0;i<10;i++){
/* Watch stdin (fd 0) to see when it has input. */
FD_ZERO(&rfds);
FD_SET(0, &rfds);
/* Wait up to five seconds. */
tv.tv_sec = 5;
tv.tv_usec = 0;
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval == -1){
perror("select()");
exit(EXIT_FAILURE);
}
else if (retval){
/* FD_ISSET(0, &rfds) is true so input is available now. */
/* Read data from stdin using fgets. */
fgets(buff, sizeof(buff), stdin);
/* Convert data stored in the buffer to long int. */
errno = 0;
val = strtol(buff, &endptr, 10);
/* First, check for various possible errors. */
if (errno != 0 && val == 0) {
perror("strtol()");
exit(EXIT_FAILURE);
}
if (endptr == buff) {
fprintf(stderr, "No digits were found.\n");
exit(EXIT_FAILURE);
}
/* If we got here, strtol successfully parsed a number. */
printf("%d was read from stdin.\n", val);
}
else{
printf("No data within five seconds.\n");
break;
}
}
exit(EXIT_SUCCESS);
}
#include <signal.h>
#include <setjmp.h>
#include <stdio.h>
int flag;
static sigjmp_buf jmpbuf;
static void sig_arm(int signo)
{
if(flag == -1)
return;
else if(flag == 0)
siglongjmp(jmpbuf,1);
}
int main(void){
int i, value;
signal(SIGALRM,sig_arm);
for (i=0;i<10;i++){
if(sigsetjmp(jmpbuf,0) == 0)
{
flag = 0;
alarm(5);
scanf(" %d", &value);
flag = 1;
}
if(flag == 0) // 5 second out
break;
}
flag = -1;
alarm(0);
}