C++使用C风格IO读取文本统计元音并筛选写入新文件问题求解
问题解答
异常原因
你遇到的统计错误核心是字符串遍历逻辑错误:
- C语言中
fgets读取到的内容是合法的C风格字符串,会在有效内容的末尾自动添加\0作为结束标志,数组中超出有效长度的位置是未初始化的垃圾值 - 你当前的循环固定遍历1024个数组元素,会把有效内容后的垃圾值也纳入统计,自然会得到错误的元音计数
除此之外你的代码还有几处隐性问题: - 未校验文件打开结果:如果输入文件不存在、无读写权限,
fopen会返回空指针,后续读写操作会直接触发崩溃 - 仅统计了小写元音,大写A/E/I/O/U未纳入计数,会出现漏算
- 输出文件使用
a+追加模式,多次运行程序会导致结果累加,通常这类单次统计需求建议使用w模式每次清空重写 - 额外的ASCII范围判断逻辑没有必要,不可见字符不存在元音字母,该判断反而可能漏掉合法的特殊字符统计
修正后的完整代码
#include <stdio.h> #include <ctype.h> void voals_text() { FILE *input_file = fopen("questions.txt", "r"); FILE *output_file = fopen("result.txt", "w"); // 校验文件打开是否成功 if (input_file == NULL || output_file == NULL) { perror("文件打开失败"); return; } char line[1024]; int nr_voals = 0; while (fgets(line, sizeof(line), input_file) != NULL) { nr_voals = 0; // 遍历到字符串结束符'\0'就停止,不会读取垃圾值 for (int i = 0; line[i] != '\0'; i++) { // 统一转小写,同时统计大小写元音 char c = tolower(line[i]); if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') { nr_voals++; } } // 元音数为偶数就写入输出文件 if (nr_voals % 2 == 0) { fputs(line, output_file); } } fclose(input_file); fclose(output_file); } int main() { voals_text(); return 0; }
更优化的实现方案
如果需要支持超过1024字节的长行,可以采用动态缓冲区方案:
- 初始分配指定大小的缓冲区,用
fgets读取内容 - 判断读取到的内容末尾是否包含换行符,如果未包含说明行未读完,用
realloc扩容缓冲区后继续读取剩余内容 - 统计完成后释放动态缓冲区即可
内容的提问来源于stack exchange,提问作者geekt
相关产品推荐
相关产品推荐

