fgets() & gets() Function In C | A Simple Explanation (+ Examples)
The fgets() and gets() in C programming language are functions primarily used for reading strings from user input or external files. However, they differ significantly in terms of safety and usage. The fgets() in C reads text from a file and stores it in a character array while allowing you to specify a character limit for safe input processing. On the other hand, the gets() in C also reads text from files but cannot define a character limit, making it less secure due to its susceptibility to buffer overflow vulnerabilities.
In this article, we will explore the functionalities and use cases of fgets() and gets() in C. We’ll also discuss the important differences between these two functions, highlighting why fgets() is the preferred choice in modern C programming.
What Is The fgets() C Function?
The built-in fgets() C function is used for reading strings from a file or basic user inputs (like keyboard).
- It reads a text line and stores it in a string/ character array. The function stops reading when it gets to a new line or the designated character limit (whichever comes earlier).
- The fact that it allows you to set a maximum number of characters to read ensures safe input storage and prevents any memory issues.
- The fgets() C is part of the <stdio.h> header file and it uses a pointer to character array/buffer where the input string will be stored.
The fgets() function reads a specified number of characters from a stream and stores them in a buffer, ensuring that the buffer does not overflow and that the string read is properly null-terminated. It offers a safer alternative to functions like gets(), which can lead to buffer overflows and security vulnerabilities.
Syntax:
char *fgets(char *str, int n, FILE *stream);
Here,
- *char str: It is a pointer to the character array where the read data is stored.
- int n: The maximum number of characters to be read, including the null character escape sequence (\0).
- FILE *stream: The file stream from which data is read.
Return Values:
- On success: The fgets() function returns a pointer to the string read from the file if the operation is successful.
- On Failure: If an error is encountered or the end of the file (EOF) is reached, it will return NULL (null pointer).
Code:
Output (assuming "example.txt" contains the following text):
Hello,
This is an example of using fgets in C.
Explanation:
In the above code example-
- We start by including the standard input-output library.
- In the main() function, we open a file named example.txt in read mode(r) using fopen() function. We will then store the file pointer in a variable file.
- Then, we use an if-statement to check if the file was opened successfully by ensuring that the file pointer is not NULL.
- If the file pointer is not NULL, it means the file was opened successfully. Here:
- We first define a character array buffer with a size of 100 to temporarily store each line read from the file.
- Then we use a while loop to read lines from the file using fgets() function.
- The fgets() function reads up to sizeof(buffer) - 1 characters from the file into buffer, and it stops reading if it encounters a newline character or the end of the file.
- The loop continues as long as fgets() successfully reads a line from the file (i.e., fgets() does not return NULL).
- For each line that we read, we print it to the console using the printf() function. The %s format specifier is used to print the string stored in the str array.
- After we have finished reading all lines from the file, we use fclose(file) to close the file. This is important for releasing resources and ensuring that all data is properly written and flushed.
- Finally, the main function returns 0, indicating that the program has been executed successfully.
You may also read: Length Of String In C | 7 Methods Explained With Detailed Examples
Key Features Of The fgets() C Function
Here are some key features of fgets(), along with general examples:
1. Safety and Buffer Overflow Prevention: The fgets() function in C reads up to n-1 characters from the input stream and appends a null terminator (\0) at the end of the buffer. This means it will not read more characters than the buffer can handle, thus preventing buffer overflow, which can lead to security vulnerabilities and crashes. For example-
char buffer[10]; // Buffer can hold up to 9 characters plus the null terminator
if (fgets(buffer, sizeof(buffer), stdin)) {
printf("Input: %s", buffer); // Reads up to 9 characters
}
2. Handles Newline Characters: If fgets() reads a newline character (\n) from the input, it includes it in the buffer along with the text. This feature helps to preserve the format of the input, which can be important for line-by-line processing. For example-
char buffer[100];
if (fgets(buffer, sizeof(buffer), stdin)) {
printf("Read Line: %s", buffer); // Includes the newline character if present
}
3. Error and End-of-File Detection: The fgets() in C returns NULL if an error occurs or if it reaches the end of the file before reading any characters. This allows you to handle errors or detect the end of the input stream. For example-
char buffer[50];
if (fgets(buffer, sizeof(buffer), stdin) == NULL) {
if (feof(stdin)) {
printf("End of file reached.\n");
} else if (ferror(stdin)) {
printf("Error reading input.\n");
}
} else {
printf("Input: %s", buffer);
}
4. Versatile Input Handling: The fgets() in C can be used to read text from both files and standard input. This versatility makes it a useful tool for various text-processing tasks.
5. Controlled Input Length: The n parameter specifies the maximum number of characters to read, including the null terminator. This allows you to control the size of the input and manage dynamic memory more effectively. For example-
char buffer[20];
if (fgets(buffer, sizeof(buffer), stdin)) {
printf("Input: %s", buffer); // Reads up to 19 characters plus the null terminator
}
Examples Of The fgets() Function In C
In this section, we will explore some simple C program examples to understand the working of fgets() function in C.
Reading From The Console Using fgets() In C
This method safely handles user input by reading up to n-1 characters into a buffer, preventing overflow. It includes the newline character and appends a null terminator, offering a secure alternative to the deprecated gets() function.
Code:
Output:
Enter a string: Hello user
The entered string is: Hello user
Explanation:
In the above code example-
- We start by declaring a character array/ string named str with a size of 30. This array will store the string input from the user.
- Next, using the printf() function, we display a message to the console prompting the user to input a string.
- We then use the fgets() function to read up to 29 characters (leaving space for the null terminator) from the user input and store them in the str array.
- The fgets() function will read the input until a newline is encountered, the end-of-file is reached, or the buffer is full.
- After taking the input, we use printf() to print the string the user entered. The %s format specifier is used to print the string stored in the str array.
- Finally, the main() function returns 0, indicating that the program has been executed successfully.
Reading From A File Using fgets() Function In C
In this method, the fgets() C function reads a specified number of characters from a file stream and stores them in a buffer. It includes the newline character if there is enough space in the buffer and appends a null terminator at the end.
Code:
Output (assuming "example.txt" contains the following text):
Hello, World!
This is a test file.
It contains multiple lines.
Explanation:
In the above code example-
- We first open a file named example.txt in read mode using the fopen() function. This function returns a pointer to a FILE structure, which we assign to the variable file.
- Next, we use an if-statement to check if the file was opened successfully by comparing the file pointer to NULL.
- If the file pointer is NULL, it means the file could not be opened, so we print an error message and return 1 to indicate that the program encountered an error.
- If the file pointer is not NULL, it means the file opened successfully, and we move to the next line in the program.
- Then, we declare an array of characters named buffer with a size of 100 to temporarily store each line of text read from the file.
- We then enter a while loop where we use the fgets() function to read lines of text from the file into the buffer:
- The fgets() function reads up to sizeof(buffer) - 1 characters i.e. 99 characters (leaving space for the null terminator) from the file into buffer, and stops if it encounters a newline character or the end of the file.
- The loop continues as long as fgets() successfully reads a line from the file.
- For each line read inside the loop, we print the line to the console using the printf() statement.
- After reading and printing all lines from the file, we close the file using the fclose() function to release the resources associated with the file.
Reading Multiple Lines With fgets() Function Using stdin In C
In this method, we use the fgets() C function to read multiple lines of text from standard input (using stdin) and store them in a buffer.
Code:
Output:
Enter multiple lines (CTRL+D to end):
Hello
You entered: Hello
World
You entered: World
Explanation:
In the above code example-
- We start by declaring a character array called buffer with a size of 100 bytes. This array will temporarily store the lines of text we read from the user.
- Then, we print a message prompting the user to enter multiple lines of text.
- In the message we inform the user that pressing CTRL+D command on their systems will signal the end of the input.
- Next, we enter a while loop where we repeatedly read lines of text from the standard input.
- The fgets() function reads up to 99 characters (leaving space for the null terminator) from stdin into buffer. It stops reading when it encounters a newline, end-of-file, or when the buffer is full.
- Inside the loop, we use printf() function to display each line of text the user has entered by printing the contents of the buffer.
- The loop continues to prompt the user for input until they signal the end of the input with CTRL+D command.
Reading The Complete File With fgets() Function & Loop In C
In this method, we open the file in read mode and use the fgets() function in C to read a specified number of characters from the file, storing them in a buffer. By placing fgets() inside a loop, we can continue reading lines until the end-of-file (EOF) is reached.
Code:
Output:
Line: (Content of the first line in example.txt)
Line: (Content of the second line in example.txt)
...
Explanation:
In the above code example-
- First, we open a file named example.txt in read mode using the fopen() function and store the file pointer in the variable file.
- We then use an if-else statement check if file is not NULL to ensure the file was opened correctly.
- If file is NULL, it means there was an error opening the file. In this case the else-block is executed printing an error message and skip to the end of the program.
- If the file opens successfully, then the if-block is executed. Inside, we create a character array named buffer with a size of 100 bytes to temporarily hold each line we read from the file.
- We then check if file is not NULL to confirm that the file was opened successfully. If the file is opened, we proceed to the next steps. Otherwise, we print an error message saying "Error opening file."
- Inside the if block, we declare a character array named buffer with a size of 100 bytes to temporarily store lines of text read from the file.
- Then, we enter a while loop where we use fgets() function to read lines of text from the file into the buffer.
- The fgets() function reads up to 99 characters (leaving space for the null terminator) from the file into buffer and stops reading when it encounters a newline, end-of-file, or when the buffer is full.
- Inside the loop, we use printf() statement to print each line stored in the buffer.
- Once we have finished reading all the lines from the file, we close the file using fclose() to free up system resources.
What Is The gets() Function In C?
Just like the fgets() function, gets() in C also reads a line of text from the standard input (usually the keyboard) into a buffer.
- Unlike fgets(), this function does not allow us to specify the max limit to the number of characters that can be read.
- So it reads characters until a newline character (\n) is encountered or the end of the file (EOF) is reached.
- Historically, gets() was used to read user input in C programs because it provided a simple way to read a line of text.
- However, it is no longer recommended for any purpose due to its security risks. Preference is given to alternative functions like fgets() that allow you to specify the maximum number of characters to read, thereby preventing buffer overflow issues.
Syntax:
char *gets(char *str);
Here, char *str is a pointer to the buffer where the input string will be stored.
Return Value:
- On Success: gets() returns the pointer to the string that was read.
- On Failure: gets() returns NULL. This occurs if there is an input error or if end-of-file (EOF) is reached without reading any characters.
Real-life Example:
Imagine a software application that takes user input for a chat system. The program uses gets() to accept messages from users. However, because gets() doesn't limit the number of characters that can be entered, a malicious can exploit this by sending an excessively long message, well beyond what the program's buffer can handle.
- Due to the lack of bounds checking in gets(), this oversized message will end up overflowing the buffer, overwriting adjacent memory.
- As a result, the malevolent user might be able to insert malicious code or obstruct the normal functioning of the application.
- Known by another name, buffer overflow attacks are of a kind that can lead to major security flaws, program failures, or the execution of arbitrary code by the attacker.
This illustrates the potential risk associated with using the gets() function. Hence, it is advised to use safer functions with bounds checking, like the fgets() function in C in order to reduce the chance of security breaches.
Example: Reading From The Console Using gets() Function In C
In this example, we will use gets() function in C to take input from the user and display it to the console.
Code:
Output:
Enter a string: Hello, World!
You entered: Hello, World!
Explanation:
In the above code example-
- We first declare a character array named buffer with a size of 100 to store the text we read from the user.
- Next, we use printf() to display a message prompting the user to enter a string.
- We then call gets(buffer) to read a line of text from the user.
- The gets() function reads a line of input from the standard input and stores it in the buffer array.
- Then, we use printf() to display the string that the user entered. The %s format specifier tells printf() to print the string stored in buffer.
- Finally, the main function returns 0 indicating that the program has been executed successfully.
Reading From A File Using gets() Function In C
In this section, we will discuss an example to illustrate how gets() in C is used to read from an input file.
Code:
Output (assuming "example.txt" contains the following text):
Hello, World!
Welcome to C programming.
This is an example of the gets function.
Explanation:
In the above code snippet-
- We first open a file named example.txt for reading.
- If the file opens successfully, we define a buffer to hold each line of text from the file.
- We then use the gets() function to read lines from the file one at a time and print each line to the console.
- After we’ve read and printed all the lines, we close the file and end the program.
Note:
Using gets() in C programs is unsafe because it does not check the size of the buffer. So, if the input line is longer than the buffer size, it will overflow the buffer, potentially overwriting other memory locations and causing security vulnerabilities or crashes.
It is advised to use the fgets() C function as it allows us to specify the maximum number of characters to read. This approach helps prevent buffer overflow as it ensures that we only read up to the buffer’s capacity.
Limitation Of The gets() Function In C
The gets() function has several significant limitations and risks that have led to its deprecation in modern C standards:
1. Buffer Overflow Vulnerability: The gets() in C does not perform any bounds checking on the size of the input it reads. This means if the user inputs more characters than the buffer can hold, it will write past the end of the buffer, leading to a buffer overflow. For example-
char buffer[10];
gets(buffer); // Unsafe, no bounds checking
2. No Error Handling: The gets() in C does not provide a way to handle errors during input. If gets() fails, it doesn't offer any feedback or mechanism for detecting errors. For example-
char buffer[100];
gets(buffer); // No error handling
3. No Control Over Input Size: With gets(), there’s no way to limit the amount of data being read from the input stream, leading to potential issues with large inputs.
4. Potential for Infinite Loops: If the gets() function in C encounters a situation where input never ends, it can cause an infinite loop. For example-
char buffer[100];
while (1) {
gets(buffer); // Potential for infinite loop
}
5. Not Thread-Safe: The gets() in C is not thread-safe. If multiple threads are attempting to read input using gets() simultaneously, it can result in race conditions and unexpected behavior.
6. No Portability: The use of gets() in C is not portable across different implementations of the language. Due to its deprecated status and known security risks, some compilers may issue warnings or errors when encountering its usage.
Differences Between scanf() And gets() Functions In C
When it comes to reading input in C, both scanf() and get() functions serve different purposes and come with distinct features. Here is a table highlighting some key differences between the two functions:
Feature |
The scanf() Function |
The gets() Function |
Input Source |
It reads input from standard input or specified stream. |
It reads input from standard input (usually keyboard). |
Function Type |
It is part of the standard input/output library. |
It is part of the standard input/output library. |
Syntax |
int scanf(const char *format, ...); |
char *gets(char *str); |
Buffer Overflow |
Safe with correct format specifiers. |
Highly susceptible to buffer overflow, lacks buffer size control. |
Input Format |
It allows formatted input with format specifiers. |
It reads input as a string until newline or EOF. |
Maximum Characters |
It allows you to specify the maximum number of characters to read using the width specifier. |
It does not allow explicit control over input size. |
Null Character |
It automatically appends a null character to the input string. |
It appends a null character to the input string. |
Error Handling |
It returns the number of successfully matched items or EOF in case of an error. |
It returns a null pointer (NULL) on error, with no detailed error information. |
Newline Handling |
It skips leading whitespace characters, and stops at the first whitespace character. |
It includes the newline character in the input, and terminates the string. |
Code Example For scanf() Function:
Output:
Enter your name: John
Enter your age: 25
Hello, John! You are 25 years old.
Explanation:
In the above code example-
- We first declare a character array name with a size of 50 bytes to store the user’s name. We also declare an integer variable age to store the user’s age.
- Next, we print a message using printf(), asking the user to input their name. We use the scanf() function to read the user’s name from the input and store it in the name array.
- We print another prompt asking the user to input their age. We use scanf() to read the user’s age and store it in the age variable.
- We then use the printf() statement to greet the user and display their name and age.
- Finally, the main function returns 0, indicating that the program has been executed successfully.
Conclusion
The gets() and fgets() C functions are used for reading input from a file or user, but they serve distinct purposes and come with different safety considerations. While gets() was once widely used in C programming language for its simplicity, its inability to prevent buffer overflow makes it unsafe and deprecated. On the other hand, fgets() offers a safer alternative by allowing us to specify buffer size, preventing overflow, and ensuring better control over input handling.
Understanding the differences between these functions is crucial for writing secure and efficient code in C. Always prefer fgets() over gets() to avoid potential security risks and ensure your code adheres to best practices.
Frequently Asked Questions
Q. What is the difference between gets() and puts() function?
The major difference between gets() and puts() function are as follows:
Feature |
The gets() Function |
The puts() Function |
Purpose |
Reads a line of text from standard input (deprecated). |
Writes a string to standard output. |
Input vs. Output |
Primarily used for input. |
Primarily used for output. |
Buffer Size |
Does not specify buffer size; dangerous as it can lead to overflow. |
No concept of buffer size; just prints the string. |
Error Handling |
Returns NULL on failure. |
Returns EOF on failure. |
Null Termination |
Adds a null terminator to the string read. |
Appends a newline character and then a null terminator. |
Q. Why is the gets() C function considered unsafe and deprecated?
The gets() function in C is considered unsafe and deprecated because it does not check the size of the input, which can lead to buffer overflows. This means if the input is larger than the buffer, it can overwrite adjacent memory, causing crashes or allowing attackers to exploit the program.
To prevent these issues, safer alternatives like fgets() are recommended, as they allow specifying the maximum number of characters to read, ensuring the buffer's size isn't exceeded. Due to these risks, gets() was removed from the C standard in 2011.
Q. What is the difference between fgets() and gets() functions in C?
The fgets() and gets() functions in C differ primarily in their input handling and security features. Here are the key differences between the two functions:
Feature |
The fgets() Function |
The gets() Function |
Buffer Overflow Vulnerability |
Allows specifying the maximum characters to read, preventing buffer overflow vulnerabilities. |
Highly susceptible to input buffer overflow, lacks buffer size control. |
Newline Character |
It includes the newline character in the buffer if there is enough space. |
it discards the newline character. |
Safety |
It is safer as it prevents buffer overflow by specifying the maximum number of characters to read. |
It is unsafe as it does not check for buffer overflow and can lead to security issues. |
Error Handling |
Returns a null pointer (NULL) on error or end-of-file. |
Lacks detailed error handling, may return NULL on error. |
Q. How does fgets() prevent buffer overflow compared to gets()?
The fgets() C function prevents buffer overflow by taking three arguments: the buffer to store the input, the maximum number of characters to read, and the input stream. It reads up to n-1 characters to ensure there is always space for the null terminator, thus protecting against overflow. For example,
char buffer[100];
fgets(buffer, sizeof(buffer), stdin);
// Reads up to 99 characters, leaving space for the null terminator
Q. What are the return values of gets() and fgets() C functions?
In C programming, the gets() and fgets() C functions are used for reading strings from the standard input stream, but they handle return values in different ways to indicate success or failure. The table below highlights their behavior on success and failure, respectively:
Function |
Return On Success |
Return On Failure |
gets() |
A pointer to the string containing the user’s input, excluding the newline character. |
NULL if it encounters EOF or an error during input. The function does not handle buffer overflow issues. |
fgets() |
A pointer to the string containing characters read from the file. Includes the newline character if the buffer has enough space. The string is null-terminated. |
NULL if it encounters EOF or an input error. Returns NULL if no characters are read (which can be due to EOF or no characters being available). |
You might also be interested in reading:
- Void Pointer In C | Referencing, Dereferencing & More (+Examples)
- Increment And Decrement Operators In C With Precedence (+Examples)
- Goto Statement in C Explained (With Examples)
- Decimal To Binary In C | 11 Methods (Examples + Complexity Analysis)
- Recursion In C | Components, Working, Types & More (+Examples)