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.
%n
The 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%x
In 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_t
Some 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));