Debian Linux下如何实现C语言计数程序按Q键退出?
解决Debian Linux下C语言计数程序按Q退出的问题
问题根源
你之前的实现存在三个核心问题:
getchar()放在循环结束后执行,无法在计数过程中响应按键- 终端默认是行缓冲模式,
getchar()必须等按下回车才会返回,且是阻塞状态,会打断定时逻辑 - 判断条件错误:'Q'的ASCII值是
81(小写q是113),不是1
解决方案
在Linux下需要修改终端输入模式,关闭行缓冲和回显,用非阻塞方式检测按键。具体步骤:
- 保存终端原有属性,程序退出前恢复(避免终端状态异常)
- 将终端设置为非规范模式,让输入字符立即被读取,不需要回车
- 设置标准输入为非阻塞模式,避免读取操作阻塞定时逻辑
- 在计数循环中检测按键,若为'Q'或'q'则退出循环
修改后的完整代码
#include <stdio.h> #include <time.h> #include <unistd.h> #include <termios.h> // 终端控制头文件 #include <fcntl.h> // 文件控制头文件 int main() { struct timespec duration; struct timespec remaining; int time, num; struct termios old_term, new_term; int fd = STDIN_FILENO; // 保存原有终端属性 tcgetattr(fd, &old_term); // 复制属性并修改为非规范模式 new_term = old_term; new_term.c_lflag &= ~(ICANON | ECHO); // 关闭行缓冲和回显 new_term.c_cc[VMIN] = 0; // 最少读取0个字符(非阻塞) new_term.c_cc[VTIME] = 0; // 超时时间0 tcsetattr(fd, TCSANOW, &new_term); // 设置标准输入为非阻塞模式 int flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); duration.tv_sec = 1; duration.tv_nsec = 0; time = 0; num = 0; while(time <= 32767) { int result = nanosleep(&duration, &remaining); num++; if (result == 0) { printf("Seconds Passed: %d\n", num); time++; } else if (result == -1) { printf("Error with nanosleep\n"); break; // 替换goto,更规范 } // 检测按键输入 char c; ssize_t read_len = read(fd, &c, 1); if (read_len > 0 && (c == 'Q' || c == 'q')) { printf("\n退出程序\n"); break; } } // 恢复终端原有属性 tcsetattr(fd, TCSANOW, &old_term); fcntl(fd, F_SETFL, flags); // 恢复文件状态标志 return 0; }
关键代码解释
tcgetattr/tcsetattr:用于获取和设置终端属性,关闭ICANON(行缓冲)和ECHO(回显)fcntl:设置标准输入为非阻塞模式,read()不会等待输入,没有字符时直接返回-1- 循环内的
read():每次定时结束后检测是否有按键,若读取到'Q'或'q'则退出循环 - 程序结束前必须恢复终端属性,否则终端会保持无回显、无行缓冲的异常状态
内容的提问来源于stack exchange,提问作者Yakov Kotsarenko
相关产品推荐
相关产品推荐

