Skip to content
  • Input & Output: printf and scanf · C

Input & Output: printf and scanf

LearnViaNotes @learnvianotes· 4 min read

printf formats values into text on stdout; scanf parses text from stdin into variables. Both are driven by format specifiers that must match the argument types exactly.

Format specifiers

SpecifierType (printf)Type (scanf)Example output
%d / %iintint *-42
%uunsigned intunsigned *42
%ld / %lldlong / long longpointer to same9000000000
%zusize_tsize_t *8
%fdouble (and float, promoted)float *3.140000
%lfdoubledouble * (required)3.140000
%e / %gdouble scientific / shortestsame as %f3.14e+00 / 3.14
%cint (a char)char *A
%schar * (NUL-terminated)char * (array)hello
%x / %X / %ounsigned hex / HEX / octalunsigned *ff / FF / 377
%pvoid *void **0x16d…
%%a literal %—%

Width, precision and flags

C
#include <stdio.h>

int main(void) {
    int n = 42;
    double pi = 3.14159265;
    printf("[%d] [%5d] [%-5d] [%05d] [%+d]\n", n, n, n, n, n);
    printf("[%f] [%.2f] [%8.3f] [%e] [%g]\n", pi, pi, pi, pi, pi);
    printf("[%x] [%X] [%#x] [%o] [%#o]\n", 255, 255, 255, 8, 8);
    printf("[%s] [%10s] [%-10s] [%.3s]\n", "hello", "hi", "hi", "truncate");
    printf("[%*d] [%.*f]\n", 6, n, 1, pi);    /* width / precision from args */
    printf("100%% done, char %c, code %d\n", 'A', 'A');
    return 0;
}
Output
[42] [   42] [42   ] [00042] [+42]
[3.141593] [3.14] [   3.142] [3.141593e+00] [3.14159]
[ff] [FF] [0xff] [10] [010]
[hello] [        hi] [hi        ] [tru]
[    42] [3.1]
100% done, char A, code 65

Reading input with scanf

C
#include <stdio.h>

int main(void) {
    int age;
    double height;
    char name[20];

    /* scanf needs ADDRESSES: &age, &height — but an array name already is one */
    int got = scanf("%19s %d %lf", name, &age, &height);
    printf("read %d items: %s is %d years, %.2f m\n", got, name, age, height);
    return 0;
}
Output
read 3 items: Asha is 21 years, 1.68 m

scanf returns the number of items successfully converted (or EOF). Always check it — on bad input the variables are left untouched:

C
#include <stdio.h>

int main(void) {
    int x = -1;
    if (scanf("%d", &x) != 1) {
        printf("not a number, x still %d\n", x);
    } else {
        printf("x = %d\n", x);
    }
    return 0;
}
Output
not a number, x still -1

Reading a whole line: fgets

C
#include <stdio.h>
#include <string.h>

int main(void) {
    char line[64];
    while (fgets(line, sizeof line, stdin) != NULL) {
        line[strcspn(line, "\n")] = '\0';   /* strip the trailing newline */
        printf("got \"%s\" (%zu chars)\n", line, strlen(line));
    }
    return 0;
}
Output
got "hello world" (11 chars)
got "second line" (11 chars)

Character I/O

C
#include <stdio.h>
#include <ctype.h>

int main(void) {
    int c;                         /* int, not char: must hold EOF (-1) too */
    while ((c = getchar()) != EOF) {
        putchar(toupper(c));
    }
    return 0;
}
Output
SHOUT THIS

Pitfalls

MistakeConsequenceFix
scanf("%d", x) — missing &Writes to a garbage address → crashscanf("%d", &x)
scanf("%s", buf) with no widthBuffer overflow on long inputscanf("%19s", buf) for char buf[20]
%f to read a doubleWrites only 4 bytes → wrong valueUse %lf in scanf
gets(buf)Unbounded — removed in C11fgets(buf, sizeof buf, stdin)
scanf("%d") then fgetsfgets reads the leftover \n → empty lineConsume the rest of the line first
printf(user_input)Format-string vulnerabilityprintf("%s", user_input)

Why is getchar's result stored in an int?

Why does printf use %f for both float and double, but scanf needs %lf for double?

Free for students and teachers

Write notes like this one

Cards for every idea, quizzes and flashcards, read aloud — on the web and your phone.

Something wrong with this note? Open it to report