Mac下实现按下ESC键无需回车立即触发C++程序输出的方法
解决Mac下C++程序按下ESC立即触发统计的问题
你当前的程序用cin.getline(s, 500, 27)读取输入,以ESC(ASCII码27)作为终止符,但Mac终端默认处于行缓冲(规范)模式——所有输入会先暂存到缓冲区,直到按下回车才会传递给程序,因此即使按了ESC,也需要回车才能触发getline返回。
要实现按下ESC立即响应,需要修改终端输入模式,关闭行缓冲,让字符输入后直接传递给程序。下面是修改后的完整代码:
#include <iostream> #include <cctype> #include <termios.h> #include <unistd.h> using namespace std; int main() { cout << "Enter your paragraph\nTo finish press 'ESC'\n\n"; // 保存终端原属性,用于后续恢复 termios original_attr; tcgetattr(STDIN_FILENO, &original_attr); // 设置终端为无缓冲、无回显模式 termios new_attr = original_attr; new_attr.c_lflag &= ~(ICANON | ECHO); // 关闭规范模式和回显 new_attr.c_cc[VMIN] = 1; // 至少读取1个字符就返回 new_attr.c_cc[VTIME] = 0; // 无超时等待 tcsetattr(STDIN_FILENO, TCSANOW, &new_attr); long long vowels = 0, characters = 0; char c; // 逐个读取字符,直到遇到ESC while (read(STDIN_FILENO, &c, 1) == 1) { if (c == 27) { // 检测到ESC键,退出循环 break; } // 统计有效字符 if (c >= 32 && c <= 126) { characters++; char lower_c = tolower(c); if (lower_c == 'a' || lower_c == 'e' || lower_c == 'i' || lower_c == 'o' || lower_c == 'u' || lower_c == 'y') { vowels++; } } // 回显输入字符(不需要的话可注释) cout << c; cout.flush(); } // 恢复终端原属性,避免影响后续终端操作 tcsetattr(STDIN_FILENO, TCSANOW, &original_attr); // 输出统计结果 cout << "\n\nThe amount of characters: " << characters << "\nThe amount of vowels: " << vowels << '\n'; return 0; }
关键说明:
- 终端模式修改:通过
tcgetattr和tcsetattr操作终端属性,关闭ICANON标志后,终端不再使用行缓冲,输入的每个字符都会立即被程序读取。 - 字符读取:改用
read系统调用逐个读取字符,相比cin更直接控制输入流。 - 终端恢复:程序结束前必须恢复终端原属性,否则终端会保持无缓冲无回显的异常状态。
- 回显控制:如果不需要输入时的字符回显,可以删除
cout << c; cout.flush();这两行。
编译运行时,直接使用g++编译即可:
g++ your_program.cpp -o char_counter ./char_counter
内容的提问来源于stack exchange,提问作者Sadaroni
相关产品推荐
相关产品推荐

