Chapter 3 — Standard I/O
How C reads from the keyboard and writes to the screen. `printf` formats output; `scanf` parses input.
What you'll learn
- 1Pick the right `printf` format specifier.
- 2Use `scanf` to read int / double / multiple values.
- 3Understand why `scanf` is risky and what to do instead.
- 4Format numbers with width, precision, and padding.
Core Concepts
1) `printf` format specifiers
| Type | Specifier | Example |
|---|---|---|
| int | `%d` | `printf("%d", 42)` |
| double | `%f` | `printf("%.2f", 3.14)` |
| char | `%c` | `printf("%c", 'A')` |
| string | `%s` | `printf("%s", "hi")` |
| pointer | `%p` | `printf("%p", &x)` |
| size_t | `%zu` | `printf("%zu", sizeof(int))` |
| hex | `%x` / `%X` | `printf("%x", 255)` → ff |
| percent | `%%` | `printf("100%%")` |
2) Width and precision
printf("|%5d|\n", 42); // | 42| width=5, right-aligned
printf("|%-5d|\n", 42); // |42 | left-aligned
printf("|%.3f|\n", 3.14); // |3.140| 3 decimal places
printf("|%8.2f|\n", 3.14); // | 3.14| width=8, precision=23) `scanf` basics
int n;
scanf("%d", &n); // ← note the &`scanf` needs **addresses** (pointers). Forgetting `&` is the classic crash.
4) Multiple values, one call
int a, b;
scanf("%d %d", &a, &b); // whitespace = any spaces/newlines5) Why `scanf` is dangerous
For strings, `scanf("%s", buf)` doesn't check length and overflows. Prefer `fgets` (chapter 4 — strings).
Examples
Example 1 — `ex01_printf.c`: format with width/precision
printf("%d\n", 42);
printf("%.3f\n", 3.14159);
printf("%-10s|%10s\n", "left", "right");**Output**
42
3.142
left | rightKey: minus sign means left-align; `.N` is decimal places (or max chars for `%s`).
Example 2 — `ex02_scanf_int.c`: read a single integer
int n;
printf("Number? ");
scanf("%d", &n);
printf("Square = %d\n", n * n);**Output**
Number? 7
Square = 49Key: don't forget the `&` before `n`.
Example 3 — `ex03_scanf_multi.c`: read two integers
int a, b;
scanf("%d %d", &a, &b);
printf("Sum = %d\n", a + b);**Output**
3 4
Sum = 7Key: whitespace in the format matches any sequence of spaces/newlines.
Example 4 — `ex04_format.c`: floating-point precision
double pi = 3.14159265358979;
printf("%.2f\n", pi);
printf("%.5f\n", pi);
printf("%e\n", pi);**Output**
3.14
3.14159
3.141593e+00Key: `%e` is scientific notation; great for very large/small numbers.
Common mistakes
- **Missing `&` in `scanf`** — undefined behavior or instant crash.
- **Wrong specifier in `scanf`** — `%lf` for double in scanf, but `%f` in printf for double too.
- **`scanf("%s")` on user input** — buffer overflow waiting to happen.
- **No `\n` in printf** — output may not flush until program exits.
Recap
- Match the format specifier to the value's type.
- `scanf` wants addresses (`&var`); `printf` wants values.
- For strings prefer `fgets`; for production use `strtol/strtod` over `scanf`.
Try it
cd src
gcc -std=c11 -Wall -o ex01 ex01_printf.c && ./ex01
gcc -std=c11 -Wall -o ex02 ex02_scanf_int.c && ./ex02 <<< 7
gcc -std=c11 -Wall -o ex03 ex03_scanf_multi.c && ./ex03 <<< "3 4"
gcc -std=c11 -Wall -o ex04 ex04_format.c && ./ex04💻 Examples
Compilable, runnable examples — see the output yourself.
#include <stdio.h>
int main(void) {
int n = 255;
double x = 3.141592;
printf("decimal: %d\n", n);
printf("hex: %x\n", n);
printf("octal: %o\n", n);
printf("char: %c (code %d)\n", 'A', 'A');
printf("string: %s\n", "Hello");
printf("double default: %f\n", x);
printf("double 2dp: %.2f\n", x);
printf("scientific: %e\n", x);
return 0;
}
42
3.142
left | right#include <stdio.h>
int main(void) {
int n;
printf("Enter int: ");
if (scanf("%d", &n) != 1) {
printf("Input error\n");
return 1;
}
printf("input: %d\n", n);
printf("double: %d\n", n * 2);
return 0;
}
Number? 7
Square = 49#include <stdio.h>
int main(void) {
int a, b;
printf("Two ints separated : ");
if (scanf("%d %d", &a, &b) != 2) {
printf("Input error\n");
return 1;
}
printf(": %d\n", a + b);
printf(": %d\n", a - b);
printf(": %d\n", a * b);
if (b != 0)
printf(": %d\n", a / b);
return 0;
}
3 4
Sum = 7#include <stdio.h>
int main(void) {
int n = 42;
double pi = 3.14159265;
printf("[%5d]\n", n);
printf("[%-5d]\n", n);
printf("[%05d]\n", n);
printf("[%10.4f]\n", pi);
printf("[%-10.4f]\n", pi);
return 0;
}
3.14
3.14159
3.141593e+00📝 Exercises
Try them yourself first, then open the solution to compare.
Problem 1 (hw01.c)
Goal: Read a name and an age, then print a greeting.
- Filename: hw01.c
Enter name and age: Alice 25
Hello, Alice! You are 25.▶Toggle solution
#include <stdio.h>
int main(void) {
char name[64];
int age;
printf("Name: ");
scanf("%63s", name);
printf("Age: ");
scanf("%d", &age);
printf("%s is %d years old.\n", name, age);
return 0;
}
Enter name and age: Alice 25
Hello, Alice! You are 25.Problem 2 (hw02.c)
Goal: Read two ints and print their average with 2 decimal places.
- Filename: hw02.c
▶Toggle solution
#include <stdio.h>
int main(void) {
int a, b, c;
printf(" Enter int: ");
scanf("%d %d %d", &a, &b, &c);
double avg = (a + b + c) / 3.0;
printf("mean: %.2f\n", avg);
return 0;
}
Problem 3 (hw03.c)
Goal: Read a Celsius temperature and print the Fahrenheit equivalent.
- Filename: hw03.c
▶Toggle solution
#include <stdio.h>
int main(void) {
int seconds;
printf("Seconds: ");
scanf("%d", &seconds);
int h = seconds / 3600;
int m = (seconds % 3600) / 60;
int s = seconds % 60;
printf("%d:%d:%d\n", h, m, s);
return 0;
}
All lecture materials and example code are openly available on GitHub.
View on GitHub ↗