C语言FILE/IO单词计数结果存在微小偏差问题求助
问题成因
统计结果出现固定差值1的核心原因如下:
- 核心计数逻辑存在遗漏:现有代码只有在碰到空白分隔符(空格、换行、制表符、空字符)时才会触发单词数+1的操作,如果文件末尾是普通单词字符、没有尾随空白符,循环读到EOF就直接终止,最后一个单词不会被计入总数。你测试的第一个文件结果正确,是因为它末尾带有空白分隔符,最后一个单词在循环内就完成了计数;另外两个结果少1的文件都没有尾随空白,因此各漏算了1个末尾单词。
- 存在隐藏类型兼容bug:
fgetc()的返回值是int类型(用来表示值为-1的EOF标识),你用char类型变量存储返回值,当编译环境下char为有符号类型、文件中存在值为0xFF的字符时,会被误判为EOF导致读取提前终止,只是这次的测试文件没有触发该问题。 - 缺少鲁棒性判断:代码没有校验
fopen()的执行结果,如果文件不存在、权限不足导致打开失败,直接操作空文件指针会触发程序崩溃。
修复方案
针对以上问题对应修改逻辑即可:
- 将存储读取字符的变量类型从
char改为int,匹配fgetc()的返回值类型,避免EOF误判 - 文件读取循环结束后,补充判断当前是否处于单词内状态,如果是则给总单词数+1,补上末尾漏算的最后一个单词
- 增加文件打开失败的判断逻辑,避免空指针访问
修复后的完整代码如下:
int countwords(const char* filename) { int z; // 改为int类型接收fgetc返回值 int inw = 0; int words = 0; FILE *ed; ed = fopen(filename, "r"); // 增加文件打开失败判断 if (ed == NULL) { return -1; // 打开失败返回错误标识,可根据需求自定义错误处理逻辑 } while ((z = fgetc(ed)) != EOF ){ if (z == ' ' || z == '\n' || z == '\t' || z == '\0') { if(inw) { inw = 0; words++; } } else { inw = 1; } } // 补充文件末尾未以空白结尾时的最后一个单词计数 if (inw) { words++; } fclose(ed); return words; }
内容的提问来源于stack exchange,提问作者destroy_mo
相关产品推荐
相关产品推荐

