C 语言实例 – 字符串中各种字符计算(一文讲透)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...点击查看项目介绍 ;
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;

截止目前, 星球 内专栏累计输出 82w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 2900+ 小伙伴加入学习 ,欢迎点击围观

前言

在编程的世界中,字符串(String)如同一条承载信息的河流,而字符(Character)则是这条河中的每一滴水珠。对于开发者而言,如何精准地统计字符串中字母、数字、空格、标点等不同类别的字符数量,既是基础技能,也是解决复杂问题的基石。本文将以“C 语言实例 – 字符串中各种字符计算”为主题,通过循序渐进的方式,结合代码示例和实际案例,帮助读者掌握这一技能的核心逻辑与实现方法。


字符串与字符的“分拣站”:基本概念

在开始编程之前,我们需要明确几个关键概念:

  1. 字符串的存储方式:在 C 语言中,字符串本质上是一个以空字符('\0')结尾的字符数组。例如,字符串 "Hello" 实际上存储为 'H', 'e', 'l', 'l', 'o', '\0'
  2. 字符分类:根据 ASCII 码表,字符可以分为字母(A-Z/a-z)、数字(0-9)、空格(' ')、标点符号(如 ',', '.')等。
  3. 统计需求:常见的统计目标包括:
    • 统计字母总数(区分大小写或合并统计)
    • 统计数字字符数量
    • 统计空格与标点符号的数量
    • 区分其他特殊字符(如 @, #, $ 等)

形象比喻:可以将字符串视为一条项链,每个字符是项链上的珠子,而我们的任务是将这些珠子按照材质(字母、数字等)分类放入不同的“抽屉”中。


实例一:统计字母、数字与空格

代码示例

#include <stdio.h>
#include <ctype.h> // 包含字符处理函数

int main() {
    char str[] = "Hello World! 123"; // 示例字符串
    int letters = 0, digits = 0, spaces = 0;
    
    for(int i = 0; str[i] != '\0'; i++) {
        if(isalpha(str[i])) {
            letters++;
        } else if(isdigit(str[i])) {
            digits++;
        } else if(isspace(str[i])) {
            spaces++;
        }
    }
    
    printf("Letters: %d\nDigits: %d\nSpaces: %d\n", letters, digits, spaces);
    return 0;
}

关键知识点解析

  1. ctype.h 头文件:提供了 isalpha(), isdigit(), isspace() 等函数,用于快速判断字符类型。
  2. 循环终止条件str[i] != '\0' 确保循环在字符串结尾时停止。
  3. 统计逻辑:通过嵌套的 if-else 结构,逐个字符分类计数。

输出结果

Letters: 10  
Digits: 3  
Spaces: 2  

进阶实例:区分大小写字母与扩展统计

需求升级

假设我们需要进一步区分大写字母和小写字母,同时统计标点符号的数量。

代码示例

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

int main() {
    char str[] = "C语言实例 – 字符串中各种字符计算!"; // 包含中文与特殊字符
    int uppercase = 0, lowercase = 0, digits = 0;
    int spaces = 0, punctuation = 0, others = 0;
    
    for(int i = 0; str[i] != '\0'; i++) {
        char current = str[i];
        if(isupper(current)) {
            uppercase++;
        } else if(islower(current)) {
            lowercase++;
        } else if(isdigit(current)) {
            digits++;
        } else if(isspace(current)) {
            spaces++;
        } else if(strchr(".,;:!?", current)) { // 自定义标点符号列表
            punctuation++;
        } else {
            others++;
        }
    }
    
    printf("Uppercase: %d\nLowercase: %d\nDigits: %d\n", uppercase, lowercase, digits);
    printf("Spaces: %d\nPunctuation: %d\nOthers: %d\n", spaces, punctuation, others);
    return 0;
}

知识点扩展

  1. 区分大小写isupper()islower() 函数分别判断字符是否为大写或小写字母。
  2. 自定义标点符号:通过 strchr() 函数检查字符是否在预设的标点列表中。
  3. 处理非 ASCII 字符:当字符串包含中文或特殊符号时,others 变量会统计这些字符。

输出结果(以中文字符为例):

Uppercase: 0  
Lowercase: 0  
Digits: 0  
Spaces: 2  
Punctuation: 1  
Others: 22  

优化与陷阱:常见问题与解决方案

陷阱一:忘记空字符的终止条件

错误代码示例

for(int i = 0; i < 10; i++) { ... } // 固定循环次数可能导致越界  

解决方案:始终使用 str[i] != '\0'strlen() 函数控制循环范围。

陷阱二:未处理多字节字符

当字符串包含中文或 Unicode 字符时,strlen() 和逐字符遍历可能失效。此时需要:

  1. 使用宽字符函数(如 wchar_t)或 UTF-8 解析库。
  2. 或者仅统计可见字符,忽略编码细节。

优化技巧

  1. 预分配计数器:使用结构体(struct)或数组管理统计结果,提高代码可读性。
  2. 函数封装:将统计逻辑封装为独立函数,例如:
    void count_characters(const char *str, int *counts) { ... }
    

实战案例:密码强度分析器

需求

设计一个程序,统计用户输入的密码中包含的字符类别,以评估密码强度。
要求统计:

  • 大写字母、小写字母、数字、特殊字符(如 !, @, #)的数量
  • 输出密码强度等级

代码实现

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

#define MIN_LENGTH 8 // 最小密码长度

int main() {
    char password[100];
    printf("请输入密码:");
    fgets(password, sizeof(password), stdin);
    
    int uppercase = 0, lowercase = 0, digits = 0, special = 0;
    const char *special_chars = "!@#$%^&*()";
    
    // 移除fgets读取的换行符
    password[strcspn(password, "\n")] = '\0';
    
    for(int i = 0; password[i] != '\0'; i++) {
        char c = password[i];
        if(isupper(c)) uppercase++;
        else if(islower(c)) lowercase++;
        else if(isdigit(c)) digits++;
        else if(strchr(special_chars, c)) special++;
    }
    
    int score = 0;
    if(uppercase > 0) score += 2;
    if(lowercase > 0) score += 2;
    if(digits > 0) score += 2;
    if(special > 0) score += 3;
    if(strlen(password) >= MIN_LENGTH) score += 3;
    
    printf("\n密码强度分析:\n");
    printf("大写字母: %d\n小写字母: %d\n数字: %d\n特殊字符: %d\n", uppercase, lowercase, digits, special);
    printf("总分: %d/12\n", score);
    if(score >= 9) printf("密码强度:强\n");
    else if(score >= 6) printf("密码强度:中等\n");
    else printf("密码强度:弱\n");
    return 0;
}

输出示例

请输入密码:HelloWorld123!  
密码强度分析:  
大写字母: 2  
小写字母: 8  
数字: 3  
特殊字符: 1  
总分: 12/12  
密码强度:强  

结论

通过本文的实例与代码分析,我们掌握了以下核心能力:

  1. 基础统计:利用 ctype.h 函数快速分类字母、数字与空格。
  2. 进阶需求:区分大小写字母、自定义标点符号的统计方法。
  3. 优化与陷阱:避免常见错误,并学会封装统计逻辑以提升代码复用性。
  4. 实战应用:通过密码强度分析器案例,理解如何将统计功能融入实际项目。

字符串处理是编程中的“基本功”,而字符分类统计则是这一基本功的典型应用场景。希望读者通过本文不仅能掌握代码实现,更能培养“以小见大”的思维模式——从简单问题出发,逐步构建解决复杂问题的能力。

下一步行动建议

  1. 尝试修改代码,统计字符串中的中文字符数量。
  2. 设计一个程序,统计用户输入的文本中每个单词的出现次数。
  3. 使用 strtok() 函数分割字符串,并统计标点符号的具体类型(如感叹号、问号等)。

通过持续练习与实践,你将逐步成为字符串处理的“分拣大师”!

最新发布