You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 11:09:16