如何在程序运行任意时刻捕获按键以立即终止程序?
嘿,我懂你要啥——就是想让程序不管跑到哪一步(哪怕是在f1()或者f2()执行的时候),只要按个键(比如退格)就能立刻终止,而且不想在代码里到处插输入检查的逻辑对吧?这好办,给你分两种主流平台的解决方案,都是不用侵入业务代码的:
Unix/Linux 平台解决方案
核心思路是修改终端为非规范模式(不用等回车就能读取按键),然后开一个后台线程专门监听输入,一旦有任何按键触发就立刻终止程序:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <termios.h> #include <pthread.h> // 保存原终端属性,用于程序结束后恢复 struct termios old_tio; void* key_listener(void* arg) { char c; // 阻塞等待任意按键输入(非规范模式下按键会立即被读取) read(STDIN_FILENO, &c, 1); // 恢复终端原有属性,避免终端异常 tcsetattr(STDIN_FILENO, TCSANOW, &old_tio); printf("\n程序已终止\n"); exit(0); return NULL; } void f1() { // 你的f1函数逻辑 } void f2() { // 你的f2函数逻辑 } int main() { struct termios new_tio; pthread_t listener_thread; // 获取当前终端属性 tcgetattr(STDIN_FILENO, &old_tio); // 配置新终端属性:关闭行缓冲、关闭回显,设置为立即读取模式 new_tio = old_tio; new_tio.c_lflag &= ~(ICANON | ECHO); new_tio.c_cc[VMIN] = 1; new_tio.c_cc[VTIME] = 0; tcsetattr(STDIN_FILENO, TCSANOW, &new_tio); // 创建后台监听线程 pthread_create(&listener_thread, NULL, key_listener, NULL); // 你的原有业务逻辑 int x; puts("hello"); puts("hi"); f1(); scanf("%d", &x); f2(); printf("%d",x); // 程序正常结束时恢复终端属性 tcsetattr(STDIN_FILENO, TCSANOW, &old_tio); pthread_join(listener_thread, NULL); return 0; }
Windows 平台解决方案
Windows下需要修改控制台的输入模式,同样用后台线程监听按键:
#include <stdio.h> #include <stdlib.h> #include <windows.h> #include <process.h> unsigned __stdcall key_listener(void* arg) { HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); DWORD old_mode; // 获取原控制台模式 GetConsoleMode(hStdin, &old_mode); // 关闭行缓冲和回显,设置为立即读取按键 SetConsoleMode(hStdin, old_mode & ~ENABLE_LINE_INPUT & ~ENABLE_ECHO_INPUT); CHAR c; DWORD bytes_read; // 阻塞等待任意按键 ReadConsoleA(hStdin, &c, 1, &bytes_read, NULL); // 恢复控制台原有模式 SetConsoleMode(hStdin, old_mode); printf("\n程序已终止\n"); exit(0); return 0; } void f1() { // 你的f1函数逻辑 } void f2() { // 你的f2函数逻辑 } int main() { HANDLE listener_thread; // 创建后台监听线程 listener_thread = (HANDLE)_beginthreadex(NULL, 0, key_listener, NULL, 0, NULL); // 你的原有业务逻辑 int x; puts("hello"); puts("hi"); f1(); scanf("%d", &x); f2(); printf("%d",x); // 程序正常结束时恢复控制台模式 HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE); DWORD old_mode; GetConsoleMode(hStdin, &old_mode); SetConsoleMode(hStdin, old_mode | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT); WaitForSingleObject(listener_thread, INFINITE); CloseHandle(listener_thread); return 0; }
关键说明
- 两种方案都不会干扰你的原有业务代码,不用在
f1()、f2()里加任何输入扫描逻辑; - 退格键(ASCII码
0x08)会被正常捕捉,和其他按键效果一致; - 一定要记得恢复终端/控制台模式,不然程序结束后你的终端可能会出现输入不回显、不用回车就执行命令等异常情况。
内容的提问来源于stack exchange,提问作者marmofayezi
相关产品推荐
相关产品推荐

