Thread: Problems with cin and GetAsyncKeyState

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Registered User
    Join Date
    Aug 2008
    Posts
    30

    Problems with cin and GetAsyncKeyState

    Well, I'm a beginner in C++ and I tend to make MANY errors when trying out codes I'm not taught before. So recently I got to know about GetAsyncKeyState and i used it in my main function which is basically a menu. I did all the stuff I will need to do for GetAsyncKeyState in a bool keyDown(int vKey) function which returns either 1 or 0 depending on whether the key is pressed.

    Now my menu is supposed to link to another file which takes care of the user entering his/her profile. For this page I used cin, but I noticed a bug. This bug is that if I type something on the menu then press Enter to go into the profile page, which would go to the void profile() function, whatever I typed while on the menu page would automatically cin into my first cin, which is very weird. Of course, it would be better if someone could add me on MSN and help me but [if you need to see a part of my code to find out whats causing this problem feel free to post it here.]

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I don't do MSN, but I will try to help you here.
    GetAsyncKeyState doesn't "consume" the keys that it returns as being used. You may want to use the FAQ to get the code for "how do I read input without waiting for the user" (In level 2 "How Do I ..."). That will consume the input.

    However, if you want to use cin, you'd better not use Windows API functions intermingled with that.

    [Of course, another option would be to count the number of keys detected with GetAsyncKeyState, and then use cin.ignore(count), but if you don't scan for EVERY key on the keyboard, you potentially will miss some - so I'd still recommend that you use a different method for reading the keyboard].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Aug 2008
    Posts
    30
    Well basically what I meant was that the bool keyDown(int vKey) function would check if a key is pressed. So lets say keyDown(VK_RETURN) would check if VK_RETURN is pressed. So lets say I do something like

    Code:
    if(keyDown(VK_RETURN))
    {
         cout << "Enter!" << endl;
    }
    the keyDown function would return true if I pressed Enter and then cout Enter right? But now the problem is the string I want the user to cin after the user is done with the menu.

    Like
    Code:
    struct profile
    {
         string name;
    };
    void profilepage(void)
    {
         system("cls");
         profile player;
         cout << "Enter your name :";
         cin >> player.name;
    void main (void)
    {
         cout << "This is the Menu! Press Enter to proceed!" << endl;
         if(keyDown(VK_RETURN))
         {
              profilepage();
         }
    }
    So if the player presses Enter, he'll go to the "Enter your name :" part right? But the bug now is that, if I press Enter, it would show "Enter you name :" but the blinking _ is on the next line. I found it weird so at the "This is the Menu! Press Enter to proceed!" part I typed lolol before pressing Enter and the moment I press Enter it shows "Enter you name : lolol". Why does this happen? O_O and please remember that I am still a newbie so xD

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Yes, so did you just skim through my reply without paying attention: GetAsyncKeyState() only tells you whether that key is pressed. If you press the key, a character is entered into the input buffer. That is what cin reads. GetAsyncKeyState does not use up the keypresses, it just reports if that key is pressed at the exact moment in time or not.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Aug 2008
    Posts
    30
    Well I admit I skimmed through but it was because I didn't get the "consume" part so I thought I had to make things as clear as possible. So anyway, are you talking about the cin buffer thing which cin.clear() clears? and whenever I type anything it would go into the cin buffer?

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Yes, I'm talking about [1] the buffer that cin uses. But cin.clear() does not empty that buffer. cin.ignore(19999) will remove anything up to the next newline (as long as it's less than 19999 characters).

    And by consume, I mean that GetAsyncKeyState does not "use up" any keypresses, the keys you hit will go into the cin buffer as you type, and then be used by cin >> player.name. Try typing in "Charlie" before hitting enter on the main menu, and you would see that palyer.name becomes "Charlie".


    [1] Technically, cin doesn't get any data until enter is pressed, but for all intents and purposes we can ignore that. I'm just saying this to avoid someone commenting that this is incorrect.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    By default, ignore ignores until the EOF.

    As to your question, who knows what you did? (Answer: you, and not us.) What is the loop condition on your infinite loop?

  8. #8
    Registered User
    Join Date
    Aug 2008
    Posts
    30
    That endless loop is something like THE endless loop that happens when say you cin a char into an int variable. But if you need to see the code,
    Here it is!
    Code:
    struct personProfile
    {
    	char name[50];
    	int age;
    	char gender;
    };
    void profile (void)
    {
    	int choice;
    	personProfile person1;
    	
    	system("cls");
    	cout<<"                         ~~Welcome to Black-O~~"<<endl;
    	cout << endl;
    		cout<<"Enter Name: ";
    		cin.get(person1.name,50,'\n');
    .
    .
    .

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    There is no loop shown in your code, so I expect the endless loop is elsewhere.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  10. #10
    Registered User
    Join Date
    Aug 2008
    Posts
    30
    No even in a simple code without any loops, this error will also happen.
    See Cprogramming.com : FAQ > How do I...(Level 2) > Why does my program enter an infinite loop if the user inputs invalid data? (C++).
    I just want to know what I should do to my code that you can see to prevent the user from entering invalid data.

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by KgNe View Post
    No even in a simple code without any loops, this error will also happen.
    See Cprogramming.com : FAQ > How do I...(Level 2) > Why does my program enter an infinite loop if the user inputs invalid data? (C++).
    I just want to know what I should do to my code that you can see to prevent the user from entering invalid data.
    Well, there are several approaches to "avoid user inputting invalid data" - the most common one is to read data with a fgets (in C) or getline (in C++). That way, the user can type in anything he/she likes, and the application will not misbehave. It is then up to the rest of the code to figure out if the input is valid/useful with suitable conversion functions to conver the data into the correct format - e.g. string to integer, string to date, string to limited length string [e.g. you input a line of up to 500 characters, but a "username" is only allowed to be 30 characters].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    Registered User
    Join Date
    Aug 2008
    Posts
    30
    But I used cin.get(person1.name,50,'\n') so why won't it work? If cin.get is significantly different from getline could you tell me how I could use getline to replace cin.get in the code i posted earlier?

  13. #13
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    getline and get behave the same way. You can only get the infinite loop of bad input you appear to be talking about if you try to read numeric input directly. You can't get an infinite loop on inputting a string or characters.

  14. #14
    Registered User
    Join Date
    Aug 2008
    Posts
    30
    I'm using cin.get to get a string aren't I? So why does it still error?

  15. #15
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by KgNe View Post
    I'm using cin.get to get a string aren't I? So why does it still error?
    I assume the error is on the very next line after the bit you posted where it says cin >> person1.age. I will continue to believe that until you convince me otherwise. (In other words: I have been completely unable to make the snippet you posted behave in any violent manner.)

Popular pages Recent additions subscribe to a feed