C fgets function
last modified April 6, 2025
The fgets
function is a fundamental tool in C programming for safe
line input from files or standard input. Unlike gets
, it prevents
buffer overflows by limiting input size. This tutorial explores fgets
in depth, covering its parameters, return values, and practical applications.
Mastering fgets
ensures robust input handling in your C programs.
What Is fgets?
The fgets
function reads a line from a specified stream and stores
it in a buffer. It takes three parameters: the buffer to store the input, the
maximum number of characters to read, and the input stream. Unlike
gets
, it includes the newline character in the buffer and always
null-terminates the string. fgets
returns the buffer pointer on
success or NULL
on error or end-of-file.
Basic fgets Syntax
The function prototype for fgets
is:
char *fgets(char *str, int n, FILE *stream);
str
is the destination buffer, n
is the maximum
characters to read (including null terminator), and stream
is the
input source. The function reads until it encounters a newline, EOF, or has read
n-1 characters. The resulting string is always null-terminated.
Reading from Standard Input
This example demonstrates using fgets
to read user input from the
keyboard (stdin).
#include <stdio.h> int main() { char name[50]; printf("Enter your name: "); fgets(name, sizeof(name), stdin); // Safe input with size limit printf("Hello, %s", name); return 0; }
Here, fgets
reads from stdin
into the name
buffer, with a maximum of 49 characters (plus null terminator). Unlike
scanf
, it safely handles spaces in input. The newline character is
included in the buffer if present in the input.
Reading from a File
This example shows how to read a file line by line using fgets
.
#include <stdio.h> int main() { FILE *fp; char line[100]; fp = fopen("data.txt", "r"); if (fp == NULL) { perror("Error opening file"); return 1; } while (fgets(line, sizeof(line), fp) != NULL) { printf("%s", line); // Print each line } fclose(fp); return 0; }
The program opens "data.txt" and reads it line by line. fgets
returns NULL
when it reaches end-of-file or encounters an error.
Each line is printed as read, preserving the original formatting including
newlines. The buffer size (100) determines the maximum line length that can be
read safely.
Handling Long Lines
This example demonstrates how to handle lines longer than the buffer size.
#include <stdio.h> #include <string.h> int main() { char buffer[10]; int complete = 0; while (!complete) { fgets(buffer, sizeof(buffer), stdin); // Check if line was fully read if (strchr(buffer, '\n') != NULL) { complete = 1; } printf("Partial: %s", buffer); } return 0; }
When a line exceeds the buffer size, fgets
reads only part of it.
This code checks for newline characters to detect complete lines. The loop
continues until a newline is found, processing long input in chunks. This
technique is useful when memory is limited or for very long lines.
Removing the Newline Character
This example shows how to remove the trailing newline that fgets
includes in its output.
#include <stdio.h> #include <string.h> int main() { char input[50]; printf("Enter text: "); fgets(input, sizeof(input), stdin); // Remove trailing newline if present input[strcspn(input, "\n")] = '\0'; printf("You entered: '%s'\n", input); return 0; }
The strcspn
function finds the first newline character and replaces
it with a null terminator. This creates a cleaner string without the newline.
This technique is especially useful when comparing strings or storing user input.
Note that if the input was truncated, there may be no newline to remove.
Comparing fgets with Other Input Functions
This example contrasts fgets
with scanf
and
gets
.
#include <stdio.h> int main() { char buffer1[20]; char buffer2[20]; char buffer3[20]; // Unsafe gets (deprecated) printf("Enter text (gets): "); gets(buffer1); // Dangerous - no bounds checking // scanf with %s (stops at whitespace) printf("Enter text (scanf): "); scanf("%19s", buffer2); // Limited protection // Safe fgets printf("Enter text (fgets): "); fgets(buffer3, sizeof(buffer3), stdin); printf("\ngets: %s\n", buffer1); printf("scanf: %s\n", buffer2); printf("fgets: %s\n", buffer3); return 0; }
gets
is dangerous as it doesn't limit input size. scanf
with %s
is safer but stops at whitespace. fgets
is the
safest option, reading entire lines with size limits. This comparison highlights
why fgets
is preferred for robust input handling in modern C code.
Reading Multiple Lines
This example demonstrates reading multiple lines until a blank line is entered.
#include <stdio.h> #include <string.h> int main() { char line[100]; printf("Enter lines (blank to quit):\n"); while (1) { fgets(line, sizeof(line), stdin); // Check for blank line (just newline) if (strcmp(line, "\n") == 0) { break; } printf("You entered: %s", line); } printf("Goodbye!\n"); return 0; }
The program continues reading lines until it encounters a blank line (just a newline character). Each line is processed as it's entered. This pattern is common in interactive programs that need to accept multiple lines of input. The blank line serves as a simple but effective termination condition.
Error Handling with fgets
This example shows proper error handling when using fgets
.
#include <stdio.h> #include <errno.h> #include <string.h> int main() { FILE *fp; char line[100]; fp = fopen("nonexistent.txt", "r"); if (fp == NULL) { fprintf(stderr, "Error %d: %s\n", errno, strerror(errno)); return 1; } if (fgets(line, sizeof(line), fp) == NULL) { if (feof(fp)) { printf("Reached end of file\n"); } else { perror("Error reading file"); } } else { printf("First line: %s", line); } fclose(fp); return 0; }
This code demonstrates comprehensive error handling. It checks for file opening
errors and distinguishes between end-of-file and other read errors. The
feof
function tests for end-of-file condition explicitly. Proper
error handling makes programs more robust and easier to debug when problems
occur.
Best Practices for Using fgets
- Always specify buffer size: Prevent buffer overflows by using sizeof(buffer) or a constant.
- Check return value: Verify fgets didn't return NULL before using the buffer.
- Handle the newline: Use strcspn or similar to remove trailing newline if needed.
- Clear stdin when needed: After fgets, use while(getchar()!='\n'); to clear extra input.
- Combine with sscanf: For parsing, use fgets followed by sscanf for safer input processing.
Source
This tutorial has explored the fgets
function in depth, from basic
usage to advanced techniques. By following these examples and best practices,
you can implement safe and reliable input handling in your C programs.
Author
List C Standard Library.