How do you clean out the contents of an array after you take input?

In my program, I put fgets in a loop to get input. However, once I loop back to the beginning to get input for the second time, the previous input values are still in the array, so it skips the fgets :cry:

The problem occurs in the first while loop.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define SIZE 20
#define CSIZE 4

struct name {
	char first[SIZE];
	char last[SIZE];
};

struct student {
	struct name ppl;
	float grade[3];
	float avg;
};

int main(void)
{
	static struct student data[CSIZE] = {
		{{"Bill", "Gates"}, {0.0, 0.0, 0.0}, 0.0},
		{{"Mace", "Windu"}, {0.0, 0.0, 0.0}, 0.0},
		{{"Darth", "Vader"}, {0.0, 0.0, 0.0}, 0.0},
		{{"Happy", "Dog"}, {0.0, 0.0, 0.0}, 0.0},
	};

	char inputA[SIZE], inputB[SIZE];
	int i = 0, j = 0, k = 0;
	float score = 0, sum = 0;

	while (i < CSIZE)
	{
	
		fputs("First name:", stdout);
		fgets(inputA, SIZE, stdin);
		fputs("Last name:", stdout);
		fgets(inputB, SIZE, stdin);

		while (j < 3)
		{
			printf("score %d: ", j+1);
			scanf("%f", &score);

			data[i].grade[j] = score;
			sum += score;
			j++;
		}
		
		data[i].avg = (sum / 3);
		j = 0;
		i++;
	}

	while (k < CSIZE)
	{
		printf("%s %s. Scores = %.2f %.2f %.2f. Average = %.2f\n", data[k].ppl.first, data[k].ppl.last,
			data[k].grade[0], data[k].grade[1], data[k].grade[2], data[k].avg);
		k++;
	}

	return 0;
}

Hi. Thanks for the reply.

The same problem still occurs even after I use memset - fgets() still skips over user input :cry:

Well i just solved it by using fflush (which i'm not really sure what it does). But here is the code with memset.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define SIZE 20
#define CSIZE 4

struct name {
	char first[SIZE];
	char last[SIZE];
};

struct student {
	struct name ppl;
	float grade[3];
	float avg;
};

int main(void)
{
	static struct student data[CSIZE] = {
		{{"Bill", "Gates"}, {0.0, 0.0, 0.0}, 0.0},
		{{"Mace", "Windu"}, {0.0, 0.0, 0.0}, 0.0},
		{{"Darth", "Vader"}, {0.0, 0.0, 0.0}, 0.0},
		{{"Happy", "Dog"}, {0.0, 0.0, 0.0}, 0.0},
	};

	char inputA[SIZE], inputB[SIZE];
	int i = 0, j = 0, k = 0;
	int sizeA, sizeB;
	float score = 0, sum = 0;

	while (i < CSIZE)
	{
		fputs("First name:", stdout);
		fgets(inputA, SIZE, stdin);
		fputs("Last name:", stdout);
		fgets(inputB, SIZE, stdin);

		sizeA = strlen(inputA);
		sizeB = strlen(inputB);
		while (j < 3)
		{
			printf("score %d: ", j+1);
			scanf("%f", &score);

			data[i].grade[j] = score;
			sum += score;
			j++;
		}
		
		data[i].avg = (sum / 3);
		memset(inputA, '\0', sizeA);
		memset(inputB, '\0', sizeB);
	//	fflush(stdin);
		sum = j = 0;
		i++;
	}

	while (k < CSIZE)
	{
		printf("%s %s. Scores = %.2f %.2f %.2f. Average = %.2f\n", data[k].ppl.first, data[k].ppl.last,
			data[k].grade[0], data[k].grade[1], data[k].grade[2], data[k].avg);
		k++;
	}

	return 0;
}

I see the problem now. When you typed the score 45\n for example, scanf take the integer part for the score, and leaves the newline \n in the stream. Therefore fgets takes this remaining \n as the input for the firstname: hence you see firstname:lastname in the same line. It had nothing to do with clearing the array.

fflush() flushes out all the remaining characters in the stream thereby clearing the stream of the remaining \n.

The function flushall() also does the same thing.

Edited 3 Years Ago by __avd: fixed formatting.

I am not that good in theory, but you use the term stream for communications channels like a file, input/output device.

>fflush(stdin);
Ack! I'll not allow such heresy on this forum. ;) The fflush function is only defined for output streams, and the behavior is unpredictable at best when you give it an input stream.

fflush() flushes out all the remaining characters in the stream thereby clearing the stream of the remaining \n.
The function flushall() also does the same thing.

Perhaps on your implementation, but the C standard says quite clearly that flushing an input stream is undefined, and flushall is a non-standard function. Now, you can pass fflush a null pointer and it will flush all open output streams, but that still has nothing to do with discarding any unread characters from an input stream. This is what people usually want when they use fflush(stdin):

void jsw_flush ( FILE *in )
{
  int ch;

  do
    ch = fgetc ( in );
  while ( ch != EOF && ch != '\n' );

  clearerr ( in );
}

>I never got this concept, but what do you mean by stream?
Think of one of those fun tunnel slides at the water park. The slide is a stream, and the kids who go through it are the characters. The source of the stream is at the top, and the sink (your program) is at the bottom. Characters come from the source, through the stream, and end up in your program for processing. The souce could be a file, or a device like the keyboard, it really doesn't matter because streams are designed to be black boxes. You don't need to know where the characters come from or how they get to you as long as they do.

But it's not always that simple. There's usually a line. That line is what we call the stream buffer, where characters wait to be inserted into the stream and sent to you. Now, it's a pain for the characters to just sit in the buffer, and the maintenance is frustrating for all parties, but it's much faster to grab a kid from the front of the line and toss him into the stream than call the kid's house and have him come down to the water park to take a ride.

Actually, the buffer is on both sides, and the buffer that matters to you is on your side, but that kills the analogy. :)

Perhaps on your implementation, but the C standard says quite clearly that flushing an input stream is undefined, and flushall is a non-standard function.

Yeah my compiler Visual C 2003 allows clearing an input stream with

fflush

, and

flushall

. :sad: Thanks for the correction. Got to refer the Standard C documentation more, rather than MSDN.

>Got to refer the Standard C documentation more, rather than MSDN.
If your documentation uses void main (or deprecates in favor of its own butt ugly "safe" replacements"), you shouldn't rely on it for standard C information. ;)

>> if its a character array then initialize it with '\0' and if its an integer array then initilize it with 0

I'm not about to revive that old thread you linked, so I'll do it here because I just can't resist the urge :twisted: . In the above, '\0' and 0 are identical because '\0' == 0. Personally, I prefer just plain 0 -- why? because its less typing.

char array[255];
memset(array,0,sizeof(array));

int array[255];
memset(array,0,sizeof(array);

>> if its a character array then initialize it with '\0' and if its an integer array then initilize it with 0

I'm not about to revive that old thread you linked, so I'll do it here because I just can't resist the urge :twisted: . In the above, '\0' and 0 are identical because '\0' == 0. Personally, I prefer just plain 0 -- why? because its less typing.

char array[255];
memset(array,0,sizeof(array));

int array[255];
memset(array,0,sizeof(array);

Man ain't I learning today. I always used 0 blindly. Didn't know that \0 == 0 :eek: Thanks Dragon. :)

>Man ain't I learning today. I always used 0 blindly. Didn't know that \0 == 0 Thanks Dragon.

It seems like you enjoy learning all the stuff everyone else hates... win32,using flushin'....


;)

> How do you clean out the contents of an array after you take input?
The problem goes away (or more precisely, never arises) if you use fgets() to read all input, then use sscanf() / strcpy() / strxxx or whatever to extract information from the line returned by fgets().

By using scanf(), you upset the whole input stream, and have to resort to all sorts of bizarre ways of getting out of the hole you just dug for yourself - a hole which simply didn't need to be dug in the first place.

This article has been dead for over six months. Start a new discussion instead.