Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

confuded

macrumors newbie
Original poster
Apr 20, 2011
3
0
Hi,

Please consider the following SHORT code:

Code:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <stdbool.h>

#define kCups 3

int RandomNumber(int l_limit, int u_limit);
void ClearArray(bool array[], int size);

int main (int argc, const char * argv[]){
    //initialise array of cups (boolean)
    bool cups[kCups];
    
    //initialise menu loop
    bool exit = false;
    do{
        printf("There are %d cups. One of them contains the ball.\n"
               "Which cup contains the ball?\n", kCups);
        
        //play again?
        bool validAnswer = false;
        do{
            printf("Play the game again?\n");
            char answer[4];
            fgets(answer, 4, stdin);
            switch(answer[0]){
                case 'y': case 'Y':
                    validAnswer = true;
                    break;
                case 'n': case 'N':
                    validAnswer = true;
                    exit = true;
                    break;
                default:
                    printf("Please enter a valid answer!\n");
            }
        }while(!validAnswer);
    }while(!exit);
    
    
    return 0;
}

void ClearArray(bool array[], int size){
    for(int i = 0; i < size; i++)
        array[i] = false;
}

If you run the program the first time around and type in 'yes' when asked, it will go back and do what it's suppose to... The second time it gets to the switch statement NO MATTER what you type - the switch goes do default!

I've run the code in Xcode 4 under gdb and looked at the answers array the first and the consecutive times around... At first all seems normal, but then the array is filled up with jumble!

Does the fgets() fail? Does the array needs to be cleared or something?

Thanks in advance!

~confuded
 
Last edited:

subsonix

macrumors 68040
Feb 2, 2008
3,551
79
My guess is that a new line character is left in the buffer. So the second time around, fgets gets '\n' which match nothing but the default. This makes sense with the 'Yes' alternative as well since the string consumes all space you have i.e 'Y', 'e', 's', '\0'. Try making the answer into answer[5].
 

chown33

Moderator
Staff member
Aug 9, 2009
10,747
8,420
A sea of green
My guess is that a new line character is left in the buffer. So the second time around, fgets gets '\n' which match nothing but the default. This makes sense with the 'Yes' alternative as well since the string consumes all space you have i.e 'Y', 'e', 's', '\0'. Try making the answer into answer[5].

I concur.

The posted code works fine if you only enter short responses, such as "y" or "n". It only malfunctions with long responses: e.g. try it with "yarrow" or "yesterday" or "you must be joking".

Better input checking would improve results even more. The key is to check for a newline at the end of the fgets() result. If you don't see a newline, then it means a complete line wasn't read, so you should repeatedly call fgets() until a newline IS read. This newline indicates the end of the line, i.e. the end of "yarrow" or "yesterday" or "you must be joking". If you're smart, you'll put this in a separate function, which you can then reuse in other programs that have similar input requirements.
 

Bill McEnaney

macrumors 6502
Apr 29, 2010
295
0
Since you check only answer[0], to avoid the newline problem, why not declare answer as a character variable, not as a string?
 
Last edited:

confuded

macrumors newbie
Original poster
Apr 20, 2011
3
0
subsonix, the suggestion works temporarily for my programing practice to allow for answer to be 5 chars long, though if I enter something longer than 'yes' the problem still occurs...

chown33, I am a little confused on how this solves the problem...
The inout still REMAINS in the stdin buffer...

If I type in 'yess' the first time around and press enter, the answers array (size 5) will have 'yess' + the '\0' (terminating zero). The second time around it looks like this:

4ibsl2.png


It seems like the rest of what I typed in i.e. carriage return, is inputed to fgets() without even asking for user input! Thats right! The second round fgets() skips user input entirely! (as you can see by the program stopping at the breakpoint in the pic, at the default clause of the switch statement)

My conclusion is that the stdin buffer needs to be cleared from my understanding... Is there a way to do that?


Since you check only answer[0], to avoid the newline problem, why not declare answer as a character variable, not as a string?

It is a character variable ;),


Thanks for all the help guys! Fast response and friendly feedback is great! :eek:

~confuded


EDIT: I tried fflush(stdin) staright after fgets()... it didn't work...
subsonix's, suggestion seems to match best the criteria stated in the code... Heh, I still would like to know how to make this universal if possible :). Thanks!
 
Last edited:

subsonix

macrumors 68040
Feb 2, 2008
3,551
79
EDIT: I tried fflush(stdin) staright after fgets()... it didn't work...
subsonix's, suggestion seems to match best the criteria stated in the code... Heh, I still would like to know how to make this universal if possible :). Thanks!

What is commonly used in place of fflush(stdin), is a while loop like this:

Code:
while( getchar() != '\n' );
 

larswik

macrumors 68000
Sep 8, 2006
1,552
11
I remember when I had this NEW LINE problem I used a scanf after my fgets to absorb the new line left over. It may not be the best way but it worked for a small project I made when I was learning C

-Lars
 

confuded

macrumors newbie
Original poster
Apr 20, 2011
3
0
OK, thanks for the replies guys... I'll go figure something out now that I have a couple of solutions :).

~confuded
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.