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

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


当前回答

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

其他回答

适用于我的windows:

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

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

CONIO.H

你需要的函数是:

int getch();
Prototype
    int _getch(void); 
Description
    _getch obtains a character  from stdin. Input is unbuffered, and this
    routine  will  return as  soon as  a character is  available  without 
    waiting for a carriage return. The character is not echoed to stdout.
    _getch bypasses the normal buffering done by getchar and getc. ungetc 
    cannot be used with _getch. 
Synonym
    Function: getch 


int kbhit();
Description
    Checks if a keyboard key has been pressed but not yet read. 
Return Value
    Returns a non-zero value if a key was pressed. Otherwise, returns 0.

libconio http://sourceforge.net/projects/libconio

or

conio.h的Linux c++实现 http://sourceforge.net/projects/linux-conioh

假设是Windows,看一下ReadConsoleInput函数。

以下是一个从Expert C Programming: Deep Secrets中提取的解决方案,它应该可以在SVr4上工作。它使用stty和ioctl。

#include <sys/filio.h>
int kbhit()
{
 int i;
 ioctl(0, FIONREAD, &i);
 return i; /* return a count of chars available to read */
}
main()
{
 int i = 0;
 intc='';
 system("stty raw -echo");
 printf("enter 'q' to quit \n");
 for (;c!='q';i++) {
    if (kbhit()) {
        c=getchar();
       printf("\n got %c, on iteration %d",c, i);
    }
}
 system("stty cooked echo");
}