I/O Operations in C
Learn console and file input/output in C - printf formatting, reading stdin, and working with FILE pointers using Docker-ready examples
Input and output are where a program meets the outside world. In C, all I/O lives in the standard library rather than the language itself - the <stdio.h> header (standard input/output) provides the functions you use to print to the screen, read what a user types, and read or write files on disk.
As a procedural systems language, C exposes I/O at a fairly low level. There is no automatic string handling or garbage collection cleaning up after you: you manage buffers yourself, you check whether a file actually opened, and you close what you open. Streams are represented by FILE pointers, and three of them - stdin, stdout, and stderr - are opened for you automatically when the program starts.
This tutorial covers formatted console output with printf, reading keyboard input safely, and reading and writing files with FILE pointers. Each example is self-contained and runs unchanged inside the official gcc:14 Docker image.
Formatted Output with printf
You already met printf in Hello World. Its real power is format specifiers - placeholders like %d and %f that control exactly how each value is rendered. This is the printf-style formatted output that dozens of later languages inherited from C.
Create a file named io_output.c:
| |
Each specifier maps to one argument, in order:
%d- a signed decimal integer.%#x- an integer in hexadecimal; the#flag adds the0xprefix.%.2f- a floating-point value with exactly two digits after the decimal point.%c- a single character.%s- a null-terminated string.%5d/%-5d- a field width of 5, right-aligned by default, left-aligned with-.%%- a literal percent sign (you cannot write a bare%).
Reading Input from stdin
To read what a user types, you read from stdin. The safest general-purpose approach is fgets, which reads a whole line into a fixed-size buffer and will never overflow it. fgets keeps the trailing newline, so we strip it. For numbers, scanf with a format specifier parses the text.
Create a file named io_input.c:
| |
A few C-specific details worth noting:
sizeof(name)passes the buffer’s capacity sofgetscannot write past the array - this is how you avoid buffer overflows.&agepasses the address ofage;scanfneeds a pointer so it can store the parsed value back into your variable.- Return values are your error handling.
fgetsreturnsNULLon failure andscanfreturns the number of items successfully read. Checking them is the idiomatic way to detect bad input in C. fprintf(stderr, ...)writes errors to the standard error stream instead ofstdout.
Reading and Writing Files
Files are handled through FILE pointers. You fopen a file with a mode string ("w" for write, "r" for read, "a" for append), work with it, and fclose it. fopen returns NULL if it fails - checking that is not optional in correct C code. The example below writes three lines to a file, then reopens it and reads them back.
Create a file named io_files.c:
| |
Key points:
fprintfworks exactly likeprintfbut writes to a stream you name - here the open file rather than the console.perrorprints your message followed by a human-readable description of the system error (for example,Permission denied).fgetsin a loop is the standard idiom for reading a file line by line; it returnsNULLat end-of-file, ending the loop.- Each line read already contains its newline, so the
printfformat string has no\nof its own.
Running with Docker
The gcc:14 image compiles and runs all three programs. For the input example we pipe text into the program’s stdin so it runs without interaction.
| |
Expected Output
Running io_output:
Integer: 42
Hexadecimal: 0x2a
Float (2 dp): 19.95
Character: A
String: codearchaeology
Padded number: | 42|
Left-aligned: |42 |
Percent sign: 100%
Running io_input with the piped input Ada and 42:
Enter your name: Enter your age: Hello, Ada! Next year you will be 43.
Running io_files (which also creates notes.txt in your directory):
1 | Line 1: C handles files with FILE pointers.
2 | Line 2: Always check the return of fopen.
3 | Line 3: Close files with fclose.
Key Concepts
- All I/O comes from
<stdio.h>- the language has no built-in I/O statements; you call library functions instead. - Three streams open automatically:
stdin(input),stdout(normal output), andstderr(error output). Sending errors tostderrkeeps them separate from a program’s real output. - Format specifiers control rendering -
%d,%f,%s,%c,%x, plus width, precision, and alignment flags like%.2fand%-5d. - Prefer
fgetsovergets-fgetstakes a buffer size and cannot overflow; the oldgetsfunction is unsafe and was removed from the standard. scanfneeds addresses - pass&variableso the function can write the parsed value back to you.- Check every return value -
fopenreturnsNULL,scanfreturns a count, andfgetsreturnsNULLat end-of-file or error. In C, these return values are your error handling. - Open, use, close - every
fopenshould be paired with anfclose; C will not clean up open file handles for you.
Comments
Loading comments...
Leave a Comment