1

我知道如何使用事件来测试何时按下某个键,但在 CI 中从未发现如何做到这一点。

我真正想要的是一个“KeyListener”,它监听、Up和箭头键。我需要它在Linux中工作,所以没有 Windows 库。而且,如果可能的话,不使用 3rd 方库对我来说是最好的选择。DownLeftRight

我想要的伪代码:

int main() {
 
    // key listener {
    // if(key == up) { // do something }
    // if(key == down) { // do something }
    // if(key == left) { // do something }
    // if(key == right) { // do something }
    // }
}
4

2 回答 2

5

也可以使用 SDL 来读取键盘。

  SDL_Event event;
  .
  .
  /* Poll for events. SDL_PollEvent() returns 0 when there are no  */
  /* more events on the event queue, our while loop will exit when */
  /* that occurs.                                                  */
  while( SDL_PollEvent( &event ) ){
    /* We are only worried about SDL_KEYDOWN and SDL_KEYUP events */
    switch( event.type ){
      case SDL_KEYDOWN:
        printf( "Key press detected\n" );

        if (event.key.keysym.sym==SDLK_UP) 
            printf( "It was the UP key\n" );

        break;
      case SDL_KEYUP:
        printf( "Key release detected\n" );
        break;

      default:
        break;
    }
  }
  .
  .

来源:http ://www.libsdl.org/docs/html/guideinputkeyboard.html

于 2012-10-03T13:19:12.203 回答
0

这是基于我在此处的其他答案的技巧:Capture characters from standard input without waiting for enter to be press。我使用 C 或 C++ 中的 bash 系统调用来读取和解析箭头按键。箭头键按 3 个字符输入,所以我一次解析 3 个字符并找出它是哪个箭头键。

无需按 Enter。按下箭头键后会立即检测到它们。

read_arrow_keypresses_system_call.c:

#include <stdbool.h> // For `true` (`1`) and `false` (`0`) macros in C
#include <stdint.h>  // For `uint8_t`, `int8_t`, etc.
#include <stdio.h>   // For `printf()`
#include <stdlib.h>

#define BUFSIZE 32

typedef enum arrowKey_e
{
    ARROWKEY_UNKNOWN = 0,
    ARROWKEY_UP,
    ARROWKEY_DOWN,
    ARROWKEY_LEFT,
    ARROWKEY_RIGHT,
} arrowKey_t;

// Modeled after my answer here: https://stackoverflow.com/a/54728664/4561887
const char* arrowKeyGetName(arrowKey_t arrowKey)
{
    const char* arrowKeyName = "TBD";

    switch (arrowKey)
    {
        case ARROWKEY_UNKNOWN:
            arrowKeyName = "ARROWKEY_UNKNOWN";
            break;
        case ARROWKEY_UP:
            arrowKeyName = "ARROWKEY_UP";
            break;
        case ARROWKEY_DOWN:
            arrowKeyName = "ARROWKEY_DOWN";
            break;
        case ARROWKEY_LEFT:
            arrowKeyName = "ARROWKEY_LEFT";
            break;
        case ARROWKEY_RIGHT:
            arrowKeyName = "ARROWKEY_RIGHT";
            break;
    }

    return arrowKeyName;
}

// Read a keyboard key press and return the character pressed, or a negative
// number in the event of an error.
// NB: for help reading output from system calls, see here:
//  1. https://stackoverflow.com/a/28971647/4561887
//  2. https://stackoverflow.com/a/18297075/4561887
arrowKey_t readArrowKeyPress()
{
    arrowKey_t arrowKeyPressed = ARROWKEY_UNKNOWN;

    // This bash cmd is from my answer here:
    // https://stackoverflow.com/a/70979348/4561887
    // `-n3` here means to read 3 chars at once, since an arrow key press
    // comes in as 3 chars.
    // The `-t .01` forces a timeout of that many seconds, which means the loop
    // interval will be this fast.
    const char* cmd = "bash -c 'read -s -t .1 -n3 c && printf \"%s\" \"$c\"'";
    FILE *fp = popen(cmd, "r");
    if (fp == NULL)
    {
        printf("\nError opening pipe!\n");
        return arrowKeyPressed;
    }

    char buf[BUFSIZE] = {0};
    char* retval1 = fgets(buf, BUFSIZE, fp);
    if (retval1 == NULL)
    {
        // printf("\nFailed to read cmd response.\n");
        // Timeout occured; just exit.
        return arrowKeyPressed;
    }

    // See meaning of this return value here:
    // https://stackoverflow.com/questions/43116/how-can-i-run-an-external-program-from-c-and-parse-its-output/28971647#comment60311936_28971647
    int retval2 = pclose(fp);
    if (retval2 == -1)
    {
        printf("\nError obtaining the cmd's exit status code.\n");
        return arrowKeyPressed;
    }
    else if (retval2 != 0)
    {
        printf("\nCommand exited with exit status code %i.\n", retval2);
        return arrowKeyPressed;
    }

    // Map the readings to arrow keys
    if ((buf[0] == 27) && (buf[1] == 91) && (buf[2] == 65))
    {
        arrowKeyPressed = ARROWKEY_UP;
    }
    else if ((buf[0] == 27) && (buf[1] == 91) && (buf[2] == 66))
    {
        arrowKeyPressed = ARROWKEY_DOWN;
    }
    else if ((buf[0] == 27) && (buf[1] == 91) && (buf[2] == 67))
    {
        arrowKeyPressed = ARROWKEY_RIGHT;
    }
    else if ((buf[0] == 27) && (buf[1] == 91) && (buf[2] == 68))
    {
        arrowKeyPressed = ARROWKEY_LEFT;
    }

    return arrowKeyPressed;
}

// int main(int argc, char *argv[])  // alternative prototype
int main()
{
    printf("Press any arrow key. Press Ctrl + C to quit.\n");
    fflush(stdout);

    while (true)
    {
        arrowKey_t arrowKeyPressed = readArrowKeyPress();
        if (arrowKeyPressed == ARROWKEY_UNKNOWN)
        {
            continue;
        }
        printf("Key pressed = %s\n", arrowKeyGetName(arrowKeyPressed));
    }

    return 0;
}

示例构建和运行输出:

eRCaGuy_hello_world/c$ gcc -Wall -Wextra -Werror -O3 -std=gnu17 read_arrow_keypresses_system_call.c -o bin/a && bin/a
Press any arrow key. Press Ctrl + C to quit.
Key pressed = ARROWKEY_DOWN
Key pressed = ARROWKEY_UP
Key pressed = ARROWKEY_LEFT
Key pressed = ARROWKEY_RIGHT
Key pressed = ARROWKEY_UP
Key pressed = ARROWKEY_DOWN
Key pressed = ARROWKEY_LEFT
Key pressed = ARROWKEY_RIGHT
Key pressed = ARROWKEY_UP
Key pressed = ARROWKEY_DOWN
Key pressed = ARROWKEY_LEFT
Key pressed = ARROWKEY_RIGHT
于 2022-02-04T00:16:42.170 回答