How to avoid pressing Enter with getchar() for reading a single character only?

后端 未结 12 1620
长发绾君心
长发绾君心 2020-11-22 00:33

In the next code:

#include 

int main(void) {   
  int c;   
  while ((c=getchar())!= EOF)      
    putchar(c); 
  return 0;
}
相关标签:
12条回答
  • 2020-11-22 01:06

    On a linux system, you can modify terminal behaviour using the stty command. By default, the terminal will buffer all information until Enter is pressed, before even sending it to the C program.

    A quick, dirty, and not-particularly-portable example to change the behaviour from within the program itself:

    #include<stdio.h>
    #include<stdlib.h>
    
    int main(void){
      int c;
      /* use system call to make terminal send all keystrokes directly to stdin */
      system ("/bin/stty raw");
      while((c=getchar())!= '.') {
        /* type a period to break out of the loop, since CTRL-D won't work raw */
        putchar(c);
      }
      /* use system call to set terminal behaviour to more normal behaviour */
      system ("/bin/stty cooked");
      return 0;
    }
    

    Please note that this isn't really optimal, since it just sort of assumes that stty cooked is the behaviour you want when the program exits, rather than checking what the original terminal settings were. Also, since all special processing is skipped in raw mode, many key sequences (such as CTRL-C or CTRL-D) won't actually work as you expect them to without explicitly processing them in the program.

    You can man stty for more control over the terminal behaviour, depending exactly on what you want to achieve.

    0 讨论(0)
  • 2020-11-22 01:07

    yes you can do this on windows too, here's the code below, using the conio.h library

    #include <iostream> //basic input/output
    #include <conio.h>  //provides non standard getch() function
    using namespace std;
    
    int main()
    {  
      cout << "Password: ";  
      string pass;
      while(true)
      {
                 char ch = getch();    
    
                 if(ch=='\r'){  //when a carriage return is found [enter] key
                 cout << endl << "Your password is: " << pass <<endl; 
                 break;
                 }
    
                 pass+=ch;             
                 cout << "*";
                 }
      getch();
      return 0;
    }
    
    0 讨论(0)
  • 2020-11-22 01:08

    I like Lucas answer, but I would like to elaborate it a bit. There is a built-in function in termios.h named cfmakeraw() which man describes as:

    cfmakeraw() sets the terminal to something like the "raw" mode of the
    old Version 7 terminal driver: input is available character by
    character, echoing is disabled, and all special processing of
    terminal input and output characters is disabled. [...]
    

    This basically does the same as what Lucas suggested and more, you can see the exact flags it sets in the man pages: termios(3).

    Use case

    int c = 0;
    static struct termios oldTermios, newTermios;
    
    tcgetattr(STDIN_FILENO, &oldTermios);
    newTermios = oldTermios;
    
    cfmakeraw(&newTermios);
    
    tcsetattr(STDIN_FILENO, TCSANOW, &newTermios);
    c = getchar();
    tcsetattr(STDIN_FILENO, TCSANOW, &oldTermios);
    
    switch (c) {
        case 113: // q
            printf("\n\n");
            exit(0);
            break;
        case 105: // i
            printf("insert\n");
            break;
        default:
            break;
    
    0 讨论(0)
  • 2020-11-22 01:09

    getchar() is a standard function that on many platforms requires you to press ENTER to get the input, because the platform buffers input until that key is pressed. Many compilers/platforms support the non-standard getch() that does not care about ENTER (bypasses platform buffering, treats ENTER like just another key).

    0 讨论(0)
  • 2020-11-22 01:12

    Since you are working on a Unix derivative (Ubuntu), here is one way to do it - not recommended, but it will work (as long as you can type commands accurately):

    echo "stty -g $(stty -g)" > restore-sanity
    stty cbreak
    ./your_program
    

    Use interrupt to stop the program when you are bored with it.

    sh restore-sanity
    
    • The 'echo' line saves the current terminal settings as a shell script that will restore them.
    • The 'stty' line turns off most of the special processing (so Control-D has no effect, for example) and sends characters to the program as soon as they are available. It means you cannot edit your typing any more.
    • The 'sh' line reinstates your original terminal settings.

    You can economize if 'stty sane' restores your settings sufficiently accurately for your purposes. The format of '-g' is not portable across versions of 'stty' (so what is generated on Solaris 10 won't work on Linux, or vice versa), but the concept works everywhere. The 'stty sane' option is not universally available, AFAIK (but is on Linux).

    0 讨论(0)
  • 2020-11-22 01:14

    By default, the C library buffers the output until it sees a return. To print out the results immediately, use fflush:

    while((c=getchar())!= EOF)      
    {
        putchar(c);
        fflush(stdout);
    }
    
    0 讨论(0)
提交回复
热议问题