Thread: Getchar, getch and gets inside while loop

  1. #1
    Registered User
    Join Date
    Feb 2012
    Posts
    33

    Question Getchar, getch and gets inside while loop

    - I have a if statement. Inside I have a while loop. I've noticed that in the first iteration gets() recieves something without me typing anything(I think it's the previous \n from getchar()). In the second iteration though it works properly. But if I use scanf() it works the first time. WHY?! I need to use gets() so this is really ........ing me off!

    - Also the the getchar() inside the while gets ignored. If I put two getchar() together it works. It also works if I put a getch(). WHY!?

    Here's my code:

    Code:
    int bonusRound1()
    {
        char y_or_n, firstAns[50], ans[50], exit[]="exit", quit[]="quit", yes[]="y", no[] = "n", nl;
        int i, bonusPoints=0, correctAns=0;
        char charlie[] = "charlie";
    
    
    printf("\n Would you like to play a bonus round? y or n? ");
    y_or_n=getchar();
    
    
    if(y_or_n == 'y')
    {
    while(correctAns != 1)
    {
        printf("\n________________________________________________________________________________\n");
        printf(" Bonus question 1. Who's quote is this?\n");
    
    
        printf("\n \"It's French, the French are coming! I've never been so happy to hear the\n"
               " French.\"\n");
        printf("\n > ");
        //gets(firstAns);
        scanf(" %s", firstAns);
         
    
    
        for(i=0; i<=strlen(firstAns); i++)
        {
            ans[i] = tolower(firstAns[i]);
        }
    
    
        if(strcmp(ans, charlie) == 0)
        {
            printf("\n That's correct! Press enter to continue...\n");
            //getchar();
            //getchar();
            getch();
            bonusPoints += 10;
            correctAns=1;
        }
        else if(strcmp(ans, quit) == 0 || strcmp(ans, exit) == 0)
        {
            break;
        }
    
    
        else
        {
            printf("\n That's incorrect! Press enter to continue...");
            //getchar();
            //getchar();
            getch();
            continue;
        }
    }
    }
    if(y_or_n == 'n')
    {
        return;
    }
    
    
    }
    Last edited by sampleandhold; 03-31-2012 at 08:18 AM.

  2. #2
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    gets shouldn't be used because it doesn't check to see how much you type. What it does do though is take the newline out of the input stream. It doesn't keep it, it just throws it out when it stops looking for input (that's how it decides to stop).

    gets is basically this:
    Code:
    gets( string )
        x = 0
        while ( c = getchar ) != \n
            string[ x++ ] = c
        string[ x ] = \0
    It doesn't care how much space you've set aside for your string. It just keeps going until it hits a newline.

    getchar reads 1 character. So if you type 'c' and hit enter to send that, then your getchar takes the 'c', and the enter key sits there waiting for you to do something with it.


    Quzah.
    Hope is the first step on the road to disappointment.

  3. #3
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    Dont ever use gets() for any reason. Use fgets() instead.

    When you use getchar() to input a character you need to make sure you discard the return key, otherwise it will remain in the input buffer and be used by whatever read input function you are using next.
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  4. #4
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    First never use gets(), this is a very dangerous function. Use a function where you have control over the length of user input, like fgets().

    Your problem is usually caused by mixing character input with numeric input. The numeric input leaves the end of line character in the input buffer which the character input extracts for it's input. So if you mix numeric and character input, extract the end of line character after your numeric input.

    Jim

  5. #5
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Type faster, noobs!


    Quzah.
    Hope is the first step on the road to disappointment.

  6. #6
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Haha.

    Yep, the newline is just left hanging around after the first getchar(). Best to put another getchar() after each single character input to gobble up the newlines.

    If you're using scanf you can eat the newline like so:

    Code:
    scanf(" %s\n", firstAns);
    Gets() will discard the newline, which is nice but as said, gets is bad. fgetc() will read the newline into the buffer at the end of the line, so you need to discard it, or ignore it when doing a strcmp.

  7. #7
    Registered User
    Join Date
    Feb 2012
    Posts
    33
    Thanks. I've never heard of fgets(). I'll look into it.

    But what can I do about the getchar() I'm using. I guess I can use getch(). But can someone explain to me why I have to use several getchar() ?!?

  8. #8
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by sampleandhold View Post
    But can someone explain to me why I have to use several getchar() ?!?
    It's been explained three times now.

    getchar reads 1 character. You are putting in TWO characters (letter + enter key). Why is that confusing to you?


    Quzah.
    Hope is the first step on the road to disappointment.

  9. #9
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Because of the hanging newline from this input:

    Code:
     scanf(" %s", firstAns);
    Whichever way you go you'll always have a spare newline waiting on stdin by the time you get to your getchar(). getchar() blocks until a newline is entered, so you hit enter here as prompted, and then have 2 newlines to get through.

    getch() I'm not so familiar with -- on Windows at least it seems to process the character straight away (no need to press enter at all). The second '\n' is still there, it's just processed less aggressively. If you put getch() followed by getchar() the second getchar() will go straight through with a newline, So, if you use fgets() beforehand to read the answer, then you'll only need one getchar().

    You don't have any handling for if the user decides to type in some characters before hitting enter. That'd screw everything up again, so it might be a good idea to loop until getchar() == '\n'. It's all a bit of a headache, but so long as you remember to grab the newlines right after you've typed them it's not so bad

  10. #10
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Actually quzah, I think he was asking about the bit where the user is prompted to hit "Enter" alone. So there woukd just be one character, if there wasn't a pesky newline already hanging out from previous getchar() and scanf().

  11. #11
    Registered User
    Join Date
    Feb 2012
    Posts
    33
    Quote Originally Posted by quzah View Post
    It's been explained three times now.

    getchar reads 1 character. You are putting in TWO characters (letter + enter key). Why is that confusing to you?


    Quzah.
    I took a long time to write my reply and didn't see the other responses.
    BTW it was not explained three times at the time!

    And it's not confusing at all. I read about this a long time ago but I forgot about it. I've been using getchar() alot, but only with the purpose of getting an enter key to continue. In my latest code I'm using getchar() to get a letter and then it goes into a loop.

    Now I know what to do. Thanks for the help guys

  12. #12
    Registered User
    Join Date
    Feb 2012
    Posts
    33
    Quote Originally Posted by smokeyangel View Post
    Because of the hanging newline from this input:

    Code:
     scanf(" %s", firstAns);
    Whichever way you go you'll always have a spare newline waiting on stdin by the time you get to your getchar(). getchar() blocks until a newline is entered, so you hit enter here as prompted, and then have 2 newlines to get through.

    getch() I'm not so familiar with -- on Windows at least it seems to process the character straight away (no need to press enter at all). The second '\n' is still there, it's just processed less aggressively. If you put getch() followed by getchar() the second getchar() will go straight through with a newline, So, if you use fgets() beforehand to read the answer, then you'll only need one getchar().

    You don't have any handling for if the user decides to type in some characters before hitting enter. That'd screw everything up again, so it might be a good idea to loop until getchar() == '\n'. It's all a bit of a headache, but so long as you remember to grab the newlines right after you've typed them it's not so bad
    In case the user decides to type in some characters what kind of loop should I use catch all the characters and the \n ? Can you show me how to do it?
    Last edited by sampleandhold; 03-31-2012 at 12:11 PM.

  13. #13
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Sure. I was thinking something like this:

    Code:
      printf("\npress enter");
      c = getchar();
    
     while (c != '\n')
    	 c = getchar();
    So the user could type in a load of junk and it's just be chucked away until the next newline.

    Now I've written that though, you could just call fgets again instead of getchar. Probably just as efficient, and simpler.

  14. #14
    Registered User
    Join Date
    Feb 2012
    Posts
    33

    Post

    Quote Originally Posted by smokeyangel View Post
    Sure. I was thinking something like this:
    Code:
      printf("\npress enter");  c = getchar(); while (c != '\n')     c = getchar();
    So the user could type in a load of junk and it's just be chucked away until the next newline.Now I've written that though, you could just call fgets again instead of getchar. Probably just as efficient, and simpler.
    Thanks, now I know how to do that too! Also I read about fgets() in the tutorial and I replaced all the gets() in my program with fgets(), so I should be good now

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. do - while loop ignores getchar()
    By TheIggle in forum C Programming
    Replies: 3
    Last Post: 07-15-2010, 07:51 AM
  2. for loop ignoring scanf inside loop
    By xIcyx in forum C Programming
    Replies: 2
    Last Post: 04-17-2007, 01:46 AM
  3. getch() vs. getchar()
    By mako in forum C Programming
    Replies: 5
    Last Post: 01-24-2006, 11:20 AM
  4. getch() getchar() no need 4 fflush?
    By Mikeca in forum C Programming
    Replies: 4
    Last Post: 12-03-2005, 04:16 PM
  5. Difference between getch() and getchar()
    By codec in forum C Programming
    Replies: 4
    Last Post: 04-04-2004, 02:34 AM