C语言统计文件中冒号出现次数时计数始终为0问题求助
问题描述
我有一个文本文件,内容格式如下:
Hello:Dad How:Are You:Today
我需要统计该文件中冒号的出现总次数,为此编写了如下NumColon函数:
int NumColon(char txt[]) { FILE *fp = fopen(txt, "r"); if (fp == NULL) { exit(1); } int count = 0; char ch; while (!feof(fp)) { ch = getc(fp); if (strcmp(&ch, ":") == 0) { count++; } } return count; }
运行该函数后打印count变量的值始终为0。在while循环内部、if判断语句之前添加fprintf("%s", &ch);(调试代码笔误写为fprint)打印读取到的字符,可以明确看到读取过程中确实获取到了冒号字符,但始终无法进入if判断分支完成计数。我也尝试过将判断条件修改为if (ch == ':'),但仍然无法进入if判断分支。
故障原因
- 类型不匹配:
getc()的返回值是int类型,不是char。函数读取到文件末尾/出错时会返回值为-1的EOF,如果用char类型变量接收返回值:- 若当前环境
char默认为无符号类型,-1会被转换为255,永远和值为-1的EOF不相等,直接导致循环判断逻辑错乱 - 就算环境下
char为有符号类型,也存在读取到值为0xFF的合法字符时被误判为EOF的问题
- 若当前环境
- 函数误用:
strcmp的作用是比较以\0结尾的C字符串,传入的&ch是单个栈上字符的地址,该地址后续的内存值是随机的,没有字符串结束符,和存储在常量区、结构为':'+'\0'的字符串":"永远不可能相等。 - 循环逻辑错误:
while(!feof(fp))是C语言文件读取的经典错误写法,feof只有在一次读取操作已经触发文件结束标志后才会返回真,这种写法会导致循环多执行一次,额外读取一次无效的EOF值。 - 修改为
ch == ':'仍然不生效,核心是ch定义为char导致的类型问题,外加feof循环的逻辑bug,导致判断分支根本没有按预期执行。另外原代码没有调用fclose关闭打开的文件句柄,属于资源泄漏,虽然不会直接导致计数为0,但属于必须修复的问题。
修复后代码
#include <stdio.h> #include <stdlib.h> int NumColon(char txt[]) { FILE *fp = fopen(txt, "r"); if (fp == NULL) { exit(EXIT_FAILURE); } int count = 0; int ch; // 必须用int类型接收getc返回值,兼容EOF判断 // 直接在循环条件中执行读取和EOF判断,规避feof的逻辑缺陷 while ((ch = getc(fp)) != EOF) { if (ch == ':') { // 单字符判断直接用==即可,无需调用字符串比较函数 count++; } } fclose(fp); // 关闭打开的文件,避免资源泄漏 return count; }
注意事项
- 单字符值比较直接使用
==运算符即可,strcmp/strncmp等字符串处理函数仅适用于以\0结尾的字符数组,不要混用。 - 所有使用
getc/fgetc/getchar等返回字符读取值的函数时,接收返回值的变量必须定义为int类型,否则会出现各类和EOF判断相关的诡异问题。
内容的提问来源于stack exchange,提问作者vale383
相关产品推荐
相关产品推荐

