[C和指针] ch15. 输入 / 输出函数

第十五章:输入 / 输出函数

Github 链接:ch15. 输入 / 输出函数

IO 操作在工作中、项目中是相当常用的。文件的读取和写入都离不开这些函数,然而在平时简单的日常练习中是被经常忽略的点。还是得多练练的,简单知道函数原型,在使用的时候再查找相关文档进行细致的学习即可。

本章总结及注意点

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-svP2QmpH-1609746502962)(https://raw.githubusercontent.com/Y-puyu/picture/main/images/20210104102214.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qOw8JaFy-1609746502965)(https://raw.githubusercontent.com/Y-puyu/picture/main/images/20210104103148.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZLRmUAJa-1609746502966)(https://raw.githubusercontent.com/Y-puyu/picture/main/images/20210104104007.png)]


部分课后习题解答

15.20 问题

  1. 首先,fopen() 的函数原型为:FILE *fopen(char const *name, char const *mode);fopen 打开失败,则返回一个 NULL 指针,其传递给后续的 IO 函数时则不能达到预期,函数执行失败,但是程序是否失败这个得看编译器。如果程序不终止,则会操作内存中一块不可预料的位置的内容!

  2. 我记得 FILE 就是个结构体,在此未被初始化,则程序失败,也可能修改一块不可预料的内存中的内容。

  3. fclose() 函数调用失败一般是产生了一个 bug,需要发现并修复。如果大量的 fclose() 函数均调用失败,则资源无法及时释放,则不能创建过多的流,无法再打开过多的文件。

  4. 没怎么想过这个问题,待我深入 Linux 内核去瞅瞅哈哈。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OkqYvcPD-1609746502967)(https://raw.githubusercontent.com/Y-puyu/picture/main/images/20210104105805.png)]

  5. 书中提及过:NUL 字节总是留有空间,因此如果缓冲区大小为 1,那么就没有空间容纳任何 char 来自流的角色。如果缓冲区大小为 2,则逐个读取字符。

  6. 没太想清楚第一个值为啥最多是 6 个字符…答案:第一个值最多 6 个字符,第二个最多 1 个字符,第三个最多 4 个字符。算上两个空格和结束的 NUL 字节,缓冲区必须至少有 14 个字节长。

  7. 没有办法知道缓冲区必须有多大,除非提前能知道字符串的最长长度限制,如果在此语句之前没有检查 a 的长度,缓冲区可能会溢出不管它有多大。

  8. 好问题,浮点数本来就有经度丢失的现象,如果再多轮进行浮点数计算,那么结果将失真。在此如果 3.14159 打印的代码是 %.3f。结果是 3.142。

  9. 没这样做过,见答案学习一下:编写一个程序在 errno 中存储所有可能的整数值,然后调用 perror。必须注意输出,因为对于不是合法错误代码的值可能会产生垃圾。

  10. 涉及到函数传参问题。因为它们要改变流的状态,C 值传递只是一份拷贝,并不会实际改变流的状态。

  11. r+ 模式就可以了。w 模式截断文件,a 模式限制写入文件的末尾。

  12. 它允许一个特定的流重新打开到一个新的文件。例如,一个程序如果使用 printf 开始写入另一个文件,程序将不得不重新打开 stdout。这个函数是实现这一目标的可靠方法。

  13. 不值得。只有当一个项目有极高的速度、空间限制的时候,即其不够快或不够小的时候才去想想这些事情。

  14. 150087600。浮点数存取规则,以及采用 %d 来取字节翻译为整数。结果取决于制度,但它不会是3!

  15. 字符串将左对齐。至少打印 6 个字符,但不超过 10 个。

  16. 常见坑点问题了。若实际值为 1.4049,那么前者肯定就是 1.405 了。后者自然就是 1.40。只会查看截断位置的下一个是否可以尽心四舍五入。

15.21 编程练习

  1. getchar()putchar() 的使用即可。见 demo02.c

  2. 长度限制已经给出,若是 gets() ,则缓冲区大小为 81,因为要存储一个 NUL 字节。若为 fgets() 则需要 82 大小,因为其还要存储一个换行符。见 demo03.c

  3. 常见问题。使用 fgets() 来确保缓冲区不会被更长的输入行溢出。见 demo04.c

  4. 进一步拓展。答案给的代码很清晰!非常值得学习,将打开文件操作封装为一个函数,参数为文件名和打开模式。真的诗一样的代码!见 demo05.c

  5. 利用 fgets() 读取一行进入缓冲区,再利用 sscanf() 从缓冲区读取一个数字进入局部变量中,拿返回值判断其是否类型匹配为一个整数,若类型不匹配则输入停止。关于 sscanf() 函数也是蛮重要的,可见 P308P310-P312。见 demo06.c

  6. 是一个经典问题了,可以参考我的博文:[E模拟] lc9. 回文数(模拟+字符串+边界判断)
    。给出了三种方法,其中最后一种折半的思想及效率都是非常出色的!在此使用 sprintf() 函数挺不错的,将数字转到字符数组中进行存储,整数的话直接就是位数,而浮点数,如果格式化字符串没有规定小数位数,例如 double 类型,采用 %f 来进行格式化,那么会保留 6 位小数。不小心的话非常容易引起数组越界的错误!见 demo07.c、demo08.c

  7. 答案:最多 10 个成员的限制使得使用 fgetssscanf。假设每个年龄最多为三位数字(加上一个分隔空格),则缓冲区为 40 个字符就足够了。但是,问题说明并没有说被恰好一个空白字符分隔,所以这个解决方案使用一个 512 字符的缓冲区 acters 代替。如果你知道一些关于输入的性质(例如,它是用一个编辑器的最大行大小是 512 字节),那么这种方法就很好。否则,这是有风险的而且你应该动态地分配一个可以扩展的缓冲区,每当发现一行太长了。见 demo09.c

  8. 答案:虽然在问题陈述中没有明确指定,但一个重要的考虑事项是该做什么当转储文件的长度不为16字节的偶数倍时。一个简单的方法是简单地将丢失的字节报告为零。下面的解决方案构造了每一个将行放入内存中的缓冲区;这使得只打印部分中出现的数据变得更容易最后一行,仍然保持正确的格式。该程序将更容易修改时有人出现并想要改变格式(这是不可避免的)已经定义的名称用于与格式相关的数字,而不是文字常量。见 demo10.c

  9. 这几道题都不怎么想写了,初步学习它的思想即可。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Em2EapPT-1609746502968)(https://raw.githubusercontent.com/Y-puyu/picture/main/images/20210104151812.png)]。

  10. demo11.c

  11. 建议去参考英文答案,很详细,很多,多到直接跳过的那种…

随笔

重点是重点,得多做做实验,玩一玩文件的操作。几个函数也需要知道它是干啥的就行了。

疑问

  1. 编程练习 9、10、11 简直就离谱了…本身也比较困,日后再补补看吧,不过大概率是不会补了。

  2. 本章内容蛮枯燥的,加上中间有些事情需要处理,断断续续整了有一周才整理完毕,就很慢…再看下一本书的 IO 相关内容的时候会拿出来对比着学习和复习一遍!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值