The functions printf() and scanf() are
trickier and more powerful than people usually think.
Tips here apply to related functions, e.g., fprintf(), vprintf() and sscanf().
In case you need a quick reference, a complete online specification (for C99) can be found in
fprintf()
and
fscanf().
Under Linux, try to type
man 3 printf or man fprintf
or
man scanf
-” (as in "%-6d")Default is to align to the right.
%lf in printf(), no %g in scanf()
In printf(), always use %f for both double and float,
because float will be automatically upgraded to double.
Most compilers, however, accepts %lf.
On the other hand, in scanf(), use %f for float,
%lf for double.
&s"It applies to both printf() and scanf()
Suppose char s[32] = "abc"; then
Right: scanf("%10s", s); or printf("%s", s);
Wrong: scanf("%10s", &s); or printf("%s", &s);
printf("%.5s", s)This is a nice trick printf("%.5s", s) to print only the first five characters,
note printf("%5s", s); won't work.
Even better, you can use "%.*s" to specify a variable width like
printf("%.*s", n, s);
The trick can be used as "safe" string copying:
char *strncpy_safe(char *t, const char *s, int n)
{
sprintf(t, "%.*s", n-1, s);
return t;
}
See an example.
%5c vs. %5s in scanf()Both can be used to read strings, but the differences are:
%5s skips spaces, %5c counts spaces.
%5s adds a '\0' in the end, %5c doesn't.
So %5c is kind of like memcpy().
See an example.
scanf()A space in the format string fmt of scanf(fmt, ...) means to skip spaces,
Leading spaces before % is usually skip, but not in the case of %c, or an ordinary character
sscanf(" abc", "%c", &c); makes c == ' ',
sscanf("abc", "%c", &c); makes c == 'a'.
An ordinary character (not space or %) in the format string is to be matched,
however, you usually want to skip some leading spaces, so
sscanf("\t\v x \n =5", " x =%d", &x);
will work, while
sscanf("\t\v x \n =7", "x=%d", &x);
won't.
See an example.
[]” in scanf()The pattern %10[a-zA-Z+-] matches a string of maximal of 10 characters long,
with every character in the set {a, b, c, ..., z, A, B, C, ..., Z, +, -}.
(leading spaces are not skipped, to skip spaces use % 10[a-zA-Z+-]).
Use %10[]a-zA-Z+-] to include ']';
use %10[][a-zA-Z+-] to include ']' and '['.
%10[^a-zA-Z] matches a string of maximal of 10 characters long,
with no character in the set {a, b, c, ..., z, A, B, C, ..., Z}.
(leading spaces are not skipped, to skip spaces use % 10[a-zA-Z]).
Use %10[^]a-zA-Z] to exclude ']';
use %10[^][a-zA-Z] to exclude ']' and '['.
See an example.
%nThe format string %n can be used to indicate how many characters read so far.
This is especially useful for sscanf().
Note %n does not count as one scanned item in the return value of
sscanf().
It can be used to read an array of data from string in sscanf().
for (p = s, i = 0; i < 3; i++, p += next)
if (1 != sscanf(p, "%lf%n", &x[i], &next))
exit(1);
see the example.
%#x == 0x%xIn printf()"#" in %#x means the alternate form.
For a hexadecimal number, it usually adds “0x” before the number,
so it's pretty much the same as 0x%x.
Old Visual C++ and Borland C++ use "%I64d" to print 64-bit integers.
On 64-bit Unix/Linux compilers, "%lld" is often used instead,
for long long is usually 64-bit.
In C99, we have PRId64 and SCNd64 defined in <inttypes.h>.
They are equivalent to "I64d" or "lld".
There are also similar macros like PRIx64, PRIu64, etc.
Note that “%” is not included,
for we may need alignment and width flags after “%”.
See the example.
#include <stdio.h>
#include <inttypes.h>
/* constant 64-bit integer */
#if defined(_MSC_VER) || defined(__BORLANDC__)
#define CI64(x) (x ## i64)
#else
#define CI64(x) (x ## ll)
#endif
int64_t x = CI64(3141592653589793);
printf("The number is %-20" PRId64 "\n", x);
In scanf(), use %f to read float,
and %lf to read a double.
If you just need a large integer,
try also %jd
(formally, it's for intmax_t).
This only works for C99.
%z for size_tSome compiler gives a warning if you try to print a size_t with %d.
So use %z instead for C99,
printf("%z\n", sizeof(int));
This trick does not work for C89.
A workaround is
printf("%u\n", (unsigned) sizeof(int));
On a 64-bit machine, it is easier to print a double
printf("%lf\n", 1. * sizeof(int));