如何让C语言程序仅等待输入一段时间而非无限等待?
带超时的终端字符输入修改方案
原程序通过system("stty raw")设置终端为原始模式,但getchar()会无限等待输入,导致超时场景下无法输出-。以下是两种可靠的修改方案,核心是实现输入超时机制:
方案一:使用select实现超时(推荐)
select是POSIX标准函数,可监听文件描述符状态并设置超时,逻辑清晰且无信号干扰问题:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/select.h> #include <termios.h> int main(void) { char c = 'A'; struct termios old_tio, new_tio; fd_set readfds; struct timeval timeout; // 保存原终端属性,设置为原始模式 tcgetattr(STDIN_FILENO, &old_tio); new_tio = old_tio; // 关闭规范模式(无需回车读取)和回显(输入不显示) new_tio.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &new_tio); // 配置超时:5秒0微秒,可自行调整 timeout.tv_sec = 5; timeout.tv_usec = 0; FD_ZERO(&readfds); FD_SET(STDIN_FILENO, &readfds); // 监听标准输入,等待超时或输入 int ret = select(STDIN_FILENO + 1, &readfds, NULL, NULL, &timeout); if (ret > 0) { // 有输入可读,读取字符 c = getchar(); } // ret == 0 表示超时,保持c='A';ret <0 表示出错,此处简化处理 // 恢复终端原属性,避免影响后续操作 tcsetattr(STDIN_FILENO, TCSANOW, &old_tio); if (c == 'A') printf("-\n"); else printf("+\n"); return 0; }
关键说明:
- 替代
system调用:直接用termios系列函数操作终端属性,比依赖shell的stty命令更可靠,避免环境差异问题。 select超时逻辑:通过struct timeval设置超时时长,FD_SET将标准输入加入监听集合。当select返回大于0时,说明有输入,才调用getchar()读取;返回0则表示超时,保持初始的c='A'。
方案二:使用alarm信号实现超时
通过设置闹钟信号中断阻塞的getchar(),适合简单场景,但需注意信号处理的细节:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <signal.h> #include <termios.h> #include <errno.h> void timeout_handler(int sig) { // 超时信号的空处理函数,仅用于中断阻塞调用 } int main(void) { char c = 'A'; struct termios old_tio, new_tio; // 注册SIGALRM信号处理函数 signal(SIGALRM, timeout_handler); // 保存并设置终端原始模式 tcgetattr(STDIN_FILENO, &old_tio); new_tio = old_tio; new_tio.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &new_tio); // 设置5秒超时闹钟 alarm(5); int ch = getchar(); if (ch != -1 || errno != EINTR) { // 读取成功,取消未触发的闹钟 alarm(0); c = ch; } // 恢复终端属性 tcsetattr(STDIN_FILENO, TCSANOW, &old_tio); if (c == 'A') printf("-\n"); else printf("+\n"); return 0; }
关键说明:
alarm(5)会在5秒后发送SIGALRM信号,中断正在阻塞的getchar(),此时getchar()返回-1且errno设为EINTR。- 若输入在超时前到达,需调用
alarm(0)取消未触发的闹钟,避免后续不必要的信号触发。
内容的提问来源于stack exchange,提问作者12iq
相关产品推荐
相关产品推荐

