0
votes

I hope somebody can help me in explaining the following behaviour when using multiple fgets.

The following code works and the user needs to enter something for each fgets :

char input[1]; // to store a character
fgets(input,3,stdin); // read a character from the keyboard

char test[5];// for second fgets
fgets(test,3,stdin); // to test if this asks for user input too

printf("The character input is %c",input[0]);

==========OUTPUT============
Enter a character please: 
e
f
The character input is e
=============================

However the following code will only let the user enter input for the FIRST fgets:

char input[1]; 
fgets(input,2,stdin); // THIS IS THE DIFFERENCE, USING 2 INSTEAD OF 3

char test[5];
fgets(test,3,stdin);

printf("The character input is %c",input[0]);
=====OUTPUT=============
Enter a character please: 
e
The character input is e
=========================

The difference is this line:

fgets(input,2,stdin);

Where using less than 3 means that the following fgets does not ask for user input. I think this might be because with size 3, when the user presses Enter after inputting a character, the \n is consumed by the first fgets when the size is 3 or more. But if the size is less than 3, the \n is not consumed by first fgets, leaving it on stdin, and so it is consumed by the 2nd fgets which is why the 2nd fgets terminates without waiting for user input.

If I use sizeof(char) as that value, then I get output:

=============OUTPUT============
Enter a character please: 
e
The character input is 
===============================

Which is weird because I have seen people recommending using sizeof(type) for that parameter.

I hope somebody can explain why 3 is needed to consume the \n, I would have expected 2 would be enough, e.g. 1 byte for the char and 1 byte to consume the \n, and also if that is the case then the recommended choice of sizeof(type) is wrong, because you would need sizeof(type)+1, but it seems you actually need sizeof(type) + 2 to allow the \n to be consumed and removed from stdin. Please help me with your understanding of this, thankyou.

2
Thankyou for replying so quickly. However using char input[3] I still have the same problem, which is that fgets(input,2,stdin); still stops the following fgets from accepting user input. If I use char input[3] and fgets(input,sizeof(char),stdin) then enter say 'e' it doesn't store this is input[0] at all.mertcoder
This is why it is better to use fgets(input, sizeof input, stdin); You need "1 byte for the char and 1 byte to consume the \n," and 1 byte for the terminating nul character. Please use a generously sized buffer.Weather Vane
Letter, newline, null byte. Three bytes needed. Under normal circumstances, start with char input[2048]; — you can always make it bigger if need be. You have to be on a tiny system for 2 KiB to be a problem.Jonathan Leffler
thanks Weather Vane and Jonathan Leffler, that sounds like the answer. Which means that it is necessary to use fgets(input,sizeof(char)+2,stdin);mertcoder
No, don't play with it like that. Allocate a large buffer in the first place.Weather Vane

2 Answers

2
votes

You have two different problems:

The first is that you write out of bounds of your array input, which leads to undefined behavior.

For the second problem, when you tell fgets that the size of the buffer is 3 it will read the character and the newline and add both to the buffer you provide and add the string null-terminator. When you say that the size is 2 it will read the character but not the newline, since the size includes the string null-terminator. That means the next fgets call will read the newline and think it's an empty line.

You solve the problems by using a buffer large enough to fit all the characters, plus the newline and the string null-terminator. For a single characters, that means your array must contain three elements:

char input[3];
fgets(input, sizeof input, stdin);

As an optional solution, you could read a single character (for example with getchar or getc or fgetc).

Then you need to read (but don't store) characters in a loop until you have read the newline.

Perhaps something like this:

int input = getchar();

// Discard the rest of the line
for (int temp = getchar(); temp != '\n' && temp != EOF; temp = getchar())
{
    // Empty
}
0
votes
char input[1]; // to store a character
fgets(input,3,stdin);  // read a character from the keyboard

the input variable, If a user enters a string like "new", It will leads to segmentation fault, And when the value exceeds the caharacter from fgets(input,3,stdin) The stdin will ignore them, I can't actually state the design behind this fgets() having same values with the array of char.