Scanf vs gets vs fgets in C: Key Differences and Usage
scanf reads formatted input but can leave newline characters in the buffer, gets reads a line but is unsafe and deprecated, while fgets safely reads a line with buffer size control and includes the newline character. Use fgets for safer input handling over gets and scanf when reading strings.Quick Comparison
Here is a quick comparison of scanf, gets, and fgets based on key factors.
| Feature | scanf | gets | fgets |
|---|---|---|---|
| Input Type | Formatted input (e.g., %s, %d) | String input (line) | String input (line) |
| Buffer Overflow Protection | No (can overflow if not limited) | No (unsafe, deprecated) | Yes (limits input size) |
| Reads Newline Character | No (stops at whitespace) | No (newline discarded) | Yes (newline included if fits) |
| Safety | Moderate (needs format control) | Unsafe (deprecated) | Safe (recommended) |
| Use Case | Reading formatted data | Legacy line input | Safe line input with size limit |
Key Differences
scanf reads input according to a format specifier, such as %s for strings or %d for integers. It stops reading strings at the first whitespace and does not consume the newline character, which can cause issues for subsequent input calls.
gets reads an entire line until a newline but does not check the buffer size, making it unsafe and deprecated because it can cause buffer overflows and security risks.
fgets reads a line from a stream safely by specifying the maximum number of characters to read, including the newline character if it fits. It prevents buffer overflow and is the recommended way to read strings line-by-line in modern C programming.
Code Comparison
Example reading a string input using scanf:
#include <stdio.h> int main() { char name[20]; printf("Enter your name: "); scanf("%19s", name); // limit input to avoid overflow printf("Hello, %s!\n", name); return 0; }
fgets Equivalent
Example reading a string input using fgets safely:
#include <stdio.h> #include <string.h> int main() { char name[20]; printf("Enter your name: "); if (fgets(name, sizeof(name), stdin)) { // Remove newline if present size_t len = strlen(name); if (len > 0 && name[len - 1] == '\n') { name[len - 1] = '\0'; } printf("Hello, %s!\n", name); } return 0; }
When to Use Which
Choose scanf when you need to read formatted input like numbers or strings without spaces and you can control the format carefully. Avoid it for reading full lines because it stops at whitespace and leaves newlines in the buffer.
Never use gets because it is unsafe and removed from modern C standards.
Use fgets when you want to read a full line safely, especially strings that may contain spaces, and want to avoid buffer overflow risks. It is the safest and most reliable choice for line input.