有没有一种方法可以在不按回车键的情况下获得用户输入

Is there a way to get user input without pressing the enter key?

本文关键字:回车 情况下 输入 用户 一种 方法 有没有      更新时间:2023-10-16

我正在编写一个控制台游戏(pac-man),我想知道如果用户不按回车键,我该如何获得用户输入。我在互联网上浏览了一下,发现了一些关于_getch()的东西,但它显然不再是最新的,也没有已知的头文件来声明它,除非有人自己构建它,我不能这样做,因为我对C++还很陌生。那么,我该如何构建一个能够做到这一点的代码呢?感谢

这对我有效(我在linux上):

#include <stdio.h>
#include <unistd.h>
#include <termios.h>
int main()
{
    struct termios old_tio, new_tio;
    unsigned char c;
    /* get the terminal settings for stdin */
    tcgetattr(STDIN_FILENO,&old_tio);
    /* we want to keep the old setting to restore them a the end */
    new_tio=old_tio;
    /* disable canonical mode (buffered i/o) and local echo */
    new_tio.c_lflag &=(~ICANON & ~ECHO);
    /* set the new settings immediately */
    tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);
    do {
         c=getchar();
         printf("%d ",c);
    } while(c!='q');
    /* restore the former settings */
    tcsetattr(STDIN_FILENO,TCSANOW,&old_tio);
    return 0;
}

它使控制台没有缓冲区。

参考:http://shtrom.ssji.net/skb/getc.html

您可以使用conio.h库和函数_getch()以实时方式获取输入,还可以为多个输入设置循环。

#include<conio.h>
#include<iostream>
using namespace std;
int main()
{
    char n = 'a'; //Just to initialize it. 
    while(n != 'e') // Will exit if you press e.
    {
        n = _getch();
    }
}

允许本地文本编辑的Windows解决方案

#include <Windows.h>
#include <conio.h>
enum key_code
{
    KEY_QUIT = 3,
    KEY_BACKSPACE = 8,
    KEY_TAB = 9,
    KEY_RETURN = 13,
    KEY_ESCAPE = 27,
    KEY_SPACE = ' ',
    KEY_EXCLAMATION_POINT = '!',
    KEY_QUOTATION = '"',
    KEY_HASHTAG = '#',
    KEY_DOLLAR = '$',
    KEY_MODULUS = '%',
    KEY_AMPERSAND = '&',
    KEY_APOSTROPHE = ''',
    KEY_LEFT_PAREN = '(',
    KEY_RIGHT_PAREN = ')',
    KEY_ASTERICK = '*',
    KEY_PLUS = '+',
    KEY_COMMA = ',',
    KEY_MINUS = '-',
    KEY_PERIOD = '.',
    KEY_FORWARD_SLASH = '/',
    KEY_0 = '0',
    KEY_1 = '1',
    KEY_2 = '2',
    KEY_3 = '3',
    KEY_4 = '4',
    KEY_5 = '5',
    KEY_6 = '6',
    KEY_7 = '7',
    KEY_8 = '8',
    KEY_9 = '9',
    KEY_COLON = ':',
    KEY_SEMICOLON = ';',
    KEY_LESS_THAN = '<',
    KEY_EQUALS = '=',
    KEY_GREATER_THAN = '>',
    KEY_QUESTION = '?',
    KEY_AT = '@',
    KEY_A = 'A',
    KEY_B = 'B',
    KEY_C = 'C',
    KEY_D = 'D',
    KEY_E = 'E',
    KEY_F = 'F',
    KEY_G = 'G',
    KEY_H = 'H',
    KEY_I = 'I',
    KEY_J = 'J',
    KEY_K = 'K',
    KEY_L = 'L',
    KEY_M = 'M',
    KEY_N = 'N',
    KEY_O = 'O',
    KEY_P = 'P',
    KEY_Q = 'Q',
    KEY_R = 'R',
    KEY_S = 'S',
    KEY_T = 'T',
    KEY_U = 'U',
    KEY_V = 'V',
    KEY_W = 'W',
    KEY_X = 'X',
    KEY_Y = 'Y',
    KEY_Z = 'Z',
    KEY_OPENING_SQR_BRACE = '[',
    KEY_BACKSLASH = '',
    KEY_CLOSING_SQR_BRACE = ']',
    KEY_EXP = '^',
    KEY_UNDERSCORE = '_',
    KEY_BACKTICK = '`',
    KEY_a = 'a',
    KEY_b = 'b',
    KEY_c = 'c',
    KEY_d = 'd',
    KEY_e = 'e',
    KEY_f = 'f',
    KEY_g = 'g',
    KEY_h = 'h',
    KEY_i = 'i',
    KEY_j = 'j',
    KEY_k = 'k',
    KEY_l = 'l',
    KEY_m = 'm',
    KEY_n = 'n',
    KEY_o = 'o',
    KEY_p = 'p',
    KEY_q = 'q',
    KEY_r = 'r',
    KEY_s = 's',
    KEY_t = 't',
    KEY_u = 'u',
    KEY_v = 'v',
    KEY_w = 'w',
    KEY_x = 'x',
    KEY_y = 'y',
    KEY_z = 'z',
    KEY_OPENING_CURLY_BRACE = '{',
    KEY_LINE = '|',
    KEY_CLOSING_CURLY_BRACE = '}',
    KEY_TILDA = '~',
    KEY_UP_ARROW,
    KEY_DOWN_ARROW,
    KEY_LEFT_ARROW,
    KEY_RIGHT_ARROW,
    KEY_DELETE,
    KEY_END,
    KEY_HOME,
};
struct handle
{
    HANDLE console;
    DWORD old_mode;
    handle() : console{GetStdHandle(STD_OUTPUT_HANDLE)}
    {
        GetConsoleMode(console, &old_mode);
        SetConsoleMode(console, old_mode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
    }
    handle(const handle&) = delete;
    handle& operator=(const handle&) = delete;
    COORD get_cursor_pos() const
    {
        CONSOLE_SCREEN_BUFFER_INFO screen{};
        GetConsoleScreenBufferInfo(console, &screen);
        return screen.dwCursorPosition;
    }
    void set_pos(COORD pos) const
    {
        SetConsoleCursorPosition(console, pos);
    }
    void write(const WCHAR* sequence) const
    {
        DWORD written = 0;
        WriteConsoleW(console, sequence, (DWORD)wcslen(sequence), &written, nullptr);
    }
    void clear_screen() const
    {
        write(L"x1b[2J");
        set_pos({0, 0});
    }
    ~handle()
    {
        SetConsoleMode(console, old_mode);
    }
};
key_code input()
{
    int c = _getch();
    // if it is a special key and there is another key to be handled
    if (c == 224 && _kbhit())
    {
        c = _getch();
        switch (c)
        {
        case 75:
            return KEY_LEFT_ARROW;
        case 77:
            return KEY_RIGHT_ARROW;
        case 72:
            return KEY_UP_ARROW;
        case 80:
            return KEY_DOWN_ARROW;
        case 83:
            return KEY_DELETE;
        case 79:
            return KEY_END;
        case 71:
            return KEY_HOME;
        }
    }
    return static_cast<key_code>(c);
}
struct handler
{
    std::wstring text;
    handle console;
    // holds initial cursor position
    COORD cursor_init;
    // holds position that the console cursor is for editing
    size_t cursor;
    bool finished;
    handler() : text{}, console{}, cursor{}, finished{true}
    {
    }
    void run()
    {
        if (finished)
        {
            text.clear();
            cursor_init = console.get_cursor_pos();
            cursor = 0;
            finished = false;
        }
        key_code code;
        // show cursor
        console.write(L"x1b[?25h");
        console.set_pos({static_cast<short>(cursor_init.X + cursor), cursor_init.Y});
        code = input();
        switch (code)
        {
        case KEY_BACKSPACE:
            if (cursor > 0)
            {
                text.erase(text.begin() + cursor - 1);
                --cursor;
            }
            break;
        case KEY_DELETE:
            if (cursor < text.size())
                text.erase(text.begin() + cursor);
            break;
        case KEY_LEFT_ARROW:
            if (cursor > 0)
                --cursor;
            break;
        case KEY_RIGHT_ARROW:
            if (cursor < text.size())
                ++cursor;
            break;
        case KEY_HOME:
            cursor = 0;
            break;
        case KEY_END:
            cursor = text.size();
            break;
        case KEY_RETURN:
        case KEY_QUIT:
            finished = true;
        case KEY_UP_ARROW:
        case KEY_DOWN_ARROW:
        case KEY_ESCAPE:
            return;
        default:
            text.insert(text.begin() + cursor, static_cast<char>(code));
            ++cursor;
        }
        // move cursor to beginning of line
        console.set_pos(cursor_init);
        // clear line
        console.write(L"x1b[0K");
        console.write(text.data());
        console.set_pos({static_cast<short>(cursor_init.X + cursor), cursor_init.Y});
        // hide cursor
        console.write(L"x1b[?25l");
    }
};
// get_input returns true if input is finished (newline is entered)
bool get_input(std::wstring& str)
{
    static handler h;
    h.run();
    str = h.text;
    return h.finished;
}