第三章 格式化输入 输出《C语言程序设计现代方法(第2版)》读书笔记

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

注意:

C语言编译器不会检测格式串中转换说明的数量是否和输出项的数量相匹配。

面这个
printf
函数调用所拥有的转换说明的数量就多于要显示的值的数量:

printf(“%d %d
n”, i);
/*** WRONG ***/

printf函数将正确显示变量i的值,接着显示另一个(无意义的)整数值。
函数调用

带有太少的转换说明也会出现类似的问题:

printf(“%d\n”, i, j); /*** WRONG ***/

在这种情况下,printf函数会显示变量i的值,但是不显示变量j的值。

此外,
C
语言编译器也不检测转换说明是否适合要显示项的数据类型。如果程序

员使用不正确的转换说明,程序将会简单地产生无意义的输出。思考下面的
printf

函数调用,
其中int型变量i和float型变量x的顺序放置错误:

printf(“%f %d\n”, i, x); /*** WRONG ***/

因为
printf
函数必须服从于格式串,所以它将如实地显示出一个
float
型值,接着是

一个
int
型值。可惜这两个值都将是无意义的。

3.1.1 转换说明🚀

转换说明可以用%m.pX格式或%-m.pX格式

最小栏宽

minimum field width

m
指定了要显示的最少字符数量。如果要显示的数值所

需的字符数少于
m
,那么值在字段内是右对齐的。(换句话说,在值前面放置额外的空格。)例如,转换说明%4d
将以
·
123
的形式显示数
123
(本章用符号
·
表示空格字符)。如果要显示的值所需的字符数多于m
,那么字段宽度会自动扩展为所需的尺寸。因此,转换说明
%4d
将以
12345的形式显示数12345
,而不会丢失数字。在
m
前放上一个负号会导致左对齐;转换说明
%-4d
将以123·
的形式显示
123

精度

precision

p
的含义很难描述,因为它依赖于
转换说明符

conversion specifier

X
的选择。X
表明在显示数值前需要对其进行哪种转换。对数值来说最常用的转换说明符有以下几个。

编写程序时无法预知数的大小或者数值变化范围很大的情况下,说明符
g
对于数的显示是特

别有用的。在用于显示大小适中的数时,说明符
g
采用定点十进制形式。但是,在显示非常大或非常小的数时,说明符g
会转换成指数形式以便减少所需的字符数。

3.1.2 转义序列🚀

格式串中常用的代码
\n被称为转义序列

escape sequence
)。转义序列(
7.3节)使字符串包含一些特殊字符而不会使编译器引发问题,这些字符包括非打印的(控制)字符和对编译器有
特殊含义的字符(如
"

当这些转义序列出现在
printf
函数的格式串中时,它们表示在显示中执行的操作。在大多

数机器上,输出
\a
会产生一声鸣响,输出
\b
会使光标从当前位置回退一个位置,输出
\n
会使光

标跳到下一行的起始位置,输出
\t
会把光标移动到下一个制表符的位置。

附带提一下,不能在字符串中只放置单独一个字符

,编译器将认为它是一个转义序列的开

始。为了显示单独一个字符

,需要在字符串中放置两个

字符:

printf(“\”); /* prints one \ character */

3.2 scanf 函数🚀

scanf函数转换说明的用法和printf函数转换说明的用法本质上是一样的。

scanf
函数调用中像
“%d%d%f%f”
这样“紧密压缩”的格式串是很普遍的,而printf
函数的格式串很少有这样紧挨着的转换说明。

调用
scanf
函数是读数据的一种有效但不理想的方法。许多专业
C
程序员会避免用
scanf

数,而是采用字符格式读取所有数据,然后再把它们转换成数值形式。(在本书中,特别是前面的几章将相当多地用到scanf函数,因为它提供了一种读入数的简单方法。

3.2.1 scanf 函数的工作方法🚀

实际上
scanf
函数可以做的事情远远多于目前为止已经提到的这些。
scanf
函数本质上是一

种“模式匹配”函数,试图把输入的字符组与转换说明相匹配。

像printf函数一样,scanf函数是由格式串控制的。
调用时,scanf函数从左边开始处理字符串中的信息。对于格式串中的每一个转换说明,scanf函数从输入的数据中定位适当类型的项,并在必要时跳过空格。然后,scanf函数读入数据项,并且在遇到不可能属于此项的字符时停止。如果读入数据项成功,那么scanf函数会继续处理格式串的剩余部分;如果某一项不能成功读入,那么scanf函数将不再查看格式串的剩余部分(或者余下的输入数据)而立即返回。

在寻找数的起始位置时,scanf函数会忽略空白字符

white-space character
,包括空格符、

水平和垂直制表符、换页符和换行符)。因此,我们可以把数字放在同一行或者分散在几行内输入。考虑下面的scanf
函数调用:

scanf(“%d%d%f%f”, &i, &j, &x, &y);

假设用户录入
3
行输入:

1

-20      .3

-4.0e3

scanf
函数会把它们看成是一个连续的字符流:

··
1¤-20
···
.3¤
···
-4.0e3¤

(这里使用符号
·
表示空格符,用符号
¤
表示换行符。)因为
scanf
函数在寻找每个数的起始位置时会跳过空白字符,所以它可以成功读取这些数。在接下来的图中,字符下方的s
表示此项被跳过,而字符下面的r
表示此项被读取为输入项的一部分:

scanf函数“忽略”了最后的换行符,实际上没有读取它。这个换行符将是下一次scanf函数调

用的第一个字符。

scanf
函数遵循什么规则来识别整数或浮点数呢?在要求读入整数时,
scanf
函数首先寻找正号或负号,然后读取数字直到读到一个非数字时才停止。当要求读入浮点数时,scanf函数

会寻找一个正号或负号(可选),随后是一串数字(可能含有小数点),再后是一个指数(可选)。指数由字母e
(或者字母
E
)、可选的符号和一个或多个数字构成。在用于
scanf
函数时,转换说明%e

%f

%g
是可以互换的,这
3
种转换说明在识别浮点数方面都遵循相同的规则。

当scanf函数遇到一个不可能属于当前项的字符时,它会把此字符“放回原处”,以便在扫描下一个输入项或者下一次调用scanf函数时再次读入。
思考下面(公认有问题的)
4
个数的排列:

3.2.2 格式串中的普通字符🚀

通过编写含有普通字符和转换说明的格式串能更进一步地理解模式匹配的概念。处理格式

串中的普通字符时,
scanf
函数采取的动作依赖于这个字符是否为空白字符。

空白字符
当在格式串中遇到一个或多个连续的空白字符时,scanf函数从输入中重复

读空白字符直到遇到一个非空白字符(把该字符“放回原处”)为止。
格式串中空白字

符的数量无关紧要,格式串中的一个空白字符可以与输入中任意数量的空白字符相匹

配。(附带提一下,在格式串中包含空白字符并不意味着输入中必须包含空白字符。格

式串中的一个空白字符可以与输入中
任意
数量的空白字符相匹配,包括零个。)

其他字符
当在格式串中遇到非空白字符时,scanf函数将把它与下一个输入字符进行

比较。
如果两个字符相匹配,那么
scanf
函数会放弃输入字符而继续处理格式串。如果

两个字符不匹配,那么
scanf
函数会把不匹配的字符放回输入中,然后异常退出,而不

进一步处理格式串或者从输入中读取字符。

例如,假设格式串是"%d/%d"。如果输入是:

·
5/
·
96

在寻找整数时,
scanf
函数会跳过第一个空格,把
%d

5
相匹配,把
/

/
相匹配,在寻找下一个整数时跳过一个空格,并且把%d

96
相匹配。另一方面,如果输入是:

·
5
·
/
·
96

scanf
函数会跳过一个空格,把
%d

5
相匹配,然后试图把格式串中的
/
与输入中的空格相匹配。但是二者不匹配,所以scanf
函数把空格放回原处,把字符·
/
·
96
留给下一次
scanf
函数调用来读取。为了允许第一个数后边有空格,应使用格式串"%d /%d"

3.2.3 易混淆的 printf 函数和 scanf 函数🚀

问与答(很重要)🚀

*问:转换说明%i****也可以用于读写整数。%i和**%d**之间有什么区别?(p.27)

*
答:在
printf
格式串中使用时,二者没有区别。但是,在
scanf
格式串中
%d
只能与十进制(基数为
10
)形式的整数相匹配,而%i
则可以匹配用八进制(基数为
8
)、十进制或十六进制(基数为
16
)表示的整数。如果输入的数有前缀0
(如
056
),那么
%i
会把它作为八进制数(
7.1
节)来处理;如果输入的数有前缀0x

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

*
答:在
printf
格式串中使用时,二者没有区别。但是,在
scanf
格式串中
%d
只能与十进制(基数为
10
)形式的整数相匹配,而%i
则可以匹配用八进制(基数为
8
)、十进制或十六进制(基数为
16
)表示的整数。如果输入的数有前缀0
(如
056
),那么
%i
会把它作为八进制数(
7.1
节)来处理;如果输入的数有前缀0x

[外链图片转存中…(img-dTtKaFQ4-1715886026174)]
[外链图片转存中…(img-7QTiliX2-1715886026175)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值