ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

20201306吴龙灿第九章学习笔记

2022-09-11 22:33:41  阅读:153  来源: 互联网

标签:va 调用 函数 文件 第九章 算法 吴龙灿 缓冲区 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

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有