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

Linux环境下C++实现键盘按键按下检测功能咨询

Linux 环境 C++ 非阻塞按键检测实现

Linux 终端默认采用行缓冲模式,只有按下回车后输入才会提交给程序,要实现循环内实时检测按键状态,需要修改终端属性为非规范模式,同时配置非阻塞 IO 避免循环卡住。

完整实现代码

#include <iostream>
#include <termios.h>
#include <unistd.h>
#include <fcntl.h>
#include <string>
#include <map>

// 按键名与ASCII码映射,可按需扩展
std::map<std::string, int> key_map = {
    {"space", 32},
    {"enter", 10},
    {"esc", 27},
    {"backspace", 127},
    {"tab", 9},
    {"a", 97}, {"b",98}, {"c",99}, {"d",100}, {"e",101}, {"f",102}, {"g",103},
    {"h",104}, {"i",105}, {"j",106}, {"k",107}, {"l",108}, {"m",109}, {"n",110},
    {"o",111}, {"p",112}, {"q",113}, {"r",114}, {"s",115}, {"t",116}, {"u",117},
    {"v",118}, {"w",119}, {"x",120}, {"y",121}, {"z",122},
    {"0",48}, {"1",49}, {"2",50}, {"3",51}, {"4",52}, {"5",53}, {"6",54}, {"7",55}, {"8",56}, {"9",57}
};

struct termios orig_termios;
// 程序退出时恢复终端默认属性
void reset_terminal() {
    tcsetattr(STDIN_FILENO, TCSANOW, &orig_termios);
}

bool IsKeyPressed(const std::string& key_name) {
    static bool init = false;
    if (!init) {
        // 保存原有终端属性
        tcgetattr(STDIN_FILENO, &orig_termios);
        atexit(reset_terminal);

        termios new_termios = orig_termios;
        // 关闭规范模式、回显,不需要按回车即可获取输入,输入不显示在终端
        new_termios.c_lflag &= ~(ICANON | ECHO);
        tcsetattr(STDIN_FILENO, TCSANOW, &new_termios);

        // 设置标准输入为非阻塞模式
        int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
        fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);

        init = true;
    }

    // 检查目标按键是否在映射表中
    if (key_map.find(key_name) == key_map.end()) {
        return false;
    }
    int target_key = key_map[key_name];

    int ch;
    bool pressed = false;
    // 读取缓冲区所有字符,判断是否有目标按键
    while ((ch = getchar()) != EOF) {
        if (ch == target_key) {
            pressed = true;
        }
    }
    return pressed;
}

int main(int argc, char** argv){
    std::cout << "Press the spacebar to exit loop" << std::endl;
    while (true){
        if (IsKeyPressed("space")){
            break;
        }
        // 这里可添加其他循环逻辑
        usleep(1000); // 避免空转占用过高CPU
    }
    std::cout << "Loop exited successfully" << std::endl;
    return 0;
}

注意事项

  • 本实现仅检测当前终端聚焦时的输入,不是全局键盘监听,仅适用于终端程序场景
  • 编译运行不需要依赖额外第三方库,直接使用g++ key_detect.cpp -o key_detect && ./key_detect即可运行
  • 如果程序异常退出导致终端输入不显示,在终端执行reset命令即可恢复默认终端配置

内容的提问来源于stack exchange,提问作者Samuel Oliveira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 11:36:04