C 输入输出函数
流
就C程序而言,所有的I/O操作只是简单地从程序移入或移出字节的事情。这种字节流便称为流( stream )。
绝大多数流是完全缓存的,这意味着“读取”和“写入”实际上个是从一块被称为缓冲区的内存区域来回复制数据。
用于输出流的缓冲区只有当它写满时才会被刷新( flush ),写入到设备或文件中。一次性把写满的缓冲区写入和逐片把程序产生的输出分别写入相比效率更高。类似,输入缓冲区当它为空时通过设备或文件读取下一块较大的输入,重新填充缓冲区。
只有当操作系统可以断定它们与交互设备并无联系时才会进行完全缓冲。
每个流都有一个相应的FILE结构关联。
流分为文本流( text )和二进制流( binary ),对于每个ANSI C程序,运行时系统必须提供至少三个流
- 标准输入( standard input,
stdin
,键盘 ) - 标准输出( standard output,
stdout
,终端或屏幕 ) - 标准错误( standard error,
stderr
)
打开流
FILE*
fopen( char const *name, char const *mode );
FILE*
freopen( char const *filename, char const *mode, FILE *stream );
以mode
字段的格式打开文件名为name
的文件,执行成功返回一个指向FILE结构的指针,执行失败返回NULL
示例
FILE *fp;
fp = fopen( "data3.txt", "r" );
if( fp == NULL ){
perror( "data3.txt" );
exit( EXIT_FAILURE );
}
其中perror
是一个报告错误的函数,原型如下
void
perror( char const *message );
标准库函数在一个外部整型变量errno(在error.h中定义)中保存错误代码,当库函数失败时,errno才会被设置。当data3.txt不存在时,程序非正常退出,屏幕输出以下信息
data3.txt: No such file or directory
请按任意键继续. . .
freopen
函数用于打开或重新打开一个特定的文件流,首先试图关闭这个流,然后再按照mode
字段重新打开这个流
关闭流
int
fclose( FILE *f );
对于输出流,fclose
函数在文件关闭之前刷新缓冲区,执行成功返回零值,失败返回EOF
标准流I/O
以三种基本形式处理数据
- 单个字符
- 文本行
- 二进制数据
标准I/O常量
EOF
提示达到文件尾FOPEN_MAX
一个程序能同时打开这么多的文件FILENAME_MAX
文件名的最大长度
字符I/O
getchar家族
int
fgetc( FILE *stream );
int
getc( FILE *stream );
int
getchar( void );
getchar
始终从stdin
读取
putchar家族
int
fputc( int character, FILE *stream );
int
putc( int character, FILE *stream );
int
putchar( int character );
putchar
输出到stdout
撤销字符I/O
int
ungetc( int character, FILE *stream );
把先前读入的字符返回到流中
未格式化的文本行I/O
fgets和gets
char*
fgets( char *buffer, int buffer_size, FILE *stream );
char*
gets( char *buffer );
gets
只能用于stdin
,fgets
可以用于所有的输入流fgets
的第二个参数是缓冲区长度参数,它只读取输入的前buffer_size - 1
个字符;gets
没有缓冲区长度参数,当输入的字符长度大于缓冲区最大长度时,多出来的字符将写入到后面的内存位置,破坏了其他不相关变量的值fgets
会读入结尾的回车,gets
不会
fputs和puts
int
fputs( char const *buffer, FILE *stream );
int
puts( char const *buffer );
puts
默认输出到stdout
,fputs
可以用于所有的输出流puts
会在输出末尾追加一个回车,fputs
不追加
格式化的文本行I/O
scanf家族
int
fscanf( FILE *stream, char const *format, ... );
int
scanf( FILE *stream, char const *format, ... );
int
sscanf( char const *string, char const *format, ... );
- 每个原型中的省略号表示 一个可变长度的指针列表,从输入转换而来的值按顺序逐个存储到对应的内存位置
fscanf
从第一个参数给出的流读取,scanf
从stdin
读取,sscanf
从第一个参数给出的字符串中读取- 函数的返回值是被转换的输入值的个数,当文件到达尾部返回
EOF
printf家族
int
fprintf( FILE *stream, char const *format, ... );
int
printf( FILE *stream, char const *format, ... );
int
sprintf( char *buffer, char const *format, ... );
fprintf
输出到第一个参数给出的流,printf
输出到stdout
,sprintf
输出到第一个参数给出的字符串中sprintf
没有指明缓冲区大小的参数,解决方法是在format
字段限制输出的长度
二进制I/O
size_t
fread( void *buffer, size_t size, size_t count, FILE *stream );
size_t
fwrite( void *buffer, size_t size, size_t count, FILE *stream )
刷新和定位
int
fflush( FLIE *stream );
清空一个流的缓冲区,当stream
为stdin
时可用于吃掉回车
long
ftell( FILE *stream );
int
fseek( FILE *stream, long offset, int from );
void
rewind( FILE *stream );
ftell
返回流的当前位置fseek
在流中定位
from | |
---|---|
SEEK_SET | 起始位置起offset 个位置,offset 为非负数 |
SEEK_CUR | 当前位置起offset 个位置,offset 可正可负 |
SEEK_END | 尾部位置起offset 个位置,offset 可正可负,若为正值定位到文件尾后面 |
rewind
函数将指针设置回起始位置,同时清除错误提示标志