前言;

Hello,大家好,我是心跳sy,今天我们主要讨论一下格式化输入/输出(一),包括printf,scanf的基本使用方法及注意事项、转换说明的简单理解以及转义序列的讲解,后续将持续带来对转换说明的深入研究以及输入缓冲的概念与文件相联系的知识,以及包括字符的输入输出、行的输入输出、块的输入与输出。今天我们讨论的知识将是c语言入门时所广泛涉猎的内容,以及汇总我们经常会踩的坑,我们一起来看看吧~~

1、printf 函数

基本格式:printf(格式串,表达式1,表达式2,…);printf函数被用来显示格式串的内容,并在该串的指定位置插入可能的值。在调用printf时必须提供格式串,格式串后的参数是显示时插入该串的值(可以是常量、变量、以及复杂的表达式)。

格式串:包含普通字符以及转换说明,其中转换说明以%开头。转换说明是用来表示打印过程中待填充的值的占位符,跟在%后面的信息则指定了把数值从计算及内部形式(二进制)转换成想要打印的形式。

例如:转换说明%d指定printf函数把int型值从二进制形式转换成十进制形式。

*需要注意以下几点:

1、格式串中的普通字符要完全“复制”显示出来, 而转换说明则要用带显示的值来“替换”。例如:

int i, j;float x, y;i = 1;j = 2;x = 2.55f;y = 20.0f;printf("i=%d,j=%d\nx=%f,y=%f",i,j,x,y);

输出结果:可以看出,格式串中普通字符“i=、j=、x=、y=”和“逗号”被“复制”给输出行,而变量i,j,x,y的值则则依次替换了4个转换说明。

2、要注意格式串中转换说明是否和输出项的数量匹配。

·当转换说明数量多于要显示的值的数量时:

int i = 1;int j = 2;printf("%d %d\n", i);

输出结果: 可以看出printf函数将正确显示i的值,接着显示一个无意义的值。

·当转换说明数量少于要显示的值的数量时:

int i = 1;int j = 2;printf("%d\n", i, j);

输出结果: 可以看出只输出i的值,不显示j的值。

·也要注意使用正确的转换说明与显示项的匹配:

int i = 1;float j = 2.5f;printf("%d %f", j, i);

输出结果:可以看出,将int型变量i与float型变量j的顺序放错,程序将产生无意义的输出。

2、转换说明

* 转换说明给程序员们提供了大量的输出格式的控制方法,转换说明有时包含格式化信息,例如:用%.1f来显示小数点后带一位数字的float型值。

* 一般的,转换说明可用%m.pX格式或-%m.pX格式这里的mp都是整形常量,而X是字母。mp都是用户根据需求自定义的,如果省略p,则mp之间的小数点也要去掉。

·例如:在转换说明10.2f中,m是10,p是2,而X是f。如果转换说明为%10f时,m是10,p连同小数点一起省略了,而如果转换说明为%.2f时,p是2,m省去了。

转换说明%m.pX中,m指定了要显示的最少字符数量,称为最小栏宽。(可理解为输出显示字符总数m)

*如果要显示的数值所需字符数少于m,那么值在字段内是右对齐的(在值前面加空格凑数),例如:%4d将以 123的形式显示数123(123前加一个空格)。

*如果要显示的数值数量多于m,那么栏宽将会自动扩展;例如:%4d将以12345的形式显示数12345,而不会丢失数字。

*在m前加上负号会导致显示数值左对齐;例如:%-4d将以123 的形式显示123(123的后面有一个空格)

转换说明%m.pX中,p称为精度。(在浮点数中可表示小数点后p位)它依赖于转换指定符X的选择,X表明在显示数值前需要对其进行哪种转换。下面介绍几个常用的转换指定符(全面表格以后会详细介绍)

*d——表示十进制形式的整数。p指明了待显示数值的最少个数(若缺可在数前加额外的零)

*e——表示指数(科学计数法)形式的浮点数。p指明了小数点后应该出现的数字个数(默认值为6)。如果p为0,则不显示小数点。

*f——表示浮点数,没有指数,p的含义与说明符e一样。

*g——表示指数形式或者定点十进制形式的浮点数。形式的选择根据数的大小决定,p意味着可以显示的有效数字的最大数量(不是小数点后的数字),与f不同,g的转换将不显示尾随的零(如果g要显示的数值没有小数点后的数字,g就不会显示小数点)。在显示大小适中的数时,g采用定点十进制;在显示非常大或非常小的数时,g则会转换成指数形式。

int i;float x;i = 40;x = 200.20f;printf("|%d|%5d|%-5d|%5.3d|\n", i, i, i, i);printf("|%10.3f|%10.3e|%-10g|\n", x, x, x);

输出结果:

解析:

·%d——以十进制形式显示变量i,占用最少空间。

·%5d——以十进制形式显示变量i,且至少占用5个字符的空间。因为i只占2个字符,所以前面添加了3个空格。

·%-5d——以十进制形式显示变量i,且至少占用5个字符的空间。因为i的值不需要满5个字符,所以在后续位置添加空格(数左对齐)。

·%5.3d——以十进制形式显示变量i,至少占用5个字符的空间,并至少有3位数字,因为变量i只有2个字符长度,所以需要添加一个额外的零来保证有三位数字(现在只有3个字符长度,为保证占5个字符,还需要添加2个空格,注意是右对齐的)

·%10.3f——以定点十进制形式显示变量x,且总共10个字符,其中小数点后保留3位小数,因为变量x只需要7个字符(算小数点),所以在前面补位3个空格。

·%10.3e——以指数形式显示变量x,且总共10个字符,小数点后保留3位数字。因变量x有9个字符,所以前面补位一个空格。

`%-10g——既可以定点十进制形式显示变量x,也可以以指数形式显示变量x,且总共10个字符,因数字较小,所以选择定点十进制的形式,左对齐,后面跟4个空格。

3、转义序列

格式串中常用到的\n就被称为转义序列,转义序列常包含一些特殊字符而不会引起编译器报错,这些字符包括非打印的控制字符和一些特殊含义字符。先介绍几个常用的转义符:

*警报响铃符:\a//会产生一声鸣响

*回退符:\b //会使光标从当前位置退回一个位置

*换行符:\n //会使光标跳到下一行的起始位置

*水平制表符:\t//会把光标移动到下一个制表符位置(一般来说,水平制表符之间距//离是8个字符长度,意为补全当前长度到8,但也依据本身所使用的//操作系统,一般是8的整数倍)

*表示字符“:\“ //显示输出字符“

·下图展示了水平制表符与换行符作用:

printf("Item\tUnit\tPutchase\n\tPrice\tDate\n");

输出结果: 可以看到水平制表符占8个字符长度(包含输出字符本身,不够8的补4个空格)

·如果要显示“ ”:

printf("\"Hello!\"");

输出结果:

4、scanf 函数

*同printf一样,scanf也根据特定的格式进行读取输入。scanf的格式串也可以包含普通字符和转换说明两部分

*在许多情况下,scanf函数的格式串仅包含转换说明,例如:scanf(“%d %d”,&i,&j); 假设用户输入1 -2

scanf函数的作用是读入用户输入信息,然后分别把1 -2赋值给变量i,j。

*需要注意的是:第一:使用scanf函数时,必须检查转换说明的数量是否与输入变量的数量匹配,并检查每个转换是否与变量相对应;第二:&通常放在每个变量前,一定不要忘记,除特殊情况(当本身就表示地址信息时,因为&的意思本就是取地址)。

scanf意义再解读

scanf函数本质上是一种“模式匹配”函数,试图把输入的字符与转换说明匹配。当调用scanf函数时,scanf从最左端开始处理字符串中的信息,对于每一个转换说明,scanf函数都会定位匹配的项,并在必要时跳过空格,然后scanf继续读取输入项,直到遇到不可能匹配的字符停止读取,把剩余字符交给下一个scanf读取。

我们来看一个很容易混淆的实例:

int i, j;float x, y;scanf("%d%d%f%f", &i, &j, &x, &y);printf("i=%d,j=%d,x=%f,y=%f", i, j, x, y);

这里我们输入1-20.3-4.0e3\n

输出结果:

解释:

*转换说明%d:第一个非空输入的字符是1,整数可以从1开始,所以scanf继续向下读取,遇到-,scanf判断出负号不与整数%d转换说明匹配,所以将1存入i中,将-放回原处。

*转换说明%d:随后scanf读取-、2、0和 . ,scanf成功读取-20整数存入j,遇到小数点,与转换说明不匹配,把字符 . 放回原处。

*转换说明%f:scanf读取 . 、3、- 字符,因为浮点数后不能有负号,所以scanf把0.3存入x中。-放回原处。

*转换说明%f:最后scanf读取-、4、. 、0、e、3和换行符,因为浮点数不包括换行符,所以scanf将-4.0*10的3次方存入y,把换行符放回原处(缓冲区,我们下次详细介绍),留给下一次scanf调用。

*注:在使用scanf时一定要注意格式匹配,在读取字符串时,只要遇到一个空格,scanf() 就会停止读取,所以 “this is test” 对 scanf() 来说是三个字符串;又如:在scanf(“%d,%d”,&i,&j);中,scanf函数首先寻找合适输入整数,存入i中,然后scanf试图把逗号与下一个输入字符匹配,如果下一个字符是空格而不是逗号,那么scanf函数将终止操作,不再读取j的值。

后期将继续带来有关输入输出的再解读,感谢各位大佬友友们阅读!!!如有问题欢迎各位大佬在评论区指正支持!!!