标准I/O基础概念
标准I/O(Standard Input/Output)是C语言提供的一组高级文件操作函数,位于<stdio.h>头文件中。与低级I/O(如Unix的系统调用read/write)相比,标准I/O引入了缓冲机制,能显著提升读写效率。核心概念包括:
- 文件指针(FILE)*:指向FILE结构的指针,用于标识打开的文件流
- 缓冲类型:全缓冲、行缓冲、无缓冲
- 文本流与二进制流:文本流会处理换行符转换,二进制流直接读写原始数据
文件打开与关闭
fopen函数
FILE *fopen(const char *filename, const char *mode);
参数:
filename
:文件路径字符串mode
:打开模式:"r"
:只读(文件必须存在)"w"
:只写(创建新文件或清空已有文件)"a"
:追加(在文件末尾写入)"r+"
:读写(文件必须存在)"w+"
:读写(创建新文件或清空已有文件)"a+"
:读写(从文件末尾开始)- 附加
b
表示二进制模式(如"rb"
)
返回值:成功返回FILE指针,失败返回NULL
fclose函数
int fclose(FILE *stream);
- 参数:要关闭的文件流指针
- 返回值:成功返回0,失败返回EOF
- 注意:关闭前会刷新缓冲区,多次关闭同一流会导致未定义行为
字符I/O操作
fgetc函数
int fgetc(FILE *stream);
- 从指定流读取一个字符
- 返回值:成功返回读取的字符(转为unsigned char再转int),失败或到达文件尾返回EOF
fputc函数
int fputc(int c, FILE *stream);
- 向指定流写入一个字符
- 参数:
c
会被转为unsigned char写入 - 返回值:成功返回写入的字符,失败返回EOF
使用示例:
// 文件复制示例
FILE *src = fopen("input.txt", "r");
FILE *dst = fopen("output.txt", "w");
int ch;
while ((ch = fgetc(src)) != EOF) {fputc(ch, dst);
}
fclose(src);
fclose(dst);
行I/O操作
fgets函数
char *fgets(char *str, int n, FILE *stream);
- 从流中读取最多n-1个字符到str缓冲区
- 遇到换行符或EOF时停止,换行符会被保留
- 缓冲区末尾自动添加'\0'
- 返回值:成功返回str指针,失败或到达文件尾返回NULL
fputs函数
int fputs(const char *str, FILE *stream);
- 将字符串写入流,不包含结尾的'\0'
- 返回值:成功返回非负值,失败返回EOF
使用示例:
// 行计数示例
FILE *fp = fopen("file.txt", "r");
char buffer[256];
int lines = 0;
while (fgets(buffer, sizeof(buffer), fp)) {lines++;
}
fclose(fp);
格式化I/O操作
fscanf函数
int fscanf(FILE *stream, const char *format, ...);
- 从流中按指定格式读取数据
- 格式字符串与scanf相同
- 返回值:成功匹配并赋值的参数个数,失败或到达文件尾返回EOF
fprintf函数
int fprintf(FILE *stream, const char *format, ...);
- 按指定格式向流写入数据
- 格式字符串与printf相同
- 返回值:成功写入的字符数,失败返回负值
使用示例:
// 结构化数据读写
typedef struct {int id;char name[50];float score;
} Student;FILE *fp = fopen("data.txt", "w+");
Student s = {1, "Alice", 95.5f};
fprintf(fp, "%d %s %f\n", s.id, s.name, s.score);rewind(fp);
Student new_s;
fscanf(fp, "%d %49s %f", &new_s.id, new_s.name, &new_s.score);
fclose(fp);
错误处理与状态检查
ferror:检查流错误标志
int ferror(FILE *stream);
feof:检查文件结束标志
int feof(FILE *stream);
clearerr:清除错误和EOF标志
void clearerr(FILE *stream);
正确使用模式:
while (1) {ch = fgetc(fp);if (feof(fp)) break;if (ferror(fp)) {perror("Read error");break;}// 处理字符
}