Skip to Content
Course content

81: Line I/O: fgets and fputs

Click on the "Edit" button in the top corner of the screen to edit your slide content.

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.txt using fputs, ensuring each entry starts on a new line.
  • Close the file and print a confirmation message to the console.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.