1.printf()何时发送内容到屏幕:
printf()会先把要输出的内容发送到1个叫缓冲区(Buffer)的中间存储区域,然后缓冲区中的内容再不断被发送到屏幕上
从缓冲区把数据发送到屏幕或文件称为刷新缓冲区,C标准规定:当缓冲区被填满,遇到'\n'或需要输入时刷新缓冲区
旧式编译器遇到scanf()也不会强行刷新缓冲区,程序会停在那里不显示任何提示内容,等待用户输入数据
在这种情况下,可以使用'\n'来刷新缓冲区,但这会导致光标移动到下1行起始位置;还可以用fflush()刷新缓冲区
2.空字符(Null Character):
C语言使用字符数组来存储字符串,字符串必须以'\0'结尾(会自动补上)
'\0'是空字符,是非输出控制符,其ASCII码是0
由于必须以'\0'结尾,字符数组的长度必须至少比要存储的字符串的长度多1
比如有10个字符的字符串必须存储在长度至少为11的字符数组中
3.标准化输入输出函数的标准:
scanf()和printf()被称为标准化输入/输出函数,或简称I/O函数
最初,C把输入/输出的实行留给了编译器的作者,所以不同编译器提供的I/O函数可能有区别
不过,C90/C99规定了I/O函数的标准版本
4.转换说明修饰符:
输出控制符被称为转换说明(Conversion Specification),其中%后面的符号称为转换字符
通过在%和转换字符间插入转换说明修饰符来修饰基本的转换说明
//注意:
1.所有下述修饰符都是C99新增的
2.如果要插入多个修饰符,插入顺序应和下面列出的顺序相同
①标记
-:将待打印项左对齐,即从字段的左侧开始打印该项.如"%-20s"
//默认是最右侧,左侧用前导空格填充
+:显示值的符号(如果有).如"%+6.2f"
空格:有符号项若为正,则在前面显示前导空格(不显示符号);若为负,则显示负号并覆盖空格.如"% 6.2f"
#:把结果转换为另1种形式
如果是%o格式,则以0开始
如果是%x/%X格式,则以0x/0X开始
对于所有浮点格式,保证了即使后面没有任何数字,也打印1个小数点字符
对于%g/%G格式,防止结果结尾的0被删除
如"%#o","%#8.0f","%+#10.3e","%#%g"
0:对于数值格式.用前导0代替空格填充字段宽度
对于整数格式,如果出现负号标记或指定了精度,则忽略负号
如"%010d","%08.3f"
②数字:指定最小字段宽度.如"%4d"
③.数字:指定精度
对于%e/%E/%f格式,表示小数点后的位数
对于%g/%G格式,表示有效数字最大位数
对于%s格式,表示待打印字符的最大数量
对于整数格式,表示待打印数字的最小位数
如有必要,使用前导0来达到这个位数
只使用.相当于.0
如"%5.2f","%.f"(相当于"%.0f")
//指定字段宽度的一些用法:
float distance=10.22;
printf("Count Beppo ran %.2f miles in 3 hours.\n",distance);
//结果:Count Beppo ran 10.22 miles in 3 hours.
//指定比字段宽度更小的宽度,以防止出现多余的空格
printf("Count Beppo ran %10.2f miles in 3 hours.\n",distance);
//结果:Count Beppo ran 10.22 miles in 3 hours.
5.size_t与ptrdiff_t类型:
标准只规定了sizeof()的返回值应该是无符号整数,在不同的实现中,可以是unsigned/unsigned long/unsigned long long
如果要打印sizeof()的返回值,根据环境,需要使用%u/%lu/%llu,这意味着移植程序时需要进行修改,为此,C提供了更好的类型
stddef.h把size_t定义成sizeof()返回的类型,称为底层类型(Underlying Type),而printf()使用z修怖符表示打印相应类型
同样,C还定义了ptrdiff_t类型和t修饰符来表示系统使用的指针差值的底层有符号整数类型
6.输出时类型不匹配的补充:
//混淆整型/字符类型:
short a=336;
printf("%c\n",a);//结果:P
//超出255时,%c只会查看最后1个字节,并将该字节翻译为字符并显示(见下图)
//即该值被解释成"以256为模"(modulo 256),相当于除以256后取余数,再把余数翻译成字符
short num=336,mnum=-336;
printf("%hd,%hu,%hd,%hu\n",num,num,mnum,mnum);//结果:336,336,-336,65200
//336的补码表示为336;而-336的补码表示为65200,作为unsigned short时被解释为65200
int big=65618;
printf("%d,%hd\n",big,big);//结果:65618,82
//这时也进行了求模运算,只查看最后2B
//混淆整型与浮点型:
float n1=3.0;
double n2=3.0;
long n3=2000000000,n4=1234567890;
printf("%.1e,%.1e,%.1e,%.1e\n",n1,n2,n3,n4);//结果:3.0e+000,3.0e+000,9.9e-315,-1.$e+000
//%e让printf()认为n3是double,因此除了查看n3的4B,还需要查看相邻的4B
//让后将这8B分别解释为小数部分和指数部分
315,-1.$e+000
printf("%ld,%ld,%ld,%ld\n",n1,n2,n3,n4);//结果:0,0,2000000000,1234567890
//不能用%ld输出浮点型
//注意:再某些环境下,这种情况下n3/n4也会输出错误
7.printf()输出长字符串:
//方法1:使用多个printf(),除最后1个外,不要加'\n'
printf("My name is John Smith,");
printf("I am 10 years old.\n");
//结果:My name is John Smith,I am 10 years old.
//方法2:使用字符串连接
//多个str间如果用空白隔开,会被视为1个str
printf("Here is another way"
"to print " "a long str.\n");
//结果:Here is another wayto print a long str.
//方法3:使用反斜杠(\)来断行
//下1行必须从该行的最左侧开始,如果缩进,缩进所产生的空白也会被视为字符串的一部分
int main(void) {
printf("Third way to \
print a long str.\n");
return 0;
}
//结果:Third way to print a long str.
8.*修饰符:
//printf()的*修饰符:
如果不想预先指定字段宽度,而想通过变量指定,使用*修饰符
int a=5;
printf("%*d\n",a,a);//结果: 5
//scanf()的*修饰符:
会跳过使用*修饰符的输入项,将下1个输入项赋给变量
//需要读取文件的特定列时很有用
int a;
scanf("%*d,%d",&a);//输入:3,2
printf("%d\n",a);//结果:2
9.输入数组元素:
int index,score[3];
for (index=0;index<3;index++) {
printf("input score:");
scanf("%d",&score[index]);
}
printf("output all score:");
for (index=0;index<3;index++) {
printf("%d,",score[index]);
}
//结果①:
//input score:9
//input score:2
//input score:4
//output all score:9,2,4,
//结果②:
//input score:5 2 9
//input score:input score:output all score:5,2,9,
//结果③:
//input score:4 7 9 3 2
//input score:input score:output all score:4,7,9,