2

所以我想要一种方法来控制输入提示等待用户输入内容的时间。

例如在以下代码中:

#include <stdio.h>

int main(void){

    int i, value;
    for (i=0;i<10;i++){
            scanf(" %d", &value);
    }
}

如果用户在 5 秒后没有输入任何输入,我如何让程序打破 for 循环?

4

3 回答 3

2

这是 , 的通用版本scanfsync_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会按原样返回。
于 2013-09-01T23:34:28.473 回答
2

您可以使用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);
}
于 2013-09-02T00:14:54.603 回答
1
#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);
}
于 2013-09-01T23:13:05.897 回答