C Standard Library stdio.h

Beginner
⏱️ 14 min read
📚 Updated: Jul 2026
🎯 5 Examples
<stdio.h>

What You’ll Learn

<stdio.h> (Standard Input/Output) is the first header most beginners meet. It powers printf and scanf for console I/O, plus fopen, fprintf, and fgets for files. Every C program that talks to the user or reads data from disk relies on it.

01

printf

Print text.

02

scanf

Read input.

03

fopen

Open files.

04

FILE*

Stream handle.

05

EOF

End of file.

06

perror

Error messages.

Definition and Usage

stdio.h declares functions and types for formatted and unformatted I/O. A FILE * represents an open stream—a file on disk, or the predefined streams stdin (input), stdout (output), and stderr (errors).

Console programs use printf/scanf with stdout and stdin. File programs call fopen to get a FILE *, read or write with fgets, fprintf, fread, etc., then fclose to release resources.

💡
Beginner Tip

Always check whether fopen returned NULL before using the pointer. Always call fclose on success. For interactive prompts without a trailing newline, call fflush(stdout) before scanf so the user sees the prompt immediately.

📝 Syntax

Include the header:

C
#include <stdio.h>

Common console functions

  • printf(format, ...) — formatted output to stdout
  • scanf(format, ...) — formatted input from stdin
  • getchar() / putchar(c) — single character I/O
  • puts(s) / fgets(buf, n, stream) — line-oriented strings
  • snprintf(buf, size, format, ...) — safe formatted string (C99)

Common file functions

  • fopen(path, mode) — open file; modes: "r", "w", "a", "rb", etc.
  • fclose(stream) — close an open stream
  • fprintf(stream, format, ...) — formatted write to any stream
  • fscanf(stream, format, ...) — formatted read from a stream
  • fgets(buf, n, stream) / fputs(s, stream) — line I/O
  • fread / fwrite — binary block I/O
  • fflush(stream) — push buffered output out

Error and status helpers

  • perror(msg) — print message + system error (uses errno)
  • feof(stream) / ferror(stream) / clearerr(stream)

Important macros and streams

C
FILE *fp;
stdin, stdout, stderr   /* predefined streams */
EOF                     /* end-of-input indicator */
NULL                    /* null pointer (also in stddef.h) */
FOPEN_MAX, FILENAME_MAX /* implementation limits */

Headers and linking

  • #include <stdio.h> — part of the C standard library; linked automatically.
  • perror works with errno from <errno.h> (often included indirectly).
  • Compile: gcc program.c -std=c11 -o program.

⚡ Quick Reference

FunctionStreamPurpose
printfstdoutPrint formatted text
scanfstdinRead formatted input
fopenfileOpen; returns FILE *
fprintfany FILE *Print to file or stderr
fgetsany FILE *Read one line (safe buffer)
fcloseany FILE *Close and flush
Print
printf("%d\n", n);

Integer

Scan
scanf("%d", &x);

Need &

Open
fopen("a.txt","r")

Check NULL

Close
fclose(fp);

Always

Examples Gallery

Compile with gcc file.c -std=c11 -o out. File examples create or read example.txt in the current directory.

📚 Getting Started

Console I/O and basic file operations from the reference.

Example 1 — printf and scanf

Read an integer from the keyboard and print it back.

C
#include <stdio.h>

int main(void) {
    int num;

    printf("Enter an integer: ");
    fflush(stdout);
    if (scanf("%d", &num) != 1) {
        fprintf(stderr, "Invalid input.\n");
        return 1;
    }
    printf("You entered: %d\n", num);

    return 0;
}

How It Works

scanf("%d", &num) needs the address of num. scanf returns the number of items successfully read—checking the return value avoids silent failures. fflush(stdout) ensures the prompt appears before input on systems that buffer stdout.

Example 2 — Writing to a File with fprintf

Create (or overwrite) example.txt and write a line.

C
#include <stdio.h>

int main(void) {
    FILE *file = fopen("example.txt", "w");

    if (file == NULL) {
        perror("Error opening file for write");
        return 1;
    }

    fprintf(file, "Hello, World!\n");
    fprintf(file, "Line two from stdio.h demo.\n");

    if (fclose(file) != 0) {
        perror("Error closing file");
        return 1;
    }

    printf("Wrote example.txt successfully.\n");
    return 0;
}

How It Works

fopen("example.txt", "w") opens for writing (creates or truncates). fprintf is like printf but writes to the file stream. fclose flushes buffers and releases the handle. Mode "a" appends instead of overwriting.

📈 Practical Patterns

Reading files, errors, and buffered output.

Example 3 — Reading a File with fgets

Read example.txt line by line (run Example 2 first, or create the file manually).

C
#include <stdio.h>

int main(void) {
    FILE *file = fopen("example.txt", "r");
    char buffer[100];

    if (file == NULL) {
        perror("Error opening file for read");
        return 1;
    }

    printf("Contents of example.txt:\n");
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }

    if (ferror(file)) {
        perror("Error while reading");
        fclose(file);
        return 1;
    }

    fclose(file);
    return 0;
}

How It Works

fgets reads up to sizeof(buffer) - 1 characters and stores a null terminator. It keeps the newline if the line fits. The loop ends when fgets returns NULL at EOF or on error—use feof/ferror to tell them apart.

Example 4 — perror for File Errors

Try to open a file that does not exist and print a helpful message.

C
#include <stdio.h>

int main(void) {
    FILE *file = fopen("nonexistent.txt", "r");

    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    fclose(file);
    return 0;
}

How It Works

When fopen fails, it sets errno and returns NULL. perror prints your label plus the system message. Write errors to stderr with fprintf(stderr, ...) so they stay separate from normal program output.

Example 5 — fflush and snprintf

Flush a prompt immediately; build a string safely with snprintf.

C
#include <stdio.h>

int main(void) {
    char name[32];
    char greeting[64];
    int n;

    printf("Your name: ");
    fflush(stdout);

    if (fgets(name, sizeof(name), stdin) == NULL) {
        return 1;
    }

    n = snprintf(greeting, sizeof(greeting),
                 "Hello, %s", name);

    if (n < 0 || (size_t)n >= sizeof(greeting)) {
        fprintf(stderr, "Greeting truncated.\n");
    }

    fputs(greeting, stdout);
    return 0;
}

How It Works

fgets is safer than scanf("%s") for names because it limits how many characters are read. snprintf never writes past sizeof(greeting)—prefer it over sprintf for buffer safety. The return value tells you if the result was truncated.

🚀 Common Use Cases

  • Console programs — menus, quizzes, calculators with printf/scanf.
  • Log filesfprintf to append timestamps and messages.
  • Config files — read key/value lines with fgets and parse.
  • Data import/export — CSV or text reports written with fprintf.
  • Debugging — quick traces to stderr without mixing into stdout.
  • Binary filesfread/fwrite for images, structs, or archives.

🧠 How stdio.h I/O Works

1

Open a stream

Use stdin/stdout or fopen for files.

Setup
2

Buffered read/write

Library batches bytes for efficiency; fflush pushes them out.

Buffer
3

Check errors

NULL from fopen, return values from scanf, ferror.

Safety
=

Reliable I/O

Data reaches the screen, file, or next stage of your program.

📝 Notes

  • scanf("%s") has no length limit—use scanf("%31s", buf) or fgets instead.
  • Always match printf format specifiers to argument types (%d for int, %zu for size_t, etc.).
  • fopen mode "w" destroys existing file contents; use "a" to append.
  • Text mode ("r"/"w") may translate newlines on Windows; "rb"/"wb" for exact bytes.
  • EOF is not a character stored in files—it is a return value from read functions.
  • Close every fopen with fclose; leaking FILE * handles wastes resources.

⚡ Optimization

stdio buffering reduces system calls—avoid calling fflush more than needed. For large binary transfers, fread/fwrite with a reasonably sized buffer (e.g. 4096 or 8192 bytes) beats byte-by-byte fgetc. For heavy formatted logging, consider writing plain text with fputs or batching fprintf calls.

Conclusion

<stdio.h> is the gateway to human-readable input and output in C. Master printf, scanf, fopen, fclose, and fprintf first, then add fgets, perror, and snprintf for safer, more robust programs.

Check return values, close your files, and separate normal output (stdout) from errors (stderr).

💡 Best Practices

✅ Do

  • Check fopen for NULL
  • Call fclose on every successful open
  • Use fgets or width-limited scanf for strings
  • Check scanf return value
  • Use snprintf instead of sprintf
  • Print errors to stderr

❌ Don’t

  • Forget & on scanf for non-pointer types
  • Use scanf("%s") without a field width
  • Ignore ferror after fgets returns NULL
  • Mix binary and text modes carelessly on Windows
  • Assume printf flushes before scanf without \n

Key Takeaways

Knowledge Unlocked

Five things to remember about stdio.h

Input, output, and files in C.

5
Core concepts
📚 02

fopen

FILE *.

Files
📈 03

fgets

Safe lines.

Read
📄 04

perror

errno msg.

Errors
🌐 05

fclose

Always.

Cleanup

❓ Frequently Asked Questions

stdio.h is the Standard Input/Output header. It declares printf, scanf, fopen, fclose, fprintf, fgets, and related functions for reading and writing text to the console, files, and standard streams stdin, stdout, and stderr. It also defines FILE, EOF, and common I/O macros.
printf writes formatted text to stdout (the screen by default). fprintf takes a FILE pointer as its first argument, so you can write to a file or any stream: fprintf(file, "%d\n", n) or fprintf(stderr, "error\n").
scanf stores values into variables you pass. It needs their memory addresses. For int x, you write scanf("%d", &x). Without &, scanf would get the value of x instead of where to write—undefined behavior. Exception: arrays and strings decay to pointers, so scanf("%s", name) does not need & on the array name.
EOF is a macro (usually -1) meaning end-of-file or end-of-input. Functions like fgetc, fgets, and fread return EOF or NULL when no more data is available. Do not compare char values to EOF using char type—use int for fgetc results.
perror prints a message you supply, then a colon, then a system error message based on the global errno variable. Call it after a failed fopen or similar call. errno is set by many library functions on failure; perror helps beginners see why fopen failed.
fflush forces buffered output to be written immediately. stdout is often line-buffered when connected to a terminal, so printf usually flushes on newline. Call fflush(stdout) when you need a prompt visible before scanf without a newline, or fflush(file) before relying on data being on disk.
Did you know?

stdout is typically line-buffered when connected to a terminal (output appears when you print a newline) but fully buffered when redirected to a file. That is why prompts before scanf sometimes need fflush(stdout) even though printf feels instant after \n.

Explore C Standard Library Headers

Continue with stdlib.h or browse the library index.

Standard Library Index →

About the author

Mari Selvan M P
Mari Selvan M P 🔗

Developer, cloud engineer, and technical writer

  • Experience 12 years building web and cloud systems
  • Focus Full Stack Development, AWS, and Developer Education

I write practical tutorials so students and working developers can learn by doing—from databases and APIs to deployment on AWS.

5 people found this page helpful