一、字符输入:getchar()必须返回int类型
错误案例:
char c;
while ((c = getchar()) != EOF) { // 错误:c是char类型
putchar(c);
}
错误原因:
- 若
char为有符号类型:正常字符0xFF(ÿ)会被误判为EOF - 若
char为无符号类型:EOF(-1)转为0xFF(255),循环永不终止
正确写法:
int c; // 必须用int存储
while ((c = getchar()) != EOF) {
putchar(c);
}
原理:
int类型可同时存储字符值(0~255)和EOF(-1),确保判断准确。
二、文件读取:避免feof导致最后一行重复
错误案例:
while (!feof(infp)) { // 错误判断
fgets(buf, sizeof(buf), infp);
fputs(buf, outfp);
}
错误原因:
feof仅在读取失败后返回真。当文件末尾无换行符时:
- 首次
fgets读取最后一行 → 输出 - 再次循环时
fgets读取失败,但buf仍存有旧数据 → 重复输出
正确写法:
while (fgets(buf, sizeof(buf), infp) != NULL) { // 检查fgets返回值
fputs(buf, outfp);
}
关键原则:
- 用输入函数返回值(如
fgets != NULL)判断读取成功 feof仅用于读取失败后区分文件结束/错误:if (feof(infp)) printf("文件结束"); else perror("错误");
三、混合IO:解决scanf与fgets的换行符残留
错误案例:
scanf("%d", &num); // 输入"123\n"后残留'\n'
fgets(buf, 100, stdin); // 读到'\n',buf为空行
解决方案:
- 清除残留字符
scanf("%d", &num); int c; while ((c = getchar()) != '\n' && c != EOF); // 清空缓冲区 - 完全用
fgets+sscanf替代fgets(num_buf, 100, stdin); // 读取整行 sscanf(num_buf, "%d", &num); // 解析数据 fgets(str_buf, 100, stdin); // 无残留问题 strchr(str_buf, '\n')[0] = '\0'; // 移除换行符(可选)
优势:
fgets+sscanf彻底避免换行符干扰,是文档推荐做法。
标准IO库核心避坑准则
getchar()返回值必存int- 禁止单独用
feof判断文件结束 → 检查输入函数返回值 - 绝对不用
gets→ 用fgets(buf, size, stdin)替代 scanf后清除残留 →while((c=getchar())!='\n'&&c!=EOF)- 处理
fgets的换行符 →strchr(buf, '\n')[0] = '\0' - 二进制文件用
"rb"/"wb"模式 → 避免换行符转换 - 检查所有IO函数返回值 → 包括
fopen,fread,scanf等 - 禁止
fflush(stdin)→ 清除输入流用while(getchar()...)
遵循这些准则可规避90%的标准IO陷阱。核心思想:明确函数行为边界(如
EOF本质是状态码而非字符)、严格检查返回值、保持IO操作一致性(避免混合使用不同抽象层的函数)。
7571

被折叠的 条评论
为什么被折叠?



