格式化输入输出
fprintf 和 fscanf 是文件的格式化读写函数,与 printf/scanf 类似但操作文件。格式化 I/O 适合读写结构化文本数据,但 fscanf 使用复杂且容易出错,需要谨慎处理。
fprintf
FILE *fp = fopen("data.txt", "w");
if (fp != NULL) {
int id = 42;
float score = 98.5;
char name[] = "Alice";
fprintf(fp, "%d %s %.1f\n", id, name, score);
fclose(fp);
}
fscanf
FILE *fp = fopen("data.txt", "r");
if (fp != NULL) {
int id;
char name[100];
float score;
while (fscanf(fp, "%d %99s %f", &id, name, &score) == 3) {
printf("ID: %d, Name: %s, Score: %.1f\n", id, name, score);
}
fclose(fp);
}
格式化字符串读写
char buffer[256];
sprintf(buffer, "Value: %d", 42); /* 写入字符串 */
int value;
sscanf(buffer, "Value: %d", &value); /* 从字符串读取 */
C99 snprintf
char buffer[10];
snprintf(buffer, sizeof(buffer), "Very long string %d", 123);
/* buffer 包含 "Very long" + '\0',不会溢出 */
常见错误
fscanf 缓冲区溢出:
char name[10];
fscanf(fp, "%s", name); /* 危险:输入超过 9 字符溢出 */
/* 正确 */
fscanf(fp, "%9s", name); /* 限制最多 9 字符 */
未检查返回值:
int x;
fscanf(fp, "%d", &x); /* 如果读取失败,x 未初始化 */
/* 正确 */
if (fscanf(fp, "%d", &x) == 1) {
/* 使用 x */
}
最佳实践
fscanf始终限制字符串长度- 检查
fscanf返回值(匹配项数) - 用
snprintf替代sprintf - 复杂解析考虑用
fgets+sscanf或专用解析器 - 浮点数注意精度问题