<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.
Fundamentals
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.
Foundation
📝 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)
#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.
Cheat Sheet
⚡ Quick Reference
Function
Stream
Purpose
printf
stdout
Print formatted text
scanf
stdin
Read formatted input
fopen
file
Open; returns FILE *
fprintf
any FILE *
Print to file or stderr
fgets
any FILE *
Read one line (safe buffer)
fclose
any 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
Hands-On
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;
}
📤 Output (user types 36):
Enter an integer: 36
You entered: 36
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;
}
📤 Output:
Wrote example.txt successfully.
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;
}
📤 Output (after Example 2):
Contents of example.txt:
Hello, World!
Line two from stdio.h demo.
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.
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;
}
📤 Output (user types Ada):
Your name: Ada
Hello, Ada
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.
Applications
🚀 Common Use Cases
Console programs — menus, quizzes, calculators with printf/scanf.
Log files — fprintf 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 files — fread/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.
Important
📝 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.
Performance
⚡ 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.
Wrap Up
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).
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.