📄 19.txt
字号:
CS 1355
Introduction to Programming in C
Monday 2006.11.20 (Week 11)
Lecture notes (at http://r638-2.cs.nthu.edu.tw/C/notes/19.txt)
Today:
Chapter 9: C Formatted Input/Output
Chapter 10: C structures
printf's first parameter is a format string.
For integers, shorts, longs
%d : format as a Decimal numeral
%i : same as a (decimal) Integer (same as %d for printf)
%o : as an Octal (8進位) numeral (unsigned, 沒有負數)
%u : as an Unsigned decimal numeral
%x : as a heXadecimal (16進位), using lower case letters abcdef
%X : as a heXadecimal, but using upper case letters ABCDEF
%hd : as a Half-width (usually 16-bit) decimal
%ld : as a Long (usually 64-bit) decimal
For floating point, double
%e : in exponential notation. e.g., 150.4582 => 1.504582e+02
%E : in exponential notation (1.504582E+02)
%f : in floating point form
%g
%G : let the library decide whether to display as %e or %f
%Le, %LE, %Lf, %Lg, %LG : printing a "long double"
=> Must write it with a big L, not a small l!!!!
otherwise it will not work!
Note:
- All floats are passed as doubles (as an R-value) during function calls!
- similarly, all chars are passed as ints (as an R-value) during calls
- "long double" is a data type!
- Try this on the workstation!! Results can be different from your PC
=======
#include <stdio.h>
int main() {
long double ld = 10.0;
printf("size of long double is %d\n", sizeof(long double));
printf("printing as %%f (incorrect): %f\n", ld);
printf("printing as %%Lf: %Lf\n", ld);
}
=========
./a.out
size of long double is 16
printing as %f (incorrect): -21753684701546415500030991398759357226344272062870388735791907028089517845458017872216707720447382547477024773409800476278392032309734718328818217695224286798853089130941282304450072761765149211680898012259709934116641270471478890541257182616440064835005198661338228363637744629485482240158753966880427343872.000000
printing as %Lf: 10.000000
===========
Result can be very different on a PC!
- (long double) data type might be the same as just a (double)
- On the workstation
float is 4 bytes
double is 8 bytes
long double is 16 bytes (but on many PCs it might be 8 bytes)
(reason: hardware or compiler might not support it)
%c : print as a character (must pass a char or an int)
%s : print as a string (must pass a null-terminated string)
%p : print as "pointer" address (must pass a pointer R-value)
%n : print nothing, but the purpose is to return the number of
characters already printed up to this point by this
printf call. (must pass the address of an L-value integer variable)
%% : print a single %
Try out %n:
#include <stdio.h>
int main() {
int x, y, z;
z = printf("abc%nxyz%n\n", &x, &y);
printf("x=%d y=%d z=%d\n", x, y, z);
}
===
Run it:
./a.out
abcxyz
x=3 y=6 z=7
Why is this useful: because conversion may be variable length!
Why %%?
- Important distinction: what C-language sees vs what printf() sees
C language handles string literals.
C language does not know the interpretation of %d %c %s %n ... etc
=> these are defined by the stdio library!!
these are just usage conventions.
I can define my own I/O library with totally different conventions
- If you say \% (inside a string literal or a char literal),
like "\%" or '\%'
C compiler will find it strange because % is not a special character.
it doesn't need the escape.
But, the C compiler generally will just ignore \ and keep the %.
- When passed to the printf() routine, then both \% and % look like
just a single %
- This is why having a \ does not help!
3 alternative solutions:
printf("%c", '%');
printf("%s", "%");
printf("%%");
=> all print just a %
Numbers
%4d : print decimal, right-justified, blank padded, minimum of 4 width
%-4d : print decimal, left-justified, blank padded, minimum of 4 width
%.4d : print decimal, right-justified, 0-padded!
%04d : print decimal, right-justified, 0-padded
%+4d : print decimal, right-jusitified, print + sign for positive
%+-4d
%-+4d : left-justified
% 4d : print a space instead of a + sign for non-negative
Problem with all of these -- hardwired widths!
- even though 4 is an int,
- it is passed as part of a string!! "4"
- the stdio library needs to "parse" the string to extract number 4
- sometimes, want to vary the width.
One solution: create the format string
char format[20];
int i;
for (i = 1; i < 10; i++) {
sprintf(format, "%%%dd\n", i);
/* this creates "%1d", "%2d", ... for each i */
printf(format, 10);
}
Output:
10
10
10
10
10
10
10
10
10
Another solution: use * and pass an int instead!
for (i = 1; i < 10; i++) {
printf("%*d\n", i, 10);
}
This means (in the context of %_d)
* matches the i (width)
d matches the 10 (integer)
This works for other bases: hex, octal...
====
Integer literals (inside a C program) in other bases
For octal: add an extra 0 in front!
00 01 02 03 04 05 06 07 => same as decimal 0 1 2 3 4 5 6 7
010 011 012 013 014 015 016 017 => these are octal!!
their values are decimal 8 9 10 11 12 13 14 15
020 021 022 023 024 025 026 027 => also octal
their values are decimal 16 17 18 19 20 21 22 23
0100 0101 0102 0103 0104 0105 0106 1017
=> corresponds to decimal 64 65 66 67 68 69 70 71
For hexadecimal, add 0x in front
0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xA 0xB 0xC 0xD 0xE 0xF
=> same as decimal 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
actually, you can also put extra zeros:
0x1 is the same as 0x01 0x001 0x0001 0x0001 ...
0x10 0x11 0x12 0x13 0x14 0x15 0x16 0x17
0x18 0x19 0x1A 0x1B 0x1C 0x1D 0x1E 0x1F
=> same as decimal 16 17 18 19 20 21 22 23
24 25 26 27 28 29 30 31
etc.
But, if you just use %o or %x formatting,
it does not actually print the extra 0 or 0x in front!!
Solution: format it as %#o or %#x !!
another use:
%#g => forces decimal point like 123.4567,
instead of choosing 1.234567e+2
------------------------------------------
scanf() formats
- first parameter is format
- subsequent parameters are pointers to variables
=> data types must match!
=> you can't convert an L-value to a different data type!
int, short, long
%d : decimal
%i : integer! accepts decimal, octal, or hex, based on syntax!
(if 0001 then interepreted as octal; 0x0001 interpreted as hex)
%o : interpret as octal
%u : unsigned
%x : hex
%hd : "half-length decimal" integer
%ld : "long decimal" integer
(%li, %lo, %lx, .... for long,
%hi, %ho, %hx ... for short)
float, double, long double
%e %f %g : float
%le %lf %lg : double
%Le %Lf %Lg : long double
char and string
%c : scan one char
%s : scan one string delimited by a blank
character set, using [ ] notation (but must pass a pointer to char[ ] buffer!)
%[abcdefg] : scan one char which must match a, b, c, d, e f, g
%[^abcdefg] : scan one char, which is NOT one of a, b, c, d, e, f, g
%[a-z] : scan one char, which is one of a, b, ... , y, z
%[0-9] : scan one char in 0, 1, ... 8, 9
=> these are for a single character.
For variable-length string, just add a * after the %[ ... ]
%n : does not actually input, but returns the number of chars
scanned by this scanf() call so far!
What about everything else?
=> they are pattern-matched and skipped.
Example:
int year, month, day;
scanf("%d/%d/%d", &year, &month, &day);
=> you can input
2006/11/20
it will "pattern match" the / / and
year = 2006
month = 11
day = 20
Assignment suppression:
- if you just want to skip the matched pattern without assigning it,
then use %*c instead of %c
(and don't pass a char pointer)
- works for other patterns too
Example:
int year, month, day;
scanf("%d%*c%d%*c%d", &year, *month, &day);
This way, it will accept either
2006/11/20
or
2006-11-20
(or 2006\11=20 works too)
Instead of a single character, we can match-and-skip any data type,
including strings!
scanf("%d%*s%d%*s%d", &x,&y,&z)
/* this scans three decimals separated by strings */
input could actually be
13 zzfdfdfsdf 22 _+_+_+$$% 1523
=> this will return three ints
13, 22, 1523
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -