Input

We're now going to discuss how to take user input from the standard input (stdin) in C.

scanf

scanf() allows you to read different data types from the user's input and store them in variables, making it a versatile function for interactive applications. It enables you to control the input format, extract data from the input stream, and store it in the appropriate variables.

Signature

The general signature of scanf() is similar to printf(), it takes a format string indicating the format of the input sequence and a variadic list of addresses (pointers)where values are stores. scanf()'s format string uses a similar format specification to printf() however, the variable specifiers (denoted with %) indicate values that are to be read in and stored in program variables. As we are reading values in with scanf(), when we wish to store a variable we must pass the address of the variable we want to store the value in. This is because variables have copy semantics in C meaning we cannot pass a variable to a function and get the modified value with returning it or using a pointer. scanf() uses pointers.

scanf(char* fmtstring, ...);

Example

This simple program is similar to the printf() example we saw earlier in the book except, instead of hard coding values we are able to take input from the user in the form x + y and the program will return the result.

#include <stdio.h>

int main()
{
    double a = 0.0;
    double b = 0.0;
    double sum = 0.0;

    printf(">> ")
    scanf("%f + %f", &a, &b);
    sum = a + b;
    printf("%f", sum);

    return 0;
}

Formatting Specification

The format specification is a mirror to that used by printf() (there are many _f() functions in the C standard library that all use similar format specifications) as values being read in must conform to a given C type. This allows us to easily convert the incoming string data as int, double or even substrings.

The general format specification is as below:

_%\[width\]\[.precision\]\[length\]type-specifier_

There are a variety of different options for each part of the specification. Below is a series of tables breaking down the various options for each sub-specifier but note that only type-specifier is needed, the others are optional.

Type Specifiers

Type SpecifierTypeExample
%Two sequential % will result in a single % being printed.%
d or iSigned Decimal Integer392
uUnsigned Decimal Integer7235
oUnsigned Octal Integer610
x or XUnsigned Hexadecimal Integer (X: uppercase variant)7fa or 7FA
f or FDecimal Floating Point (F: uppercase variant for special numbers eg. nan vs NAN)392.65
e or EScientific Notation (mantissa and exponent) (E: uppercase variant)3.9265e+2 or 3.9265E+2
g or GUse the shortest representation: %e or %f (G: uses uppercase variants)7fa or 7Fa
a or AHexadecimal Floating Point (A: uppercase variant)7fa or 7Fa
cCharactera
sStringexample
pPointer Address0x7ffce531691c
nPrints nothing. The argument corresponding to this specifier must be pointer to a signed integer. Stores the number of character read so far.
[set]Matches a non-empty sequence of character from set of characters. If the first character of the set is ^, then all characters not in the set are matched. If the set begins with ] or ^] then the ] character is also included into the set. It is implementation-defined whether the character - in the non-initial position in the scanset may be indicating a range, as in [0-9]. If a width specifier is used, matches only up to width. Always stores a null character in addition to the characters matched (so the argument array must have room for at least width+1 characters)
*Assignment-suppressing character. If this option is present, the function does not assign the result of the conversion to any receiving argument (optional).

Width

WidthDescription
numberMinimum number of characters to be printed. If the value to be printed is shorter than this number, the result is padded with blank spaces. The value is not truncated even if the result is larger.

Precision

.precisionDescription
.numberFor integer specifiers (d, i, o, u, x, X): precision specifies the minimum number of digits to be read. If the value read is shorter than this number, the result is padded with leading zeros. The value is not truncated even if the result is longer. A precision of 0 means that no character is written for the value 0. For a, A, e, E, f and F specifiers: this is the number of digits to be printed after the decimal point (by default, this is 6). For g and G specifiers: This is the maximum number of significant digits to be printed. For s: this is the maximum number of characters to be printed. By default all characters are printed until the ending null character is encountered. If the period is specified without an explicit value for precision, 0 is assumed.

Length

Type Specifier
Length Modifier d, i u, o, x, X f, F, e, E, g, G, a, A c s p n
(none) int unsigned int double int char* void* int*
hh signed char unsigned char signed char*
h short int unsigned short int short int*
l long int unsigned long int wint_t wchar_t* long int*
ll long long int unsigned long long int long long int*
j intmax_t uintmax_t intmax_t
z size_t size_t size_t
t ptrdiff_t ptrdiff_t ptrdiff_t
L long double