ps:字段宽度是指答应出来的“东西”所占位置大小,比如用%8.3f打印出来的浮点数,小数点前占4个字符位,其中小数点后占3个字符位,小数点算一个字符位,如果小数点前不满4个数,就用空格代替。用%08.3f打印出来的浮点数如果小数点前不满4个数,就用0代替。
#1. 输出 #1.1 printf()函数要输出的内容 => 缓冲区(buffer) => 屏幕
何时发送到屏幕:
- buffer满时
- 遇到换行字符
- 需要输入时(旧编译器可能不支持)
#include#define PAGES 999 int main(void) { printf("%2dn", PAGES); printf("%5.3dn", 6); printf("%05.3dn", 6); printf("%05.2dn", 6); return 0; }
结果为:
999
006
006
06
#1.1.1 转换字符不匹配时转换字符要匹配!!!!!
#include#define PAGES 336 #define WORDS 65618 int main() { short int num = PAGES; short int mnum = -PAGES; printf("short int:%zd, int:%zd, char:%zdn", sizeof(short int), sizeof(int), sizeof(char)); printf("num as short and unsigned short:%hd %hun", num, num); printf("-num as short and unsigned short:%hd %hun", mnum, mnum); printf("num as int and char:%d %cn", num, num); printf("WORDS as int, short and char:%d %hu %cn", WORDS, WORDS, WORDS); return 0; }
结果如下:
可以看到
short int为2字节(0~65535),用%hd打印时,范围为-32768~32767 [ -2^(15) ~ 2^(15)-1 ] ,用%hu打印时,范围为0~65535[ 0 ~ 2^(16)-1 ];
因为num=336都在这个范围内,因此 printf("num as short and unsigned short:%hd %hun", num, num); 打印出来都没问题。
对于printf("-num as short and unsigned short:%hd %hun", mnum, mnum); 由于mnum=-336,在用%hd打印的范围内,因此用%hd打印没问题;但是不在用%hu打印的范围内,因此出现问题,336用二进制表示为0000 0001 0101 0000,故-336为1111 1110 1011 0000,用%hu打印时,左边第一位不是符号位,因此65200。
对于printf("num as int and char:%d %cn", num, num); 由于int为4字节,用%d打印时,范围为-2,147,483,648~2,147,483,647 ,336在其范围内,因此输出没问题;但336用%c输出时出现问题,因为%c为1个字节也即用%c打印时,只会输出336的后八位(01010000),也即十进制的80,对应ASKII码的P。
对于printf("WORDS as int, short and char:%d %hu %cn", WORDS, WORDS, WORDS); WORDS=65618,包含在%d的输出里面,因此没问题;对应的二进制为0001 0000 0000 0101 0010,%hd只有两字节,因此输出 0000 0000 0101 0010=82,这种截断方式,相当于对65536(2^16)取余;%c只有一个字节,因此输出0101 0010=82,对应ASKII码的R。
#include#define PAGES 336 #define WORDS 65618 int main() { float n1 = 3.0; double n2 = 3.0; long n3 = 2000000000; long n4 = 1234567890; printf("%.1e %.1e %.1e %.1en", n1, n2, n3, n4); printf("%ld %ld %ld %ld", n1, n2, n3, n4); return 0; }
运行结果为:
对于printf("%.1e %.1e %.1e %.1en", n1, n2, n3, n4); 前两个输出没有问题,对于n3=2000000000=0111 0111 0011 0101 1001 0100 0000 0000(一共4字节),用%e打印时,不仅看这四个字节,还看相邻的四个字节,共八个字节。
printf()函数打印时,会把float转换成double类型。
对于printf("%ld %ld %ld %ld", n1, n2, n3, n4); 一种解释:
参数传递时,把n1n2n3n4依次压入栈中,分别为8 8 4 4个字节,在输出时,printf()根据%ld从栈中按4字节依次取数,如图。
#1.1.2 printf()的返回值printf()函数正常运行的返回值为打印字符的个数,异常时返回复数(旧版本不一定)。
#1.1.3 printf()打印较长字符串三种字符串断行方法:
- 使用多个printf()函数
- 使用反斜杠和ENTER换行
- 在两个用双引号括起来的字符串之间用空白格隔开;注意,"XJ" "X"输出XJX ; "XJ " "x"输出XJ X
如果不想预先指定字段宽度,希望程序来指定,可以用*修饰符代替字段宽度。
如:设定一个输入width,用于确定字段宽度。
上面的语句,会根据width的值来确定后面number打印的字段宽度。
上面的语句,会根据width的值来确定weight打印的字段宽度;precision的值确定小数点后的位数。
#2. 输入 #2.1. scanf()函数转换说明:
修饰符:
#2.1.1. scanf()读取数据
- scanf()每次读取一个字符,跳过空白字符;遇到第一个非空白字符才会开始读取
- scanf()会根据转换说明来读取输入。如要输入数字,scanf()会识别数字或(+ -号),读到非数字和+ -号或者空白字符时,停止本次读取;如果第一个字符是A,则永远无法完成输入。如果使用带多个转换说明的scanf(),C规定在第1个出错处停止读取输入。
- 如果使用字段宽度,scanf()在字段结尾或第1个空白字符处停止读取(满足两个条件之一便停止)。因此,无法利用字段宽度让只有一个号s的scanf()读取多个单词。
- 当scanf()把字符串放进指定数组中时,它会在字符序列的末尾加上' ',让数组中的内容成为一个C字符串。
除了%C,其他转换说明都会自动跳过待输入值前面所有的空白。
#2.1.3. scanf()函数的返回值- 返回成功读取的项数。
- 如果没有读取任何项,且需要读取一个数字而用户却输入一个非数值字符串,返回0。
- 当scanf()检测到“文件结尾”时,会返回EoF。
#2.1.4 scanf()函数的*修饰符
上面的语句,会把第三个输入的值传递给n,实现跳过的功能。



