You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在程序运行任意时刻捕获按键以立即终止程序?

嘿,我懂你要啥——就是想让程序不管跑到哪一步(哪怕是在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 12:44:05