Thread: !_kbhit ???

  1. #1
    Registered User mr_raging_money's Avatar
    Join Date
    Mar 2012
    Posts
    18

    !_kbhit ???

    I am still trying out non-blocking keyboard input, and it kind of works. What ends up happening is none of the input I give through the keyboard is picked up.
    Code:
    while(1==1){
    if(!_kbhit())
    goto noinput;
    
    //this is what i want to happen if there is no input
    ch=getch();
    
    noinput:
    int airandom=rand()%17;
    //more stuff that happens based on this random number and user input
    Can someone point me in the right direction and tell me what I am missing, because im fairly sure I have to do something else to make ch=getch(); when I have !_kbhit() before it. I read something about drawing the character from the buffer, how would I do that and make that character equal to a variable?

  2. #2
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Don't use goto if there's no reason to (such as breaking out of a double-loop). Don't use 1==1 for a condition when a simple 1 will do.

    Otherwise it's hard to understand what your problem is. Using _kbhit is easy. Try this:
    Code:
    #include <stdio.h>
    #include <conio.h>
    
    int main(void) {
        int ch = 'a';
        int cnt = 0;
    
        while (ch != 'q')
        {
            if (_kbhit())
            {
                ch = _getch();
                printf("[%c] %d\n", ch, cnt);
            }
    
            /* This is done whether or not a key is pressed */
            cnt++;
        }
    
        return 0;
    }
    Note in particular that some keys (such as the arrow keys) actually return two characters. So to check for the arrow keys:
    Code:
    #include <stdio.h>
    #include <conio.h>
    
    int main(void) {
        int ch = 'a';
        int cnt = 0;
    
        while (ch != 'q')
        {
            if (_kbhit())
            {
                ch = _getch();
                if (ch == 224) /* indicates double-character code */
                {
                    switch (_getch()) /* get second character */
                    {
                    case 72:
                        printf("UP\n");
                        break;
                    case 75:
                        printf("LEFT\n");
                        break;
                    case 77:
                        printf("RIGHT\n");
                        break;
                    case 80:
                        printf("DOWN\n");
                        break;
                    }
                }
                else
                    printf("[%c:%d] %d\n", ch, ch, cnt);
            }
    
            /* This is done whether or not a key is pressed */
            cnt++;
        }
    
        return 0;
    }
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  3. #3
    Registered User mr_raging_money's Avatar
    Join Date
    Mar 2012
    Posts
    18
    this is what i have now
    Code:
    int main(void){
    while(ch!='q'){   //thanks for this quit program idea
    if(_kbhit()){
    
    ch=_getch(); //does this get the value for _kbhit() ?
    printf("DEBUG");
    
    //things that go off of the getch() are down here
    
    }
    //more stuff that doesn't have to do with the character
    }
    }
    for some reason the program doesn't get to the "DEBUG" part, it does execute the more stuff that doesn't have to do with the character bit.

  4. #4
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Do the programs I posted above work? Or try this one that instead of just counting, lets you move an X around the console window. (I got clrscr and gotoxy from MSDN.)
    Code:
    #include <stdio.h>
    #include <conio.h>
    #include <windows.h>
    
    #define CONSOLE_WIDTH   80
    #define CONSOLE_HEIGHT  24
    
    void clrscr();
    void gotoxy(int x, int y);
    
    int main(void) {
        int ch = 'a'; /* input char; init to anything but q */
        int x = CONSOLE_WIDTH/2, y = CONSOLE_HEIGHT/2; /* position */
        int dx = 1, dy = 0; /* displacement for x and y */
    
        clrscr();
    
        while (ch != 'q') { /* q to quit */
            gotoxy(x, y);
            _putch('X');
    
            if (_kbhit()) {
                ch = _getch();
                if (ch == 224) {
                    switch (_getch()) {
                    case 72: /* Up    */  dx =  0;  dy = -1;  break;
                    case 75: /* Left  */  dx = -1;  dy =  0;  break;
                    case 77: /* Right */  dx =  1;  dy =  0;  break;
                    case 80: /* Down  */  dx =  0;  dy =  1;  break;
                    }
                }
            }
    
            if ((dx == 1 && x < CONSOLE_WIDTH-1) || (dx == -1 && x > 0))
                x += dx;
            if ((dy == 1 && y < CONSOLE_HEIGHT) || (dy == -1 && y > 0))
                y += dy;
    
            Sleep(100);
        }
    
        return 0;
    }
    
    void clrscr() {
        COORD coordScreen = { 0, 0 };
        DWORD cCharsWritten;
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        DWORD dwConSize;
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        GetConsoleScreenBufferInfo(hConsole, &csbi);
        dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
        FillConsoleOutputCharacter(hConsole, TEXT(' '), 
    		dwConSize, coordScreen, &cCharsWritten);
        GetConsoleScreenBufferInfo(hConsole, &csbi);
        FillConsoleOutputAttribute(hConsole, csbi.wAttributes, 
    		dwConSize, coordScreen, &cCharsWritten);
        SetConsoleCursorPosition(hConsole, coordScreen);
    	return;
    } 
    
    void gotoxy(int x, int y) {
        COORD coord;
        coord.X = x; coord.Y = y;
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    	return;
    }
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  5. #5
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Strange! I had a mess with this earlier, seemed like you had some dodgy control flow but the bit where you were using kbhit was basically ok. I wrote a little test program, maybe you could try it and see if it works. Are you using MSVC?

    Code:
    #include<stdio.h>
    #include <conio.h>
    
    void main()
    {
     char c = 0;
    
     while(1)
     {
      if(_kbhit())
      {
    	  c =_getch();
    
      printf ("\ngot char %c", c);
      }
      
    noinput:
      c++;
      c--;
     }
    return;
    
    }
    I've compiled and run this with MSVC 2010, it works.

    Assuming that or one of oogabooga's examples work and it's not your environment/libraries, my guess would be that your other code is the problem. Perhaps it gets into some long intensive processing or doesn't go ever back to the if statement. Can you make sure it's executing that line reasonably frequently? Maybe increment a counter on it or easier just breakpoint it in a debugger.

  6. #6
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Here's a modification of the program in post#4 that let's you move your name around the screen like a snake.
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <conio.h>
    #include <windows.h>
    
    #define CONSOLE_WIDTH   80
    #define CONSOLE_HEIGHT  24
    #define MAX_NAME        21
    
    typedef struct {
        int x, y;
    } Point;
    
    void clrscr();
    void gotoxy(int x, int y);
    
    int main(void) {
        int ch = 'a';          /* Input char; init to anything but q */
        int dx = -1, dy = 0;   /* Displacement for x and y */
        char name[MAX_NAME];
        Point point[MAX_NAME]; /* Position of each character in name. */
        size_t i, len;
    
        clrscr();
    
        /* Get user's name, remove newline, concatenate space. */    
        printf("Enter your name: ");
        fgets(name, sizeof name - 1, stdin); /* Leave room for a space char. */
        len = strlen(name);
        if (name[len-1] == '\n')
            name[--len] = '\0';
        name[len++] = ' ';
        name[len] = '\0'; /* Ensure zero termination. */
    
        /* Initialize point array. */
        point[0].x = CONSOLE_WIDTH / 2;
        point[0].y = CONSOLE_HEIGHT / 2;
        for (i = 1; i < len; i++) {
            point[i].x = point[i-1].x + 1;
            point[i].y = point[i-1].y;
        }
    
        clrscr();
    
        while (ch != 'q') { /* q to quit */
    
            /* Display each char in name at it's position in point. */
            for (i = 0; i < len; i++) {
                gotoxy(point[i].x, point[i].y);
                _putch(name[i]);
            }
    
            if (_kbhit()) {
                ch = _getch();
                if (ch == 224) {
                    switch (_getch()) {
                    case 72: /* Up    */  dx =  0;  dy = -1;  break;
                    case 75: /* Left  */  dx = -1;  dy =  0;  break;
                    case 77: /* Right */  dx =  1;  dy =  0;  break;
                    case 80: /* Down  */  dx =  0;  dy =  1;  break;
                    }
                }
            }
    
            /* Move each char into the next char's position. */
            for (i = len - 1; i > 0; i--)
                point[i] = point[i-1];
    
            /* Update head char's position. */
            if ((dx ==  1 && point[0].x < CONSOLE_WIDTH - 1) ||
                (dx == -1 && point[0].x > 0))
                point[0].x += dx;
            if ((dy ==  1 && point[0].y < CONSOLE_HEIGHT) ||
                (dy == -1 && point[0].y > 0))
                point[0].y += dy;
    
            Sleep(100);
        }
    
        return 0;
    }
    
    void clrscr() {
        COORD coordScreen = { 0, 0 };
        DWORD cCharsWritten;
        CONSOLE_SCREEN_BUFFER_INFO csbi;
        DWORD dwConSize;
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        GetConsoleScreenBufferInfo(hConsole, &csbi);
        dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
        FillConsoleOutputCharacter(hConsole, TEXT(' '), 
    		dwConSize, coordScreen, &cCharsWritten);
        GetConsoleScreenBufferInfo(hConsole, &csbi);
        FillConsoleOutputAttribute(hConsole, csbi.wAttributes, 
    		dwConSize, coordScreen, &cCharsWritten);
        SetConsoleCursorPosition(hConsole, coordScreen);
    	return;
    } 
    
    void gotoxy(int x, int y) {
        COORD coord;
        coord.X = x; coord.Y = y;
        SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
    	return;
    }
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  7. #7
    Registered User mr_raging_money's Avatar
    Join Date
    Mar 2012
    Posts
    18
    Yes, oogabooga's first example does work. I am not using MSVS, but I don't think that matters since his codes work.

  8. #8
    Registered User mr_raging_money's Avatar
    Join Date
    Mar 2012
    Posts
    18
    Ok, now it works. The thing making it now work seems to be I had
    Code:
    while(ch!='q')
    , to keep my main loop going. In that loop I had and
    Code:
    if(ch=='q'){
    return 0;
    }
    I changes the while loop to while(1), and everything now works out all right. Thanks a lot guys.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. (!_kbhit()) problem in Dev-C++
    By HermitCrab in forum C++ Programming
    Replies: 8
    Last Post: 06-16-2007, 03:01 PM
  2. Using _kbhit() in a console window.
    By clu82 in forum C Programming
    Replies: 2
    Last Post: 09-11-2003, 01:37 AM