Solved: The Problem With Using fgets() After scanf()

Solved: The Problem With Using fgets() After scanf()
Solved: The Problem With Using fgets() After scanf()

Introduction

The scanf() function is a widely used function in C/C++. Although the syntax to use it is simple, it is important to understand some areas where its usage would require careful handling. One such area is when fgets() is used after scanf().

In this article, we will address this problem of how fgets() doesn’t work after scanf() and also derive the solutions to it. Before that let’s understand how the scanf() and fgets() functions work. 

The scanf()function in C/C++

The scanf() is a function in the C library that reads formatted data from the standard input stream and then writes the output into the given arguments. This function is declared as follows:

int scanf( const char *format, ... );

Let’s discuss the various aspects of this declaration.

  1. int refers to the type of return value of the function. 
  1. format is the C string that contains the type specifiers. Type specifiers are used to define the type of data that will be stored in a variable which is taken as input using the scanf() function. The following table displays a few examples of the type specifiers identified by scanf().
Format SpecifiersType of Data
%cCharacter
%dSigned integer
%fFloating point
%xUnsigned integer in hexadecimal format
%sString
  1. The ellipsis (“…”) points to the fact that the scanf() function may contain a variable number of arguments, given that every argument is a memory address into which the converted result is written into. 

The scanf() function is part of a family of functions that essentially have the same purpose but read the input from other sources. For example, fscanf() reads from the file stream and sscanf() reads from a null-terminated string buffer. 

Here is a small example of how we use the scanf() function:

int main () {
   char str1[20];

   printf("Enter name: ");
   scanf("%s", str1);

   printf("Entered Name: %s\n", str1);
   
   return(0);
}

Input:

Enter name: Ninja

Output:

Entered name: Ninja

The fgets() function in C/C++

The fgets in the fgets() function stands for ‘file get string’. This is essentially a function that is used to read up to n characters from the stream (file stream or standard input stream) into string str. It is declared as:

char* fgets(char* str, int n, FILE* stream);

Let’s discuss every aspect of this declaration. 

  • int n refers to the number of characters that need to be read into the string.
  • FILE* stream is the pointer to the file stream from which the input is being read. This is replaced by stdin when reading from the standard input. 
  • The pointer to str is the return value of this function.

Let’s take an example to understand how fgets() reads from a file.

# include <stdio.h>
int main( )
{
         FILE *file ;
         char str1[40] ;
         printf( "The file sample.txt is opened in read mode" ) ;
         file = fopen( "sample.txt", "r" ) ;
         if ( file == NULL )
         {
                 printf( "sample.txt couldn't be opened" ) ;
                 return 0;
         }
         printf( "sample.txt is being read." ) ;
         while( fgets ( str1, 40, file) != NULL )
         printf( "%s" , str1 ) ;
         printf("The file sample.txt is now closed") ;
         fclose(file) ;
         return 0;
} 

Output:

Opening the file test.c in read mode
Reading the file test.c
Welcome to Coding Ninjas
Closing the file test.c

The fgets() function terminates its operation if one of the following conditions is fulfilled. These conditions will be important to keep in mind during our discussion on why fgets() doesn’t work after scanf().

  • A newline character is encountered
  • The function has read n – 1 character
  • EOF (End of File) has been reached

Problem with using fgets() after scanf() 

Now that we know how the fgets() and scanf() functions work, let’s look at what happens if we use the fgets() function right after the scanf()function and whether fgets() doesn’t work after scanf(). 

int main(){

	int x;
	char str[50];
	scanf(“%d”, &x);
	fgets(str, 50, stdin);
	printf(“x = %d, str = %s”, x, str);
	return 0;

}

Input:

5
Ninja

Output:

x = 5, str =

We can see here that the string “Ninja” is not printed. What is the reason behind this? The problem is because of a certain feature of the scanf() function. 

When scanf() reads input from the standard input stream, it also creates a newline character in the buffer. So in the above code, after reading the integer x, the scanf() function left a newline character. The fgets() function then reads this newline character and terminates the operation (recall the three conditions that we discussed for the fgets() operation to stop reading input). Therefore the string “Ninjas” is ignored by the fgets() function and does not get printed. 

This feature of scanf() is something that is important to note whenever we use this function. But now the question is, is there a solution to this problem of how fgets() doesn’t work after scanf()? How do you print the string “Ninjas” as well?

The solution to the problem

After assessing the problem of why fgets() doesn’t work after scanf(), it is time to derive a solution. Observe the code below. 

int main(){

int x;
char str[50];
scanf("%d\n", &x);
fgets(str, 50, stdin);
printf("x = %d, str = %s", x, str);
return 0;
}

Input:

10
Ninjas

Output:

x = 10, str = Ninjas

Do you see the difference? We have introduced an extra “\n” in scanf(“%d\n”, &x). By doing this, we make scanf() read a new line. We can also achieve this by 

  • Introducing an extra space as in scanf(“%d “, &x). 
  • Adding a getchar() function after the scanf() function to read an extra newline. 

Therefore, the fgets() will not have to read the newline and will read the string input. Thus solving the problem of how fgets() doesn’t work after scanf().

Frequently Asked Questions

How do I make Fgets work after scanf?

This can be solved by introducing a “\n” in scanf() as in scanf(“%d\n”, &x) or by adding getchar() after scanf().

Why fgets doesn’t work after scanf?

This can be solved by introducing a “\n” in scanf() as in scanf(“%d\n”, &x) or by adding getchar() after scanf(). The fgets() function then read this newline character and terminated operation.

Is Fgets better than Scanf?

There are certain aspects to look at before deciding so. fgets() can read from any file stream but scanf() only reads from standard input.

What is the syntax for using scanf()?

Here is the syntax for using scanf(),
int scanf( const char *format, … );

What is the syntax for using fgets()?

Here is the syntax for using fgets(),
char* fgets(char* str, int n, FILE* stream);

What does Scanf return in C?

Scanf returns the total number of inputs successful or EoF(End of Line) if there is an error.

Key Takeaways

While using the scanf() function, a very common problem is faced if it is used before an fgets() function. Because of this issue, the fgets() function does not read some part of the input as the scanf() function leaves a newline character in the buffer. This can be solved by introducing a “\n” in scanf() as in scanf(“%d\n”, &x) or by adding getchar() after scanf(). 

By Khushi Sharma