Thread: Is there anything like _getch()?

  1. #1
    Registered User
    Join Date
    Sep 2018
    Posts
    217

    Is there anything like _getch()?

    I want to get input as soon as the user taps the key, so this would make sense if I'm making a console snake game for example (there is no delimiter like "\n" for other istream inputs, as soon as I tap the key the snake must turn).

    I don't know why _getch() isn't used but what's an alternative and why isn't _getch() itself good practice?


    Also notice the following:
    Code:
       
    char foo;
        while (true) {
            foo = _getch();
            cout << "taken\n";
        }
    Why do I see "taken" twice when I click a key? That's weird.. What is it reading the second time?


    When I print foo, I get the key I pressed and follow by one single whitespace.. why is there a whitespace? And how do I make it so that it doesn't read the whitespace..

    When we put foo to integer, we don't see 32 (ASCII for whitespace) being printed, but yet however when you typecast it then you get the whitespace.. Also the integer equivalent is in 4 digits..
    Last edited by Nwb; 11-02-2018 at 12:41 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    FAQ > How can I get input without having the user hit [Enter]? - Cprogramming.com
    You can do it, but you need to craft something specific to the OS you're using, or use a library (preferably one supporting multiple platforms) to do the grunt work for you.

    > I don't know why _getch() isn't used but what's an alternative and why isn't _getch() itself good practice?
    Because it's a non-portable relic from the past.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    Salem (I didn't want to over flood this forum with my threads so I'll post this here itself), What happens when a linux user or any other os other than windows tries to run a .exe which uses windows.h?

    Also _WIN32 can be used to determine whether he is using windows, but what cross-platform way can I use to prompt him that the program is not supported? And then exit after he closes the prompt?


    @Salem if my program has _getch(), other people of all os can still run the executable right? That's more convenient than trying to use os specific solutions because my compiler (VS 2017) has _getch() (conio.h)
    Last edited by Nwb; 11-02-2018 at 01:00 AM.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    What happens when a linux user or any other os other than windows tries to run a .exe which uses windows.h?
    A windows exe can only be run on windows.

    Also _WIN32 can be used to determine whether he is using windows, but what cross-platform way can I use to prompt him that the program is not supported?
    Again a Windows program will not run on any platform other than Windows.

    if my program has _getch(), other people of all os can still run the executable right?
    No, _getch() is an implementation detail of the Microsoft compiler and is limited to the Microsoft OS. By the way do you even realize that _getch() will only work with a console program under Windows? It will not even work with a Windows GUI program.

    That's more convenient than trying to use os specific solutions because my compiler (VS 2017) has _getch() (conio.h)
    But _getch() is a compiler specific solution, not an OS specific solution. No other compiler that I'm aware of support _getch(). Do you see that leading underscore? That is to inform you that you are using a compiler specific "solution" that will only work with that specific compiler. Even the old Borland Turbo-C (the originator of getch()) and gcc don't support _getch(), they support getch() as a non-standard implementation defined function for the DOS operating system. And by the way the conio.h header file also defines several other functions that may or may not be supported by any one compiler, remember that this header is a non-standard header and the various compiler manufacturers didn't support every feature that every other manufacturer supported and you can't even rely on the functions that are supported by "all" the compilers will work exactly the same with each compiler.

  5. #5
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    I feel so stupid of course only windows can run .exe lol. Thanks jim. I guess I'll still use _getch() for my console program otherwise I have to add other dependencies.

    But I don't understand the behavior _getch() is producing as mentioned in the first post..

  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613

    When I print foo, I get the key I pressed and follow by one single whitespace.. why is there a whitespace? And how do I make it so that it doesn't read the whitespace..

    When we put foo to integer, we don't see 32 (ASCII for whitespace) being printed, but yet however when you typecast it then you get the whitespace.. Also the integer equivalent is in 4 digits..
    Well, these questions are for mind readers. What did you press? What was the four digit number you cast into?

    Here's another fact about unbuffered input. Every single keypress matters. In a way, when you are using unbuffered input you usually want to capture a functional key (like control + something else for example) that you wouldn't get cleanly in buffered input routines like fgets. Since the input isn't buffered, if you still want conventions like backspace or delete to work, you have to code them yourself. So the input can be very weird and not the nice final product you usually get from buffered routines. After all, in a line buffered routine, the user can make as many mistakes as he likes, the input isn't final and sent until enter, signaling for a new line, is pressed.

  7. #7
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    Sorry let's go step by step.
    Consider:
    Code:
    char foo;
    
        while (true) {
    
            foo = _getch();
    
            cout << foo;
    
        }
    If I type "abcd" in above program, I get this on console:
    Code:
    a b c d
    Now consider this program below,
    Code:
    int foo;
    
        while (true) {
    
            foo = _getch();
    
            cout << foo;
    
        }
    typing "abcd" would give this output:
    Code:
    9709809901000
    I have no clue how or why that's happening or how _getch() even works..
    But I want to read only the character typed by the user, I'm not understand this behavior.
    Last edited by Nwb; 11-02-2018 at 10:22 AM. Reason: editted snippets, sorry they were wrong

  8. #8
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    This has nothing to do with getch.

    Code:
    #include <iostream>
    
    int main(void) {
        char a = 'a';
        int b = 'a';
        std::cout << a << b << std::endl;
        return 0;
    }
    will output a97. (The ASCII value of 'a' is 97....)

  9. #9
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    Quote Originally Posted by tabstop View Post
    This has nothing to do with getch.

    Code:
    #include <iostream>
    
    int main(void) {
        char a = 'a';
        int b = 'a';
        std::cout << a << b << std::endl;
        return 0;
    }
    will output a97. (The ASCII value of 'a' is 97....)
    Sorry the snippets were wrong, might make sense now..

    Tabstop, why do I get 970 and not 97 then? And why is there a whitespace when we take it as char instead of int? (whitespace's ASCII value is 37)

    Also the getch() is triggered twice when a key is pressed.
    Code:
    char foo;
        while (true) {
            foo = _getch();
            cout << "taken\n";
        }

    This might make a little more sense, sorry for being so brief:
    Code:
    char foo;
    
        while (true) {
    
            foo = _getch();
    
            cout << foo;
    
        }
    I get this output when I give abcd as input:
    Code:
    a|   getch was triggered
     |   getch was triggered
    b|   getch was triggered
     |   getch was triggered
    c|   getch was triggered
     |   getch was triggered
    Last edited by Nwb; 11-02-2018 at 10:25 AM.

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Well, it's a Microsoft function; let's see what they have to say about it:
    Quote Originally Posted by MSDN _getch page
    The _getch and _getwch functions read a single character from the console without echoing the character. None of these functions can be used to read CTRL+C. When reading a function key or an arrow key, each function must be called twice; the first call returns 0 or 0xE0, and the second call returns the actual key code.
    And then at the bottom is the link to the bug report:
    Quote Originally Posted by Microsoft Bugs at Github
    Either the implementation of _getch or the remarks are incorrect for VS2017 15.8.7.
    Testing has revealed that two calls must always be made to _getch.
    For function keys or arrow keys the behaviour is as noted, for other keys the first value is the actual key code, the second call returns 0.
    Additionally CTRL+C is actually returned as 03 00 despite the comment that it cannot be read.
    And further on they note that a later release of the SDK has (apparently) fixed it, so you may want to check your version against their version.

  11. #11
    Registered User
    Join Date
    Sep 2018
    Posts
    217
    That makes a lot of sense, thanks tabstop!. (char) 0 gives a whitespace? I didn't know that. I guess all I need to do is verify that getch did not return 0.

  12. #12
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    why do I get 970 and not 97 then? And why is there a whitespace when we take it as char instead of int? (whitespace's ASCII value is 37)
    You need to show how your printing the values, the code you've shown doesn't show how you're trying to output anything other that a single string.

    Also the getch() is triggered twice when a key is pressed.
    No, getch() is only triggered when you call getch(). Having said that, there are some keys that require you to call getch() multiple times to actually decode the key.

  13. #13
    Registered User
    Join Date
    Nov 2018
    Location
    Amberg in upper palatinate, Bavaria
    Posts
    66
    Hi Nwb!

    What is, when you try to use your own "getch() like this:
    Code:
    #include <stdio.h>
    #include <termios.h>
    #include <unistd.h>
    
    /// reads from keypress, doesn't echo
    int getch(){
        struct termios oldt, newt;
        int ch;
        tcgetattr( STDIN_FILENO, &oldt );
        newt = oldt;
        newt.c_lflag &= ~( ICANON | ECHO );
        tcsetattr( STDIN_FILENO, TCSANOW, &newt );
        ch = getchar();
        tcsetattr( STDIN_FILENO, TCSANOW, &oldt );
        return ch;
    }
    
    void clpuf(void)
     {
     while (getc(stdin) != '\n')
        ;
     }
    
       /// reads from keypress, echoes
    int getche(void)
        {
        struct termios oldattr, newattr;
        int ch;
        tcgetattr( STDIN_FILENO, &oldattr );
        newattr = oldattr;
        newattr.c_lflag &= ~( ICANON );
        tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
        ch = getchar();
        tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
        return ch;
        }
     
    long kbhit(void)
    {
    struct timeval tv;
    fd_set read_fd;
    
    tv.tv_sec=0;
    tv.tv_usec=0;
    FD_ZERO(&read_fd);
    FD_SET(0,&read_fd);
    
    if(select(1, &read_fd, NULL, NULL, &tv) == -1)
    return 0;
    
    if(FD_ISSET(0,&read_fd))
     return 1;
    
    return 0;
    }
    I am working with SUSE Linux tumbleweed.
    Don't know if it is working by you or not.
    Try and see.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. _getch()Help
    By stroggos in forum C Programming
    Replies: 2
    Last Post: 05-21-2011, 04:02 AM
  2. Converting _getch() inputted numbers
    By bengreenwood in forum C++ Programming
    Replies: 9
    Last Post: 07-16-2008, 10:46 PM
  3. _getch() and doing a carriage return
    By Leeman_s in forum C++ Programming
    Replies: 7
    Last Post: 10-01-2001, 02:19 PM

Tags for this Thread