第7章 输入与输出
1. 标准输入/输出基础
1.1 标准I/O函数概述
printf()
:格式化输出函数,支持多种数据类型转换scanf()
:格式化输入函数,需注意变量地址传递- 字符I/O:
getchar()
:从标准输入读取单个字符putchar(c)
:输出单个字符
- 字符串I/O(已废弃,不安全):
gets()
/puts()
1.2 格式化输出详解
printf("格式字符串", 参数列表);
- 格式说明符:
%d
:整数%f
:浮点数%c
:字符%s
:字符串%p
:指针地址
- 修饰符:
%5d
:最小宽度5%.2f
:保留2位小数%-10s
:左对齐
重点难点:
- 格式字符串与参数类型必须严格匹配
- 浮点数精度问题(
float
默认提升为double
)
2. 格式化输入
2.1 scanf()
基本用法
scanf("格式字符串", &变量);
- 必须使用取地址运算符
&
- 格式说明符与
printf()
类似
2.2 常见问题
- 缓冲区残留:换行符可能导致后续读取错误
- 输入匹配失败:类型不匹配时返回
EOF
- 安全性问题:字符串输入易导致缓冲区溢出
解决方案:
// 安全读取字符串
char buf[100];
fgets(buf, sizeof(buf), stdin);
3. 文件I/O操作
3.1 文件指针与基本操作
FILE *fp = fopen("文件路径", "模式");
fclose(fp);
- 打开模式:
"r"
:只读"w"
:写入(清空原内容)"a"
:追加"rb"
/"wb"
:二进制模式
3.2 文件读写函数
函数 | 描述 |
---|---|
fprintf(fp, ...) |
格式化写入 |
fscanf(fp, ...) |
格式化读取 |
fgetc(fp) /fputc(c, fp) |
字符I/O |
fgets(buf, size, fp) |
安全读取一行 |
fread() /fwrite() |
二进制块I/O |
重点难点:
- 二进制与文本模式区别(Windows换行符处理)
- 文件指针位置控制(
fseek()
/ftell()
)
4. 错误处理
4.1 错误检测函数
函数 | 作用 |
---|---|
ferror(fp) |
检查文件错误 |
feof(fp) |
检测文件结束 |
perror("提示") |
打印系统错误信息 |
4.2 最佳实践
FILE *fp = fopen("file.txt", "r");
if (fp == NULL) {
perror("打开文件失败");
exit(EXIT_FAILURE);
}
5. 高级I/O话题
5.1 可变参数函数
vprintf()
系列函数- 自定义可变参数函数:
#include <stdarg.h>
void log_message(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vprintf(fmt, args);
va_end(args);
}
5.2 缓冲机制
缓冲类型 | 特点 |
---|---|
全缓冲 | 缓冲区满时刷新(默认文件I/O) |
行缓冲 | 遇到换行符刷新(标准输出) |
无缓冲 | 立即输出(标准错误) |
手动刷新:
fflush(fp); // 强制刷新缓冲区
6. 实际应用示例
6.1 文件复制程序
void file_copy(FILE *src, FILE *dst) {
int c;
while ((c = fgetc(src)) != EOF) {
fputc(c, dst);
}
}
6.2 CSV文件解析
while (fscanf(fp, "%[^,],%d,%f\n", name, &age, &score) == 3) {
// 处理每条记录
}
7. 总结与最佳实践
7.1 关键原则
- 始终检查I/O函数返回值
- 优先使用安全函数(如
fgets
替代gets
) - 明确缓冲区管理策略
- 区分文本与二进制I/O需求
7.2 常见陷阱
scanf()
系列函数的安全问题- 文件打开未关闭导致资源泄漏
- 未处理EOF条件导致的死循环
7.3 性能优化
- 减少小数据量的频繁I/O操作
- 使用块读写(
fread
/fwrite
)处理大文件 - 合理设置缓冲区大小
本章是C语言系统级编程的基础,掌握这些I/O技术对文件处理、数据解析等任务至关重要。建议通过实际项目(如日志系统、数据转换工具)加深理解。