我从来都不记得我是怎么做到的,因为它很少出现在我身上。但是在C或c++中,从标准输入中读取字符而不等待换行符(按enter)的最佳方法是什么?

理想情况下,它也不会将输入字符回显到屏幕上。我只是想在不影响控制台屏幕的情况下捕捉击键。


当前回答

You can do it portably using SDL (the Simple DirectMedia Library), though I suspect you may not like its behavior. When I tried it, I had to have SDL create a new video window (even though I didn't need it for my program) and have this window "grab" almost all keyboard and mouse input (which was okay for my usage but could be annoying or unworkable in other situations). I suspect it's overkill and not worth it unless complete portability is a must--otherwise try one of the other suggested solutions.

顺便说一下,这将分别提供按键和释放事件,如果你喜欢的话。

其他回答

#include <conio.h>

if (kbhit() != 0) {
    cout << getch() << endl;
}

它使用kbhit()来检查键盘是否被按下,并使用getch()来获取被按下的字符。

如果你在windows上,你可以使用PeekConsoleInput来检测是否有任何输入,

HANDLE handle = GetStdHandle(STD_INPUT_HANDLE);
DWORD events;
INPUT_RECORD buffer;
PeekConsoleInput( handle, &buffer, 1, &events );

然后使用ReadConsoleInput“消费”输入字符..

PeekConsoleInput(handle, &buffer, 1, &events);
if(events > 0)
{
    ReadConsoleInput(handle, &buffer, 1, &events);  
    return buffer.Event.KeyEvent.wVirtualKeyCode;
}
else return 0

老实说,这是从一些旧的代码,我有,所以你必须拨弄它一点。

最酷的是它读取输入时没有任何提示,所以字符根本不会显示出来。

我也遇到过同样的问题。这里是一个小的解决方案为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

适用于我的windows:

#include <conio.h>
char c = _getch();

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;
}