PDA

View Full Version : [Resolved] [C] What happens to my char array?




confuded
Apr 20, 2011, 07:25 PM
Hi,

Please consider the following SHORT 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



subsonix
Apr 20, 2011, 07:36 PM
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
Apr 21, 2011, 12:10 AM
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
Apr 21, 2011, 03:40 AM
Since you check only answer[0], to avoid the newline problem, why not declare answer as a character variable, not as a string?

confuded
Apr 21, 2011, 04:42 AM
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:

http://i51.tinypic.com/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! :o

~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!

subsonix
Apr 21, 2011, 10:07 AM
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:

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

Bill McEnaney
Apr 21, 2011, 10:29 AM
It is a character variable ;)
To quote Steve Martin, "Well, excuuuuuuuuuuuse meeeeeeeeee!" I should have said, "a scalar variable of type char." :D

larswik
Apr 21, 2011, 11:09 AM
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
Apr 21, 2011, 01:47 PM
OK, thanks for the replies guys... I'll go figure something out now that I have a couple of solutions :).

~confuded