C Notes
Learn string I/O with gets() and puts() in C. Understand why gets() is dangerous and deprecated, buffer overflow vulnerabilities, and safer alternatives like fgets(). Includes practical examples.
The gets() and puts() functions handle string input and output in C. While puts() remains a perfectly valid and useful function, gets() has become one of the most infamous functions in C's history — it was officially removed from the C11 standard because it's inherently unsafe and has been responsible for countless security vulnerabilities. Understanding why it's dangerous and what to use instead is essential knowledge for any C programmer.
puts() — Print a String with Newline
puts() writes a string to standard output and automatically appends a newline character. It's simpler and slightly faster than printf("%s\n", str) for plain string output.
int puts(const char *str);Returns a non-negative value on success, or EOF on error.
#include <stdio.h>
int main() {
// Simple string output
puts("Hello, World!");
puts("This is C programming.");
// With variables
char name[] = "Alice";
char greeting[] = "Welcome to the course!";
puts(name);
puts(greeting);
// Empty string just prints a newline
puts("");
puts("Done!");
return 0;
}Hello, World! This is C programming. Alice Welcome to the course! Done!
puts() vs printf() for Strings
#include <stdio.h>
int main() {
char msg[] = "Hello";
// puts() adds newline automatically
puts(msg);
// printf() does NOT add newline
printf("%s", msg);
printf("\n");
// printf() can do formatting; puts() cannot
printf("Name: %s, Age: %d\n", "Bob", 25);
// puts() is slightly faster for plain strings (no format parsing)
puts("Just a plain string");
return 0;
}Hello Hello Name: Bob, Age: 25 Just a plain string
When to use puts():
- Printing a complete string on its own line
- No formatting needed (no variables mixed in)
- Slightly better performance for simple output
gets() — The Dangerous Function
gets() reads a line from standard input (until newline or EOF) and stores it in a buffer. The newline is replaced with a null terminator.
char *gets(char *str); // DEPRECATED AND REMOVED IN C11!Why gets() is Dangerous
The fatal flaw: gets() has no way to limit input length. If the user enters more characters than the buffer can hold, it overflows into adjacent memory — corrupting data, crashing the program, or enabling code injection attacks.
If the user enters "This is a very long string that exceeds the buffer", gets() will happily write past the 10-byte buffer, corrupting the stack. This is the classic buffer overflow vulnerability that attackers exploit.
The Morris Worm (1988)
The first major Internet worm exploited a gets() buffer overflow in the fingerd daemon. This historical event highlighted just how dangerous gets() is and eventually led to its removal from the C standard.
fgets() — The Safe Alternative
fgets() is what you should always use instead of gets(). It takes a size parameter that prevents buffer overflow:
char *fgets(char *str, int n, FILE *stream);- Reads at most
n-1characters (saves space for null terminator) - Stops at newline (which IS stored in the string, unlike
gets()) - Returns
NULLon error or end-of-file
Enter your full name: John Smith Enter your city: New York Name: John Smith, City: New York
The Newline Issue with fgets()
Unlike gets(), fgets() keeps the newline in the string. You usually want to remove it:
Enter text: Hello World With newline: [Hello World ] Length: 12 Without newline: [Hello World] Length: 11
Other Ways to Remove the Newline
Comparison: gets() vs fgets() vs scanf()
| Feature | gets() | fgets() | scanf("%s") |
|---|---|---|---|
| Buffer overflow protection | ❌ No | ✅ Yes | ⚠️ With width |
| Reads spaces | ✅ Yes | ✅ Yes | ❌ No |
| Stores newline | ❌ No | ✅ Yes | ❌ No |
| Standard in C11 | ❌ Removed | ✅ Yes | ✅ Yes |
| Input source | stdin only | Any FILE* | stdin only |
| Safety | Dangerous | Safe | Moderate |
scanf (enter 'Hello World'): Hello World scanf got: [Hello] fgets (enter 'Hello World'): Hello World fgets got: [Hello World]
Practical Examples with puts() and fgets()
Reading and Displaying Multiple Lines
Enter up to 5 lines (empty line to stop): 1> Hello World 2> C Programming 3> Is Fun You entered: Hello World C Programming Is Fun
Simple Text Reversal
Enter a sentence: Hello World Reversed: dlroW olleH
Password Input (Masking with fgets)
=== Login System === Username: admin Password: secret Access granted! Welcome, admin.
Compiler Warnings for gets()
Modern compilers will warn you (or refuse to compile) when you use gets():
warning: the `gets' function is dangerous and should not be used.GCC with -Wall flag will always warn about gets(). Some compilers define gets() as an error in C11 mode.
Interview Questions
Q1: Why was gets() removed from the C11 standard?
gets() was removed because it's inherently unsafe — there's no way to specify buffer size, making buffer overflow inevitable when user input exceeds the buffer. This has led to countless security vulnerabilities including the Morris Worm of 1988. It was deprecated in C99 and officially removed in C11.
Q2: What is the difference between gets() and fgets()?
Three key differences: (1) fgets() takes a size parameter preventing overflow; gets() does not. (2) fgets() retains the newline character in the string; gets() strips it. (3) fgets() can read from any file stream; gets() only reads from stdin.
Q3: Why does fgets() store the newline character?
fgets() keeps the newline so you can distinguish between a line that was fully read (has \n) and a line that was truncated because it exceeded the buffer size (no \n). If the newline is absent, you know more characters remain unread.
Q4: What is the difference between puts() and printf() for string output?
puts() automatically appends a newline and doesn't parse format specifiers — it just outputs the raw string. printf() requires \n explicitly and parses format specifiers (%d, %s, etc.). puts() is slightly faster for plain strings because there's no format string parsing overhead.
Q5: How do you safely remove the newline from fgets() input?
The safest method is: buffer[strcspn(buffer, "\n")] = '\0'; — strcspn() finds the position of the first \n (or returns the string length if none exists), then you replace it with a null terminator. This works correctly even if no newline is present.
Summary
puts()prints a string and adds a newline — simple and fast for string outputgets()is removed from C11 due to buffer overflow vulnerability — never use itfgets()is the safe replacement: it limits input length and works with any file streamfgets()keeps the newline — remove it withstrcspn()orstrlen()method- Always use
sizeof(buffer)withfgets()for automatic size calculation scanf("%s")doesn't read spaces;fgets()reads the entire line including spaces- Modern compilers will warn or error when you try to use
gets()
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for gets() and puts() in C Programming.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this C Programming topic.
Search Terms
c-programming, c programming, programming, input, output, gets, and, puts
Related C Programming Topics