IO
(Input & Output)操作,即输入 & 输出操作,是程序与系统、用户交互的重要渠道。程序可以从命令行、本地文件、网络、数据库以及其他途径获取输入,并向这些地方输出内容,这些操作合称 IO
操作。C
的IO操作部分定义于 stdio.h 头文件。
C
程序会将一切设备都视为文件,对设备的处理方式和一般文件无异。 C
使用文件指针来访问文件。
关于IO操作函数的详细解释见 stdio.h 。
命令行IO
在程序运行时,会自动打开以下三个文件以供基本的命令行输入输出。
名称 | 文件指针 | 设备 |
---|---|---|
标准输入 | stdin | 键盘 |
标准输出 | stdout | 屏幕或命令行窗口 |
标准错误 | stderr | 屏幕或命令行窗口 |
这些文件输入、输出的背后,有一片临时存放数据的区域,称为缓冲区。从 stdin
输入的数据会先存入缓冲区,供程序读取;向 stdout
发送的输出会先送入缓冲区,达到某一条件时再传递数据给 stdout
; stderr
则不存在缓冲区,向其发送到数据会直接送入 stderr
。
printf
printf
函数是最基本的输出函数,用于将内容输出到 stdout
,然后在命令行窗口上呈现。
printf
定义如下:
1 | int printf(const char* format, ...); |
printf
函数返回输出的总字符数。
格式化字符串
printf
的输出即格式化输出,格式化字符串中的格式化占位符会被替换为对应格式的表达式值。这些占位符都以半角百分号 %
开头,每种占位符对应不同的数据类型。
1 | printf("This %s is %d years old.\n","dog",4); |
scanf
scanf
用于读取输入。在调用 scanf
函数时,程序会阻塞,直到可以从缓冲区读取数据。
scanf
定义如下:
1 | int scanf(const char* format, ...); |
gets & puts
gets
、 puts
用于读取、输出字符串,定义如下:
1 | char* gets(char* str); |
gets
相当于 scanf("%s",str)
,若读取成功则返回 str
,读取失败则返回 NULL
。
puts
相当于 printf("%s\n",str)
,若输出成功则返回非负值,输出失败则返回 EOF
。
getchar & putchar
getchar
、 putchar
用于读取、输出单个字符,定义如下:
1 | int getchar(void); |
getchar
相当于 scanf("%c",c)
,若读取成功则返回字符对应的 ASCII
编码,读取失败则返回 EOF
。
putchar
相当于 printf("%c",c)
,若输出成功则返回字符对应的 ASCII
编码,输出失败则返回 EOF
。
文件IO
C
除了对 stdin
这种虚拟文件的读写,可也以读写真正的文件。使用 fopen
函数可以打开文件并创建文件指针(亦称文件流),然后即可对文件指针进行读写操作。
1 | FILE* fopen(const char* filename, const char* mode); |
mode
为文件的读写模式,有如下几种:
模式 | 描述 |
---|---|
r | 以只读模式打开文件,文件不存在则返回 NULL |
w | 创建一个用于写入的空文件,如果文件已经存在会删除已有的文件再创建新文件 |
a | 以追加模式打开文件,将写入的内容追加到原文件末尾,文件不存在则创建空文件 |
r+ | 以读写模式打开文件,可以读取也可以写入,文件不存在则返回 NULL |
w+ | 创建一个用于读写的空文件,如果文件已经存在会删除已有的文件再创建新文件 |
a+ | 以追加与读取模式打开文件,文件不存在则创建空文件 |
mode
可以附加参数b
和t
,例如wb+ rt ab
。b
表示以二进制模式读写,t
表示以文本模式读写。
若读取打开成功则返回文件指针 FILE*
,失败则返回 NULL
并将错误储存在全局变量 errno
中(需 errno.h
头文件)并使用 strerror
函数查看错误信息。
1 |
|
在文件使用完毕后,使用 fclose
关闭文件,保存修改,释放资源。
在对文件进行读写操作时,确保和打开文件的模式匹配。
在打开文件时,文件会载入文件缓冲区,读写都在这个缓冲区中进行。但是与
stdin
的缓冲区不同,读取文件缓冲区时不会移除已读取的数据,而是移动缓冲区中的数据游标到下一块数据的位置。通过fseek
函数可以移动游标的位置。
在读取文件时,以
EOF
结束文件数据。当读取到EOF
时表示文件已经读取完毕。
fprintf
printf
的文件输出版本,定义如下:
1 | int fprintf(FILE* stream, const char* format, ...); |
除了是向文件输出内容,其余部分和 printf
完全一致。
fscanf
scanf
的文件输入版本,定义如下:
1 | int fscanf(FILE* stream, const char* format, ...); |
除了是从文件读取内容,其余部分和 scanf
完全一致。
fgets & fputs
分别为 gets
、 puts
的文件读写版本,定义如下:
1 | char* fgets(char* str, int n, FILE* stream);//n为要读取的字符数(包括字符串结束符的位置,实际读取的字符数为n-1) |
fgetc & fputc
分别为 getchar
、 putchar
的文件读写版本,定义如下:
1 | int fgetc(FILE* stream); |
fgetc
如果读取到了缓冲区的结束符EOF
则会返回EOF
。
stdin
和stdout
作为虚拟文件,也可以使用这些函数进行读写。
写在最后
IO操作是程序最基本的一环之一,因为涉及程序外部的内容,在进行IO操作时一定要做好异常处理。