C course menu
Input and Output in C: printf, scanf, fgets and Format Specifiers
Learn console input and output in C: printf format specifiers, width and precision, reading numbers with scanf and checking its return value, why scanf is risky for strings, reading lines safely with fgets, and putchar, getchar and puts.
On this page
Most programs need to show results and read input. C does both with functions from stdio.h: printf for formatted output and scanf or fgets for input.
printf format specifiers#
The specifiers must match the argument types. A mismatch, such as passing a double for %d, is undefined behaviour; -Wall warns about it.
Width and precision#
#include <stdio.h>
int main(void) {
double price = 3.14159;
printf("[%.2f]\n", price); /* 2 decimal places */
printf("[%8.2f]\n", price); /* width 8, right-aligned */
printf("[%-8.2f]\n", price); /* left-aligned */
printf("[%05d]\n", 42); /* pad with zeros */
printf("[%10s]\n", "Asha");
printf("[%-10s]|\n", "Asha");
printf("%d%% done\n", 75);
return 0;
}[3.14]
[ 3.14]
[3.14 ]
[00042]
[ Asha]
[Asha ]|
75% doneWidth and alignment are handy for printing tables:
printf("%-10s %6s\n", "Item", "Price");
printf("%-10s %6.2f\n", "Notebook", 45.0);
printf("%-10s %6.2f\n", "Pen", 10.5);Item Price
Notebook 45.00
Pen 10.50Reading numbers with scanf#
scanf reads formatted input. It needs the address of each variable, written with &:
#include <stdio.h>
int main(void) {
char name[20];
int age;
double weight;
printf("Name: ");
scanf("%19s", name);
printf("Age: ");
scanf("%d", &age);
printf("Weight: ");
scanf("%lf", &weight);
printf("%s is %d years old and weighs %.1f kg\n", name, age, weight);
return 0;
}Name: Asha
Age: 21
Weight: 64.5
Asha is 21 years old and weighs 64.5 kg- Use
%lf(not%f) to read adoublewithscanf. - Arrays such as
namedo not need&; the array name already gives an address (Pointers and Arrays). %19slimits the input to 19 characters, leaving room for the terminating'\0'. A plain%scan overflow the array, a serious security bug.%sstops at the first space, so it cannot read "Asha Rao".
Check the return value#
scanf returns how many values it read successfully. Always check it:
#include <stdio.h>
int main(void) {
int qty;
printf("Quantity: ");
if (scanf("%d", &qty) != 1) {
printf("That is not a number.\n");
return 1;
}
printf("You ordered %d\n", qty);
return 0;
}Quantity: abc
That is not a number.Without the check, qty would be used uninitialised.
Reading a whole line with fgets#
fgets reads a line, including spaces, and never writes past the buffer size you give it. It keeps the newline character, which you usually remove:
#include <stdio.h>
#include <string.h>
int main(void) {
char full_name[50];
printf("Full name: ");
if (fgets(full_name, sizeof full_name, stdin) != NULL) {
full_name[strcspn(full_name, "\n")] = '\0'; /* remove the newline */
printf("Hello, %s!\n", full_name);
}
return 0;
}Full name: Asha Rao
Hello, Asha Rao!A robust pattern for numbers is to read a line with fgets and then convert it with strtol (Type Conversion), which avoids leftover input problems that scanf causes when mixing numbers and lines.
Character and line output#
putchar('A');
putchar('\n');
puts("puts adds a newline automatically");A
puts adds a newline automaticallygetchar() reads a single character and returns EOF at the end of the input.
Practice#
Practice exercise
Read two integers from the user and print their sum, difference and product in a neat table using width specifiers. Check that both numbers were read.
Show solution
#include <stdio.h>
int main(void) {
int a, b;
printf("Enter two numbers: ");
if (scanf("%d %d", &a, &b) != 2) {
printf("Please enter two whole numbers.\n");
return 1;
}
printf("%-12s %5d\n", "Sum", a + b);
printf("%-12s %5d\n", "Difference", a - b);
printf("%-12s %5d\n", "Product", a * b);
return 0;
}Enter two numbers: 12 5
Sum 17
Difference 7
Product 60Key takeaway#
Finished this lesson?