我从来都不记得我是怎么做到的,因为它很少出现在我身上。但是在C或c++中,从标准输入中读取字符而不等待换行符(按enter)的最佳方法是什么?
理想情况下,它也不会将输入字符回显到屏幕上。我只是想在不影响控制台屏幕的情况下捕捉击键。
我从来都不记得我是怎么做到的,因为它很少出现在我身上。但是在C或c++中,从标准输入中读取字符而不等待换行符(按enter)的最佳方法是什么?
理想情况下,它也不会将输入字符回显到屏幕上。我只是想在不影响控制台屏幕的情况下捕捉击键。
当前回答
我在另一个论坛上发现了这个,当时我想解决同样的问题。根据我的发现,我做了一些修改。效果很好。我运行的是OS X,所以如果你运行的是微软,你需要找到正确的system()命令来切换到raw和cooked模式。
#include <iostream>
#include <stdio.h>
using namespace std;
int main() {
// Output prompt
cout << "Press any key to continue..." << endl;
// Set terminal to raw mode
system("stty raw");
// Wait for single character
char input = getchar();
// Echo input:
cout << "--" << input << "--";
// Reset terminal to normal "cooked" mode
system("stty cooked");
// And we're out of here
return 0;
}
其他回答
最接近可移植的方法是使用ncurses库将终端置于“cbreak模式”。API是巨大的;你最想要的是
Initscr和endwin 黄昏时分和黄昏时分 getch
好运!
这在纯c++中以可移植的方式是不可能的,因为它太依赖于可能与stdin连接的终端(它们通常是行缓冲的)。不过,你可以使用一个库来实现:
conio available with Windows compilers. Use the _getch() function to give you a character without waiting for the Enter key. I'm not a frequent Windows developer, but I've seen my classmates just include <conio.h> and use it. See conio.h at Wikipedia. It lists getch(), which is declared deprecated in Visual C++. curses available for Linux. Compatible curses implementations are available for Windows too. It has also a getch() function. (try man getch to view its manpage). See Curses at Wikipedia.
如果你的目标是跨平台兼容性,我建议你使用curses。也就是说,我相信有一些函数可以用来关闭行缓冲(我相信这被称为“原始模式”,而不是“熟模式”-看看man stty)。如果我没记错的话,诅咒可以方便地帮你解决这个问题。
我也遇到过同样的问题。这里是一个小的解决方案为windows控制台使用cygwing++与if(GetKeyState(keycode) & bitANDcompare){};
#include <windows.h>
#include <fstream>
#include <iostream>
using namespace std;
void clear() {
COORD topLeft = { 0, 0 };
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO screen;
DWORD written;
GetConsoleScreenBufferInfo(console, &screen);
FillConsoleOutputCharacterA(
console, ' ', screen.dwSize.X * screen.dwSize.Y, topLeft, &written
);
FillConsoleOutputAttribute(
console, FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE,
screen.dwSize.X * screen.dwSize.Y, topLeft, &written
);
SetConsoleCursorPosition(console, topLeft);
}
class Keyclick{
private:
int key;
char id;
public:
bool keydown = false;
Keyclick(int key1, char id1){
key=key1;
id=id1;
};
void watch(){
if(keydown==false){
if(GetKeyState(key) & 0x8000 ){
cout << id;
cout << " pressed.\r\n";
keydown = true;
}
}
if(keydown == true){
if(!(GetKeyState(key) & 0x8000)) {
cout << "released!!!!!!!!!!\r\n";
keydown = false;
clear();
}
}
};
};
int main()
{
bool primaryloop =true;
Keyclick keysp(VK_SPACE,'S');
Keyclick keyw(0x57,'w');
Keyclick keya(0x41,'a');
Keyclick keys(0x53,'s');
Keyclick keyd(0x44,'d');
Keyclick keyesc(VK_ESCAPE,'E');
while(primaryloop){
keysp.watch();
keyw.watch();
keya.watch();
keys.watch();
keyd.watch();
keyesc.watch();
if(keyesc.keydown){
primaryloop=false;
};
}
return 0;
}
https://github.com/wark77/windows_console_keypoller/blob/main/getkeystate_SOLUTION01.cpp
Ncurses提供了一个很好的方法来做到这一点! 这也是我的第一篇文章(我记得),所以欢迎任何评论。我会欣赏有用的,但都是受欢迎的!
编译: g++ -std=c++11 -pthread -lncurses .cpp -o
#include <iostream>
#include <ncurses.h>
#include <future>
char get_keyboard_input();
int main(int argc, char *argv[])
{
initscr();
raw();
noecho();
keypad(stdscr,true);
auto f = std::async(std::launch::async, get_keyboard_input);
while (f.wait_for(std::chrono::milliseconds(20)) != std::future_status::ready)
{
// do some work
}
endwin();
std::cout << "returned: " << f.get() << std::endl;
return 0;
}
char get_keyboard_input()
{
char input = '0';
while(input != 'q')
{
input = getch();
}
return input;
}
我使用kbhit()来查看是否存在一个字符,然后使用getchar()来读取数据。 在windows上,您可以使用“conio.h”。在linux上,您必须实现自己的kbhit()。
参见下面的代码:
// kbhit
#include <stdio.h>
#include <sys/ioctl.h> // For FIONREAD
#include <termios.h>
#include <stdbool.h>
int kbhit(void) {
static bool initflag = false;
static const int STDIN = 0;
if (!initflag) {
// Use termios to turn off line buffering
struct termios term;
tcgetattr(STDIN, &term);
term.c_lflag &= ~ICANON;
tcsetattr(STDIN, TCSANOW, &term);
setbuf(stdin, NULL);
initflag = true;
}
int nbbytes;
ioctl(STDIN, FIONREAD, &nbbytes); // 0 is STDIN
return nbbytes;
}
// main
#include <unistd.h>
int main(int argc, char** argv) {
char c;
//setbuf(stdout, NULL); // Optional: No buffering.
//setbuf(stdin, NULL); // Optional: No buffering.
printf("Press key");
while (!kbhit()) {
printf(".");
fflush(stdout);
sleep(1);
}
c = getchar();
printf("\nChar received:%c\n", c);
printf("Done.\n");
return 0;
}