标准IO
1. 为什么要使用标准IO?
每个操作系统下面,对文件的管理和接口是不一样的!!!
同一个文件,在不同的操作系统下面,我们的操作文件的代码都不一样。
所以,C语言标准委员会,统一文件操作的接口。
标准IO库:主要统一对文件及常用接口的操作
"文件" : 普通文件和二进制文件
在标准IO库中,用结构体
FILE来描述或表示一个文件,然后在这个结构体中创建了两个缓冲区(内存/缓冲区),分别为读缓冲和写缓冲。缓存:同步问题
- 行缓冲:行缓冲缓冲区中的数据达到一行的时候,同步到外设上面去。
- 全缓冲:缓存区中数据要填满整个缓冲区,才会同步到外设上去
- 无缓冲:缓冲区有一个字节,就同步到外设上去。
2. 标准IO流(stdin, stdout, stderr)
#include <stdio.h> // 在其中定义
#define stdin
#define stdout
#define stderr
有三个文本流是预定义的。这些流在程序启动时隐式打开,且为无取向的。
- 与标准输入流关联,用于读取传统的输入。程序启动时,当且仅当能确定流不引用交互式设备时该流为完全缓冲。
- 与标准输出流关联,用于写入传统的输出。程序启动时,当且仅当能确定流不引用交互式设备时该流为完全缓冲。
- 与标准错误流关联,用于写入诊断输出。程序启动时,该流不为完全缓冲。
这些宏展开成
FILE类型的表达式。
3. 标准IO的函数接口
3.1 打开文件流
#include <stdio.h>
FILE *fopen( const char *filename, const char *mode );
FILE *fopen( const char *restrict filename, const char *restrict mode );
errno_t fopen_s( FILE *restrict *restrict streamptr,
const char *restrict filename,
const char *restrict mode ); //(C11)
参数:
filename: 关联到文件系统的文件名mode: 确定访问模型的空终止字符串文件访问模式streamptr: 指向存储函数结果的指针的指针
文件访问标记:
| 文件访问 模式字符串 | 含义 | 解释 | 若文件已存在的动作 | 若文件不存在的动作 |
|---|---|---|---|---|
| "r" | 读 | 打开文件以读取 | 从头读 | 打开失败 |
| "w" | 写 | 创建文件以写入 | 销毁内容 | 创建新文件 |
| "a" | 后附 | 后附到文件 | 写到结尾 | 创建新文件 |
| "r+" | 读扩展 | 打开文件以读/写 | 从头读 | 错误 |
| "w+" | 写扩展 | 创建文件以读/写 | 销毁内容 | 创建新文件 |
| "a+" | 后附扩展 | 打开文件以读/写 | 写到结尾 | 创建新文件 |
返回值:
-
成功 则返回指向新文件流的指针。流为完全缓冲,除非
filename表示一个交互设备。错误时,返回空指针。 -
失败 返回NULL
3.2 关闭文件
#include <stdio.h>
int fclose( FILE *stream );
关闭给定的文件流。冲入任何未写入的缓冲数据到 OS 。舍弃任何未读取的缓冲数据。
无论操作是否成功,流都不再关联到文件,且由
setbuf或setvbuf分配的缓冲区若存在,则亦被解除关联,并且若使用自动分配则被解分配。若在
fclose返回后使用指针stream的值则行为未定义。
参数:
- stream 需要关闭的文件流
返回值:
- 成功 0
- 失败
EOF。
3.3 直接读写
fread
size_t fread( void *restrict buffer, size_t size, size_t count,
FILE *restrict stream );
从给定输入流 stream 读取至多 count 个对象到数组 buffer 中,如同以对每个对象调用 size 次
fgetc,并按顺序存储结果到转译为unsigned char数组的buffer中的相继位置。
参数
buffer指向要读取的数组中首个对象指针size每个对象的大小count要读取的对象数stream读取来源的输入文件流
返回值
- 成功读取的对象数
- 若出现错误或文件尾条件,则可能小于 count 。
若 size 或 count 为零,则
fread返回零且不进行其他动作。
fread不区别文件尾和错误,而调用者必须用feof和ferror鉴别出现者为何。
fwrite
size_t fwrite( const void *restrict buffer, size_t size, size_t count,
FILE *restrict stream );
从给定数组 buffer 向输出流 stream 写入 count 个对象。各个对象的写入,如同将每个对象解读为 unsigned char 数组,并对每个对象调用 size 次
fputc以将那些 unsigned char 按顺序写入 stream 一般来进行。
参数
buffer指向要写入的数组中首个对象指针size每个对象的大小count要被写入的对象数stream指向输出流的指针
返回值
- 成功写入的对象数
- 若出现错误则可能小于 count 。
若 size 或 count 为零,则
fwrite返回零且不进行其他动作。
3.4 无格式的输入输出
| 函数名 | 功能 |
|---|---|
fgetc / getc |
从文件流获取一个字符 (函数) |
fgets |
从文件流获取一个字符串 (函数) |
fputc /putc |
将一个字符写入文件流 (函数) |
fputs |
将一个字符串写入文件流 (函数) |
getchar |
从 stdin 读取一个字符 (函数) |
gets(C11 中移除)/gets_s(C11) |
从 stdin 读取一个字符串 (函数) |
putchar |
将一个字符写入 stdout (函数) |
puts |
将一个字符串写入 stdout (函数) |
ungetc |
将一个字符送回文件流 (函数) |
3.4.1 fgetc / getc
#include <stdio.h>
// 从给定的输入流读取下一个字符
int fgetc( FILE* stream );
// 同fgetc,但若 getc 实现为宏,则它可能求值 stream 多于一次,所以实参始终不应为带有副作用的表达式。
int getc( FILE* stream );
参数
stream- 读取字符的来源
返回值
-
成功 返回作为 unsigned char 获得并转换为 int 的字符
-
失败 返回
EOF
3.4.2 fgets
#include <stdio.h>
char* fgets( char* str, int count, FILE* stream ); (C99 前)
char* fgets( char* restrict str, int count, FILE* restrict stream ); (C99 起)
从给定文件流读取最多 count - 1 个字符并将它们存储于
str所指向的字符数组。若文件尾出现或发现换行符则终止分析,后一情况下
str将包含一个换行符。若读入字节且无错误发生,则紧随写入到
str的最后一个字符后写入空字符。
参数
str指向char数组元素的指针count写入的最大字符数stream读取数据来源的文件流
返回值
- 成功 返回
str - 失败 返回空指针
3.4.3 fputc / putc
#include <stdio.h>
// 写入字符 ch 到给定输出流 stream 。
int fputc( int ch, FILE *stream );
// putc() 可以实现为宏并对 stream 求值超过一次,故对应的参数决不应是有副效应的表达式。
int putc( int ch, FILE *stream );
参数
ch- 要写入的字符stream- 输出流
返回值
-
成功 返回被写入字符
-
失败 返回
EOF并设置 stream 上的错误指示器
3.4.4 fputs
#include <stdio.h>
int fputs( const char* str, FILE* stream );(C99 前)
int fputs( const char* restrict str, FILE* restrict stream );(C99 起)
将以NULL结尾的字符串
str的每个字符写入到输出流stream,如同通过重复执行fputc。不写入
str的终止空字符。
参数
str要写入的空终止字符串stream输出流
返回值
- 成功 返回非负值
- 失败 返回
EOF并设置stream上的错误指示器
3.5 有格式的输入/输出
(1)scanf
scanf: 从stdin读取数据
fscanf: 从文件流stream读取数据
sscanf: 从空终止字符串buffer读取数据。抵达字符串结尾等价于fscanf的抵达文件尾条件。
#include <stdio.h>
int scanf( const char *restrict format, ... );
int fscanf( FILE *restrict stream, const char *restrict format, ... );
int sscanf( const char *restrict buffer, const char *restrict format, ... );
参数
stream要读取的输入文件流buffer指向要读取的空终止字符串的指针format指向指定读取输入方式的空终止字符串的指针...各接受实参
返回值
成功 赋值的接收参数的数量
(2)printf
printf: 将结果写入输出流stdout。
fprintf: 将结果写入输出流stream。
sprintf: 将结果写入字符串buffer。
snprintf: 将结果写入字符串buffer。至多写bufsz - 1个字符。
#include <stdio.h>
int scanf( const char *restrict format, ... );
int fscanf( FILE *restrict stream, const char *restrict format, ... );
int sscanf( const char *restrict buffer, const char *restrict format, ... );
int snprintf( char* restrict buffer, size_t bufsz,
const char* restrict format, ... );
参数
stream要写入的输出文件流buffer指向要写入字符串的指针bufsz最多会写bufsz - 1个字符,再加空终止符format指向指定数据转译方式的空终止字符串的指针...指定要打印数据的参数。
3.6 冲洗一个文件流(fflush)
将输出流与实际文件同步
#include <stdio.h>
int fflush(FILE *stream);
对于输出流(及最后操作为输出的更新流),从
stream的缓冲区写入未写的数据到关联的输出设备。对于输入流(及最后操作为输入的更新流),行为未定义。
若
stream是空指针,则冲入所有输出流,包括操作于库包内者,或在其他情况下程序无法直接访问者。
参数
stream- 要写入的文件流02
返回值
- 成功 返回零
- 失败 返回
EOF并设置文件流的错误指示器。
3.7 文件定位
(1) ftell
返回
stream的文件位置指示器若流以二进制模式打开,则由此函数获得的值是从文件开始的字节数。
若流以文本模式打开,则由此函数返回的值未指定,且仅若作为fseek()的输入才有意义。
#include <stdio.h>
long ftell( FILE *stream );
参数
stream要检验的文件流
返回值
- 成功 返回文件位置指示器,
- 失败 返回
-1L。
(2) fgetpos
获得文件流
stream的文件位置指示器和当前分析状态(若存在),并将它们存储于pos所指向的对象。存储的值仅在作为fsetpos的输入的情况有意义。
#include <stdio.h>
int fgetpos( FILE *restrict stream, fpos_t *restrict pos );
参数
stream : 要检验的文件流
pos : 指向要存储文件位置指示器到的fpos_t 对象的指针。
返回值
- 成功 0
- 失败 非0
(3)fseek 和 fsetpos
fseek
若
stream以二进制模式打开,则新位置恰好是文件起始后,或当前文件位置后,或文件结尾后的 offset 字节。若
stream以文本模式打开,则仅有的受支持offset值为零(可用于任何origin)和先前在关联到同一个文件的流上对ftell的调用的返回值(仅可用于SEEK_SET的origin)。
#include <stdio.h>
int fseek( FILE* stream, long offset, int origin );
参数
stream要修改的文件流offset相对origin迁移的字符数originoffset所加上的位置。(SEEK_SET、SEEK_CUR、SEEK_END)
返回值
- 成功 0
- 失败 非零
(4)fsetpos
按照
pos所指向的值,设置文件流stream的文件位置指示器和多字节分析状态(若存在)。
#include <stdio.h
int fsetpos( FILE *stream, const fpos_t *pos );
参数
stream要修改的文件流pos指向fpos_t对象的指针,用作文件位置指示器的新值。
返回值
- 成功 0
- 失败 非零
(5)rewind
移动文件位置指示器到给定文件流的起始。
函数等价于
fseek(stream, 0, SEEK_SET);,但它会清除文件尾和错误指示器。
#include <stdio.h>
void rewind( FILE *stream );
参数
stream要修改的文件流
3.8 错误处理(feof、ferror、perror)
feof: 检查是否已抵达给定文件流的结尾。ferror: 检查给定文件流的错误。perror: 打印当前存储于系统变量erron的错误码到stderr。
int feof( FILE *stream );
int ferror( FILE *stream );
void perror( const char *s );
注意
feof函数仅报告最近一次 I/O 操作所报告的流状态,而不检验关联的数据源。例如,若最近一次 I/O 是抵达文件最后字节的fgetc,则feof返回零。下个fgetc失败并更改流状态为文件尾。然后feof才返回非零。典型用法中,输入流处理在任何错误时停止;而
feof和ferror用于区别不同错误条件。

浙公网安备 33010602011771号