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

C语言文本统计代码:特殊符号与辅音计数异常问题排查

问题排查:C语言字符统计代码中特殊符号与辅音计数异常

问题描述

以下是用于统计lets.txt文件中元音、辅音、空格、制表符、特殊符号及行数的C语言代码,目前除特殊符号与辅音计数功能外,其余功能正常:

#include<stdio.h>
#include<stdlib.h>

int main() {
    FILE * fp;
    fp = fopen("lets.txt", "r");
    int vowels = 0, constants = 0, spaces = 0, tabs = 0, specsym = 0, nolines = 1;
    int c;

    while ((c = fgetc(fp)) != EOF) {
        if (c == 65 || c == 69 || c == 73 || c == 70 || c == 85 || c == 97 || c == 101 || c == 105 || c == 111 || c == 117) {
            vowels++;

        } else if (c == 32) {
            spaces++;
        } else if ((33 <= c <= 47) || (58 <= c <= 64) || (91 <= c <= 96) || (123 <= c <= 126)) {
            specsym++;
        } else if ((65 <= c <= 90) || (97 <= c <= 122)) {
            constants++;

        }
    }

    rewind(fp);
    char c1;
    while ((c1 = fgetc(fp)) != EOF) {
        if (c1 == '\n') {
            nolines++;
        } else if (c1 == '\t') {
            tabs++;
        }
    }
    printf("The number of vowels are %d , constants %d, spaces %d, tabs %d, special symbols %d and lines %d", vowels, constants, spaces, tabs, specsym, nolines);
}

运行时出现异常:特殊符号会被计入辅音;调换特殊符号与辅音的判断顺序后,辅音又会被计入特殊符号。

异常原因

核心问题是连续范围比较的写法不符合C语言语法逻辑:

C语言不支持像数学表达式那样的a <= x <= b连续比较,这种写法会被解析为左结合运算:先计算a <= x,得到布尔值0(假)或1(真),再将这个结果与b比较。由于0和1都小于等于代码中所有的右边界值(47、64、96、126、90、122),所以这些范围判断表达式无论c取何值,结果永远为真。

这直接导致分支判断逻辑完全混乱:所有非元音、非空格的字符会优先进入第一个“永远为真”的分支,调换判断顺序后,就会流入新的优先分支,从而出现你看到的“互相计入”现象。

修复方案

将所有连续范围比较拆分为x >= 下限 && x <= 上限的形式,同时修正代码中的其他小问题:

#include<stdio.h>
#include<stdlib.h>

int main() {
    FILE * fp;
    fp = fopen("lets.txt", "r");
    // 增加文件打开失败判断,避免崩溃
    if (fp == NULL) {
        printf("Failed to open file\n");
        return 1;
    }
    int vowels = 0, consonants = 0, spaces = 0, tabs = 0, specsym = 0, nolines = 1;
    int c;

    while ((c = fgetc(fp)) != EOF) {
        // 用字符字面量代替ASCII码,修正元音判断错误(原代码误将F当成元音)
        if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' || 
            c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') {
            vowels++;
        } else if (c == ' ') {
            spaces++;
        } else if ((c >= 33 && c <= 47) || (c >= 58 && c <= 64) || 
                   (c >= 91 && c <= 96) || (c >= 123 && c <= 126)) {
            specsym++;
        } else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) {
            consonants++;
        }
    }

    rewind(fp);
    // 用int存储fgetc返回值,避免EOF判断错误
    int c1;
    while ((c1 = fgetc(fp)) != EOF) {
        if (c1 == '\n') {
            nolines++;
        } else if (c1 == '\t') {
            tabs++;
        }
    }
    printf("元音数量:%d,辅音数量:%d,空格数量:%d,制表符数量:%d,特殊符号数量:%d,行数:%d\n", 
           vowels, consonants, spaces, tabs, specsym, nolines);
    // 关闭文件,释放资源
    fclose(fp);
    return 0;
}

额外优化说明:

  • 用字符字面量(如'A')代替ASCII码,提升代码可读性
  • 增加文件打开失败的判断逻辑,避免空指针访问崩溃
  • 用int存储fgetc的返回值(fgetc返回int类型,包含EOF的数值),避免字符类型无法正确识别EOF
  • 修正变量名拼写错误(constants改为consonants,符合英语拼写规范)
  • 增加文件关闭操作,避免资源泄漏

内容的提问来源于stack exchange,提问作者Yash Gabra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 01:45:32