admin管理员组

文章数量:1180493

I'm on macOS. How can I read input without waiting for a newline? I want to make an ASCII-based RPG with standard WASD controls, so I need to read multiple characters simultaneously to account for diagonal movement. Also, in my experience using scanf(), typing a character that doesn't match the provided format specifier causes it to bug out. It would be nice to have a solution that avoids this. Thanks!

I'm on macOS. How can I read input without waiting for a newline? I want to make an ASCII-based RPG with standard WASD controls, so I need to read multiple characters simultaneously to account for diagonal movement. Also, in my experience using scanf(), typing a character that doesn't match the provided format specifier causes it to bug out. It would be nice to have a solution that avoids this. Thanks!

Share Improve this question asked 2 days ago Kai B.Kai B. 252 bronze badges 7
  • 1 Non-canonical input mode of terminal is an answer. – Moses Commented yesterday
  • @Moses: As far as I can tell, non-canonical input mode is not the answer, because OP is not only asking for the ability to detect which keys were pressed, but also for how long and whether they are being pressed at the same time. The standard input stream does not provide both keypress and release information, not even in non-canonical mode. – Andreas Wenzel Commented yesterday
  • @Barmar: I am reopening the question because as far as I can tell, your proposed duplicate does not answer OP's question. OP is asking for both keypress and release information in order to detect diagonal movement, but as you stated yourself in a comment to another question, ncurses does not provide this information. – Andreas Wenzel Commented yesterday
  • 2 The first thing to recognize is that standard C has no built-in features addressing this question. You're looking for a platform-specific solution. – John Bollinger Commented yesterday
  • 1 If you need key press and release, this generally isn't even available from OS-specific terminal APIs. For this, you usually need to use either a window system or low-level device APIs. – Barmar Commented yesterday
 |  Show 2 more comments

1 Answer 1

Reset to default 0

not 100% sure of what you are after, below, a trivial example to capture each char as entered plus catch a couple of signals .... if this is not what you are after (or could form the basis of ... ), please elaborate, also - share what you have tried - regardless of any shortcomings !

//
//use(d) https://www.man7.org/linux/man-pages/man3/termios.3.html as reference
//

#include <termios.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

struct termios currentSettings;

void resetSTDIN(struct termios *currentSettings) {
    tcsetattr(STDIN_FILENO, TCSAFLUSH, currentSettings);  // reset to original settings
}

void setSTDIN(struct termios *currentSettings) {
    struct termios updatedSettings;

    tcgetattr(STDIN_FILENO, currentSettings);  // get current settings

    updatedSettings = *currentSettings;        // use those as basis for new settings

    updatedSettings.c_lflag &= ~ICANON;   // unset 'normal' aka canonical mode, add '|ECHO' if you don't want to see input
    updatedSettings.c_cc[VTIME] = 0;      // VTIME Timeout in deciseconds for noncanonical read (TIME) 0 == no timeout
    updatedSettings.c_cc[VMIN] = 1;       // VMIN  Minimum number of characters for noncanonical read (MIN).

    tcsetattr(STDIN_FILENO, TCSAFLUSH, &updatedSettings);
}

void catchSignals(int sig) {
    resetSTDIN(&currentSettings);
    exit(1);
}

int main() {

    setSTDIN(&currentSettings);

    signal(SIGINT|SIGQUIT, catchSignals);  // trap ^C, ^\ amend as reqd

    printf("[q|Q|^C|^D]' to exit):\n");

    char c;
    const char ctrlD=4;
    while ( read(STDIN_FILENO, &c, 1) == 1 ) {
        if ( c == ctrlD || c == 'q' || c == 'Q' )
        break;

        //printf("%c", c); // if ECHO masked and you want to see the output ...
    }

    resetSTDIN(&currentSettings);
    return 0;
}

本文标签: macosHow can I read input from terminal in C without waiting for a newlineStack Overflow