如何防止scanf()永远等待输入字符?

我想在控制台应用程序中完成以下事项:

  1. 如果用户输入字符,则应用程序将执行相应的任务。 例如,如果用户输入’1’,程序将执行任务1,如果用户输入’q’,程序将退出;
  2. 如果用户没有输入任何内容,程序将每10秒执行一次默认任务(时间不必非常严格)。

这是我的代码:

#include  #include  char buff[64]; char command; while(command != 'q') { begin: printf(">> "); scanf("%s", buff); command = buff[0]; switch (command) { case '1': // task 1 code will be added here; break; case '2': // task 2 code will be added here; break; case 'q': printf("quit the loop.\n"); break; } // wait for 10 seconds; Sleep(10000); // default task code will be added here; if(command != 'q') { goto begin; } } 

但问题是如果没有输入字符,程序将永远陷入scanf()函数的行,等待输入字符。 所以我想知道如何在一段时间之后跳过scanf()行,我的意思是,例如,如果1秒后没有输入,程序可以继续,以便完成上面列出的第二件事。

我是c编程的新手,提前感谢你的回答。

非常感谢您的回答。 该平台是Windows; 我在while()之后删除了分号,这是一个明显的错误。

尝试使用select()函数。 然后你可以等待10秒,直到你可以不受阻塞地读取标准输入。 如果select()返回零,则执行默认操作。 我不知道这是否适用于Windows,它是POSIX标准。 如果您碰巧在unix / linux上开发,请尝试man select

我刚刚用select编写了一个工作示例:

 #include  #include  #include  #include  #include  #include  #include  #include  #define MAXBYTES 80 int main(int argc, char *argv[]) { fd_set readfds; int num_readable; struct timeval tv; int num_bytes; char buf[MAXBYTES]; int fd_stdin; fd_stdin = fileno(stdin); while(1) { FD_ZERO(&readfds); FD_SET(fileno(stdin), &readfds); tv.tv_sec = 10; tv.tv_usec = 0; printf("Enter command: "); fflush(stdout); num_readable = select(fd_stdin + 1, &readfds, NULL, NULL, &tv); if (num_readable == -1) { fprintf(stderr, "\nError in select : %s\n", strerror(errno)); exit(1); } if (num_readable == 0) { printf("\nPerforming default action after 10 seconds\n"); break; /* since I don't want to test forever */ } else { num_bytes = read(fd_stdin, buf, MAXBYTES); if (num_bytes < 0) { fprintf(stderr, "\nError on read : %s\n", strerror(errno)); exit(1); } /* process command, maybe by sscanf */ printf("\nRead %d bytes\n", num_bytes); break; /* to terminate loop, since I don't process anything */ } } return 0; } 

注意:下面的poll()示例也可以,没问题。 其余的我选择将可用字节读入缓冲区(最多MAXBYTES)。 之后可以进行扫描。 (scanf()对我的朋友来说不是太多,但那是个人品味问题)。

这是一个如何使用poll执行此操作的示例(可能是Linux上最“正确”的方式):

 #include  #include  #include  int main() { struct pollfd mypoll = { STDIN_FILENO, POLLIN|POLLPRI }; char string[10]; if( poll(&mypoll, 1, 2000) ) { scanf("%9s", string); printf("Read string - %s\n", string); } else { puts("Read nothing"); } return 0; } 

超时是poll的第三个参数,以毫秒为单位 – 此示例将在stdin上等待2秒。 Windows有WSAPoll ,它的工作方式应该类似。

但问题是程序会永远陷入scanf()函数的行,等待输入字符,

稍后删除分号。

试试闹钟(3)

 #include  #include  int main(void) { char buf [10]; alarm(3); scanf("%s", buf); return 0; } 

正如其他人所说,真正实现异步IO的最佳方法是使用select(...)

但是快速而肮脏的方式来做你想要的是使用getline(...) ,它将返回每次读取的字节数(不挂在IO上),并且在没有字节读取时返回-1。

以下内容来自getline(3)手册页:

 // The following code fragment reads lines from a file and writes them to standard output. // The fwrite() function is used in case the line contains embedded NUL characters. char *line = NULL; size_t linecap = 0; ssize_t linelen; while ((linelen = getline(&line, &linecap, fp)) > 0) fwrite(line, linelen, 1, stdout);