20201306吴龙灿第九章学习笔记
作者:互联网
第九章学习笔记
知识点归纳
第九章讲了I/O库函数,也就是C语言的相关文件操作。
这里大概分成了五个主要部分部分:
1. 系统调用
课本将I/O函数库与系统调用充分联系到了一起,除了讲了两者之间的差别,更重要的是强调两者之间的相似性。并举例说明了诸如显示文件内容、复制文件在系统调用和I/O库函数之间的区别,而且特别强调了二者运行方式相似的同时所含有的根本区别,就是针对于缓冲区二者的利用不尽相同。
2. I/O库函数算法
(1) fread算法
强调此算法在第一次调用的时候,函数使用保存的文件描述符发出一个:
n=read(fd,fbuffer,BLKSIZE);
的系统调用,会用数据块填充fbuf【】的内部。随后在每一次调用的时候都会对FILE结构体内部缓冲区进行调用。
(2) fwrite算法
这个算法和上一个算法极其类似,区别就在一二者的方向是相反的。此算法目的是先判断缓冲区是不是已经满了,满了,就直接系统调用write()函数。
(3) fclose算法
使用fclose()函数就可以把缓冲区内最后剩余的数据输出到内核缓冲区,并释放文件指针和有关的缓冲区。
3. I/O库模式
此部分内容相对重要的有两点:
(1) 字符模式I/O
函数的返回值都是单个字符,目的就在于要与文件流中的所有元素的类别都要区分开。最终的结果都是只针对字符而言的。
(2) 行模式I/O
与字符模式I/O的区别在于,函数的返回值都是字符串,相应的改变也在于最终的结果是针对字符串而言的。
4. 文件缓冲系统
缓冲区的本质是一块存储区域。
我们将缓冲区分为全缓冲、行缓冲和无缓冲。
全缓冲:我们缓存在缓冲区的东西在缓冲区满的时候,才写入磁盘或者我们调用fflush刷新缓冲区才能写入到磁盘。对于全缓冲,如果我们缓冲区没满,或者我们没有手动刷新缓存,那么缓存区的内容是不能写入到磁盘的。
行缓冲:我们标准输入、标准输出都是采用的行缓存,也就是遇到换行符的时候,才会将缓存区的东西写入到磁盘。
无缓冲:有的时候,我们希望一些内容在第一时间写入磁盘或者显示出来,比如我们显示错误信息的时候,这时候典型的例子比如标准出错,它就是直接显示出错信息,而不会先放入缓存。
5. 变参函数
诸如printf()这样的函数有一个十分重要的性质,那就是里边的参数的数量是可以改变的。在此类函数内部进行着一系列操作,使用宏访问参数。
要创建变参函数需要包含头文件stdarg.h,并且创建变参函数应按照如下步骤进行:
【第一步】定义一个使用省略号的函数原型,如printf()与scanf()函数的原型为
int printf (const char __format, ...)
int scanf (const char, ...);
【第二步】在函数定义中创建一个va_list类型的变量,用于存储不定的参数;
【第三步】用宏va_start把该变量初始化为一个参数列表;
【第四步】用宏va_arg访问参数列表;
【第五步】用宏va_end完成清理工作。
示例程序:
#include <stdio.h>
#include <stdarg.h>
*double sum(int lim, ...) *
{
va_list ap;
double sum = 0;
int i;
va_start(ap, lim);
for (i = 0; i < lim; i++)
{
sum += va_arg(ap, double);
}
va_end(ap);
return sum;
}
int main(void)
{
double sum1 = 0, sum2 = 0;
sum1 = sum(3, 1.1, 2.2, 3.3);
sum2 = sum(6, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
printf("sum1 = %f\n", sum1);
printf("sum2 = %f\n", sum2);
return 0;
}
20201306吴龙灿同学最有收获的地方
因为在学习程序设计基础和数据结构的时候,我已经接触了一部分有关文件的内容。我也曾经自己设计编译过一个客户信息管理系统,这里就用到了fopen()、fwrite()等I/O库函数。
但是经过了这次更为深刻的学习之后,我对于文件的理解尤其是系统调用和利用I/O库调用之间的关系理解更为深刻。举一个例子:open()和fopen()相同点和不同点。
第1行:在系统调用程序中,文件描述符fd是一个整数;在库I/O程序中,fp是一个文件流指针。
第2行:系统调用open()打开一个文件进行读取,并返回一个整数文件描述符fd,弱国open()失败,则返回-1.I/O库函数fopen()返回一个FILE结构体指针,如果fopen()失败,则返回NULL。
第3行:系统调用程序使用while循环读取/写入文件内容。在每个迭代中,它发出read()系统调用,将最多4KB的字符读入buf[]。然后,它将个字符从buf[]写道文件描述符l中,这是该进程的标准输出。使用系统调用一次写入一个字节非常低效。相反,I/O库程序仅仅使用fgetc(fp)从文件流中获取字符,通过putchar()输出字符,直至文件结束。
问题
为什么要有缓冲区呢?
解决思路
查阅了相关资料之后,我知道了当计算机的高速部件与低速部件通讯时,必须将高速部件的输出暂存到某处,以保证高速部件与低速部件相吻合。通常情况下,就是为了高效的处理我们的cpu和i/o设备之间的交互,因为我们知道cpu处理速度是很快的。举个例子,电脑的cpu通常情况下要处理很多事务,而我们从键盘敲下的文字相对于cpu的处理是很慢的,cpu不能老等着我们,它可以这时候去处理别的事务。所以当我们敲小的文字被先放到了缓冲区,等待cpu最后的统一处理。这样就让计算机的cpu变得高效起来。
实验内容与截图
首先,我打算熟悉一下I/O库函数的算法,利用教材提供的题目,我自行编写一个C程序,将文本文件中的字母由小写转换成大写。
#include <stdio.h>
*int main(int argc,char argv[])
{
FILE fp,gp;
char c;
fp=fopen("words.txt","r");
gp=fopen("bigwords.txt","w");
if(fpNULL||gpNULL){
printf("fail to open it\n");
return 0;
}
while((c=fgetc(fp))!=EOF){
if(c>='a'&&c<='z')
c=c-32;
fputc(c,gp);
}
fclose(fp);
fclose(gp);
return 0;
}
心得体会
对于之前已经接触过的一类知识点,我对于I/O库的学习还算比较轻松,虽然书上的难点有些我还是很难接受,就比如我针对于这些I/O库函数的算法具体的内部函数的原理是怎样的我还不清楚,尤其是最早就听说了关于缓冲区溢出这一类问题当时不怎么了解,现在也了解了缓冲区的机制。缓冲区就像是一个临时停靠的地方,就比如书架,常用的书放在外边,不常用的书放在里面,这大大降低了检索带来的时间上的浪费。对于这一章函数的运用我受到了一定程度的启发,那就是既然C语言是一个面向过程的编程语言,我们如果能利用好I/O库,那么编程对于我们而言将很大程度上降低算法的复杂性,这就是我的收获。
标签:va,调用,函数,文件,第九章,算法,吴龙灿,缓冲区,20201306 来源: https://www.cnblogs.com/wulongcan20201306/p/16684994.html