学习笔记 第九章

I/O库函数

I/O库函数是一系列文件操作函数。

I/O库函数与系统调用:


  • 系统调用函数:open()、read()、write()、lseek()、close();
  • I/O库函数:fopen()、fread()、fwrite()、fseek()、fclose()。

fopen():用于对文件和终端的输入输出。

函数原型:#include <stdio.h>

FILE *fopen(const char *filename, const char *mode);

mode参数如下所示:

"r"/"rb":只读方式打开

"w"/"wb":只写方式打开,把文件长度截为0

"a"/"ab":只写方式打开,新内容追加到文件尾

"r+"/"r+b"/"rb+":以修改方式打开

"w+"/"w+b"/"wb+":以修改方式打开,同时把文件内容截为0

"a+"/"a+b"/"ab+":以修改方式打开,新内容追加到文件结尾

fread():用于从一个文件流里读取数据,数据从stream读到由ptr指定的数据缓冲区里面。

函数原型:#include <stdio.h>

size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);

fwrite(): 从stream获取数据记录写到ptr中,返回值是成功写入的记录个数。

函数原型:#include <stdio.h>

size_t fwrite(const void *ptr, size_t size, size_t items, FILE *stream);

fseek():在文件流里面为下一次读写指定位置。

函数原型:#include <stdio.h>

int fseek(FILE *stream, long int offset, int whence);

fclose():关闭指定的文件刘stream,使所有未写出的内容全部写出。

函数原型:#include <stdio.h>

int fclose(FILE *stream);


文件流缓冲

setvbuf(FILE *stream, char *buf, int node, int size)

设置缓冲区(buf)、缓冲区大小(size)、缓冲方案(mode)


  • _IONBUF 无缓冲:从非缓冲流中写入或读取的字符,将尽快单独传输到文件或从文件中传输。 如:stderr
    学习笔记2(20191222何雨蔚)_#include
  • _IOLBUF 行缓冲:遇到换行符时,写入行缓冲流的字符以块的形式传输。如:stdout
    学习笔记2(20191222何雨蔚)_#include_02
  • _IOFBUF 全缓冲:写入全缓冲流或从中读取的字符以块大小传输到文件或从文件传输。这是文件流的正常缓冲方案。
    学习笔记2(20191222何雨蔚)_#include_03

变参函数

在I/O库函数中,多种不同类型的可变数量参数被允许调用printf()。 需至少使用一个参数进行声明,如:

int func(int m, int n, ...)

通过c语言库宏访问参数

void va_start(va _ list ap, last); //从最后一个参数开始启动参数列表

type va_arg(va _ list ap, type); //类型=下一个参数类型

va _ end(va _ list ap); //清空参数列表

编写类printf函数

项目规范

在Linux中,putchar(char c)可打印一个字符

int myprintf(char *fmt, ...)

fmt(格式字符串),包含:%c单个字符、%s字符串、%u无符号数、%d十进制整数、%x十六进制数

基本代码


  • 打印十进制无符号数
    学习笔记2(20191222何雨蔚)_数据_04

函数rpu(x)以ASCII 递归生成x% 10数字,并在返回路径上打印它们。例如,如果x=123,则按'3'、*2'、'1'的顺序生成数字,按应有的顺序打印为'1'、2'、'3'。

myprintf()的算法

假设格式字符串fmt =“char=%c string=%s integer -%d u32=%x\n"。这意味着分别有 char、char*、 int、 unsigned int和type的4个附加参数。myprint()的算法如下:

(1)扫描格式字符串fmt。打印任何不是%的字符。对于每个‘\n’ 字符,打印一个额 外的‘\r' 字符。

(2)当遇到‘%’时,得到的下一个字符必须是‘c'、's'、'u'、‘d’或‘x’中的 -个。使用va_ arg(ap, type)来提取相应的参数。然后通过参数类型调用打印函数。

(3)当fmt字符串扫描结束时,算法结束。


问题与解决思路

问题1:在书上的示例9.6中,实现无缓冲时用mode是_IONBUF,同时使用stdout行缓冲文件流。在学习网上的代码时也发现许多这样使用的,为什么实现无缓冲要使用文件流stdout而非stderr?

解决思路:查阅资料得知,stderr 主要处理的错误信息输出。将"正常输出"和"错误信息输出"加以分离,可以让程序以不同的方式对待两种不同的输出,例如可以将错误信息显示在控制台上,而正常输出重新定向到某个文件上。

问题2:文件操作都有什么?

解决思路:见学习笔记。

问题3:二进制文件和文本文件如何转换?

解决思路:文本文件和二进制文件的区别在于打开这个文件的程序在对文件内容的解释,文件本身存储在电脑上的都是二进制。首先创建一个二进制文件,然后打开(使用-b),在命令模式下键入::%!xxd,然后进入编辑模式更改数据以测试,回到命令模式输入::%!xxd -r,最后保存:wq。

aggregatepagefirst_rank_ecpm_v1~rank_aggregation-3-93232260.pc_agg_rank_aggregation&utm_term=C%E8%AF%AD%E8%A8%80%E6%96%87%E4%BB%B6%E8%AF%BB%E5%8F%96%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%BD%93&spm=1000.2123.3001.4430