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

C语言isalnum()函数使用错误 非字母数字字符被误计数

问题描述

代码预期实现功能为接收用户输入的短语,统计所有输入的总字符数,同时统计其中字母、数字类字符的总个数。实际测试时输入+等非字母数字字符,字母数字计数器仍会累加,统计结果不符合预期。
问题复现代码:

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

#define MAXR 100
#define MAXC 10     
#define TERMINATOR "END"

int main() {

    char phrase[MAXR];
    char text[MAXC][MAXR];
  
    int i;
    int countalnum = 0;
    int countchar = 0;

    for (i = 0; i < MAXC; i++) {
  
        fgets(phrase, MAXR, stdin);
        phrase[strlen(phrase) - 1] = '\0';
    
        for (int j = 0; j < strlen(phrase); j++) {
            countchar++;
            if (isalnum(phrase[i]) == 0)
                countalnum++;
        }
    
        if (strcmp(phrase, TERMINATOR) == 0) {
            exit(0);
        }
    
        strcpy(text[i], phrase);
    }
    ...
}
错误原因

代码存在两处直接导致计数错误的核心问题,还有两处潜在隐患:

  • 数组索引使用错误:内层循环遍历当前输入字符串时,循环变量是j(代表当前遍历到的字符串内字符位置),但调用isalnum时传入的是phrase[i],i是外层循环的行计数变量,根本不是当前遍历到的字符位置,取到的字符和当前遍历位置完全不对应,计数自然错误。
  • 判断逻辑写反:isalnum()函数的返回规则是:传入字符为字母或数字时返回非0值,传入非字母数字字符时返回0。现有代码写的判断条件是isalnum(...) == 0时给字母数字计数器加1,相当于遇到非字母数字字符才计数,完全颠倒了判断逻辑。
  • 换行处理逻辑不安全:直接用phrase[strlen(phrase) - 1] = '\0'删除fgets读入的换行符的写法有风险,如果输入行长度超过缓冲区限制、或输入流读到EOF时没有换行符,这行代码会误删最后一个有效输入字符。
  • 标准库调用存在未定义行为风险:isalnum要求传入的参数要么是EOF,要么是可转换为unsigned char类型的值,如果编译环境下char为有符号类型,遇到值为负的字符时直接传入会触发未定义行为。
修正方案

将核心换行处理、计数逻辑替换为以下写法即可:

// 替换原有直接截断最后一个字符的换行处理逻辑
fgets(phrase, MAXR, stdin);
char *newline_pos = strchr(phrase, '\n');
if (newline_pos != NULL) {
    *newline_pos = '\0';
}

// 替换原有内层计数循环
for (int j = 0; j < strlen(phrase); j++) {
    countchar++;
    // 修正索引为j,修正判断逻辑,强转unsigned char规避未定义行为
    if (isalnum((unsigned char)phrase[j]) != 0) {
        countalnum++;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 10:24:22