C
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Arrays and Strings
-
Section 5: Pointers
-
Section 6: Memory Management
-
Section 7: Structures and Unions
-
Section 8: The Preprocessor and Build Process
-
Section 9: Standard Library: stdio.h
-
Section 10: Standard Library: stdlib.h
-
Section 11: Standard Library: string.h
-
Section 12: Standard Library: ctype.h and wctype.h
-
Section 13: Standard Library: math.h, complex.h, fenv.h, tgmath.h
-
Section 14: Standard Library: Type and Limit Headers
-
Section 15: Standard Library: Error Handling and Debugging
-
Section 16: Standard Library: Localization and Encoding
-
Section 17: Standard Library: time.h
-
Section 18: Standard Library: Concurrency (C11)
-
Section 19: POSIX and System Programming (unistd.h)
-
Section 20: More Data Structures
-
Section 21: Algorithms in C
-
Section 22: Bitwise Operations
-
Section 23: Command-Line Programs
-
Section 24: Debugging and Best Practices
-
Section 25: Compiler and Language Internals
-
Section 26: Embedded and Cross-Platform Considerations
-
Section 27: Networking Basics
-
Section 28: Practical Projects
-
Section 29: Interview Practice
-
Section 30: C23 Modern Features
-
Section 31: More Practice and Review
81: Line I/O: fgets and fputs
I want to start with a snippet of code that looks perfectly fine at a glance. You've probably written something like this recently: you want to get a string from the user, and you're using fgets because you know it's safer than the dreaded gets.
#include <stdio.h>
int main() {
char name[50];
printf("Enter your name: ");
fgets(name, 50, stdin);
printf("Hello, %s! Welcome to the system.", name);
return 0;
}
If you run this and type "Alice", you'd expect it to print Hello, Alice! Welcome to the system. Instead, you get this:
Hello, Alice
! Welcome to the system.
That awkward line break is a classic "gotcha" in C. It feels like a bug in the library, but it's actually fgets doing exactly what it was designed to do.
The "Ghost Newline" in your buffer
Here is the deal: fgets reads characters from the stream until it encounters a newline character (\n), reaches the size limit you provided, or hits the end of the file. The catch? If it finds that newline character, it stores it inside your string before appending the null terminator.
In the example above, when you pressed Enter, fgets grabbed the 'A', 'l', 'i', 'c', 'e', and the '\n'. So your name array actually contains "Alice\n\0". When you print it, the \n triggers a line feed, pushing the rest of your greeting to the next line.
Stripping the trailing newline
To fix this, we need to find that newline and replace it with a null terminator (\0), effectively cutting the string short. I usually use strcspn from string.h for this because it's concise and handles cases where the newline might not even be there (like if the user entered more characters than the buffer could hold).
#include <stdio.h>
#include <string.h>
int main() {
char name[50];
printf("Enter your name: ");
if (fgets(name, sizeof(name), stdin)) {
// Find the index of the first '\n' and replace it with '\0'
name[strcspn(name, "\n")] = '\0';
}
printf("Hello, %s! Welcome to the system.", name);
return 0;
}
The strcspn function returns the length of the initial segment of name that consists entirely of characters not in "\n". If the newline is at index 5, strcspn returns 5, and we just set name[5] = '\0'. Clean and simple.
Writing lines back with fputs
While we've spent a lot of time on fgets, fputs is its sibling. Unlike printf, which parses a format string and can be slow or dangerous if used incorrectly with user input, fputs just dumps a string directly to a file stream.
One thing to remember: fputs does not automatically add a newline at the end. If you want a new line in your output file or console, you have to include it in the string or write it separately.
FILE *fp = fopen("log.txt", "w");
if (fp != NULL) {
fputs("Log Entry: User Alice logged in.\n", fp);
fputs("Status: Success\n", fp);
fclose(fp);
}
I prefer fputs over fprintf when I don't need formatting. It's more explicit and slightly more efficient. Use it whenever you're just moving a block of text from a variable to a file.
📋 Practical Task
The Guestbook Entry Formatter
Build a program that acts as a simple guestbook. The program should:
- Prompt the user for their name and their favorite hobby (use
fgets). - Clean both input strings to remove the trailing newline characters.
- Format these inputs into a single descriptive sentence (e.g., "Alice enjoys hiking.").
- Write this formatted sentence into a file named
guestbook.txtusingfputs, ensuring each entry starts on a new line. - Close the file and print a confirmation message to the console.
There are no comments for now.