scanf(3)

C library function

Reads standard input according to a format and stores the values at the addresses you pass. Returns the number of values read, to check on every call.

Synopsis
#include <stdio.h>
int scanf(const char *restrict format, ...);

Description

scanf reads characters from standard input and converts them according to the format: %d for an int, %lf for a double, %s for a word, %c for a character. Each conversion stores its value at an address, hence the & in front of variables: scanf("%d", &age). For %s, a char array is passed without &, since its name already stands for its address.

Return value

The number of conversions that succeeded and were stored. It is EOF if input ends before the first conversion. Input that does not match the format returns a smaller number than expected, and the offending characters stay in the input buffer.

Example

age.c
#include <stdio.h>
int main(void){    int age;
    printf("Your age: ");    if (scanf("%d", &age) != 1) {        printf("\nThat is not a number.\n");        return 1;    }    printf("You are %d years old.\n", age);    return 0;}
Terminal
$ gcc -Wall -Wextra -g age.c -o age$ echo 19 | ./ageYour age: You are 19 years old.$ echo nineteen | ./ageYour age: That is not a number.

Pitfalls

  • Forgetting the & passes a value where scanf expects an address. GCC warns with -Wall (expects argument of type 'int *'), and the program often crashes.

  • Not testing the return value leaves the variable uninitialized when the input is invalid.

  • %s without a width can write past the end of the array. Always give a limit: scanf("%19s", name) for a char name[20].

  • %c also reads spaces and the newline left over from the previous input. A space in the format, " %c", skips them.

  • To read a whole line, fgets is safer than scanf.

C

mini_scanf

Write mini_scanf, a cut-down scanf that handles %d, %s and %c and returns how many conversions succeeded.

Open the exercise

Now write it yourself.