C语言 <ctype.h> 头文件详解

C语言 <ctype.h> 头文件详解

    • [1、 引言](#1、 引言)
    • [2、 头文件概述](#2、 头文件概述)
    • 3、字符分类函数
      • [3.1 、示例:分类函数综合演示](#3.1 、示例:分类函数综合演示)
    • 4、字符转换函数
      • [4.1、 示例:大小写转换](#4.1、 示例:大小写转换)
    • 5、常见使用场景
      • [5.1、 统计字符串中各类字符的数量](#5.1、 统计字符串中各类字符的数量)
      • [5.2、 将字符串中的大写字母转换为小写](#5.2、 将字符串中的大写字母转换为小写)
      • [5.3 、判断字符串是否为纯数字(常用于输入校验)](#5.3 、判断字符串是否为纯数字(常用于输入校验))
    • [6、 注意事项](#6、 注意事项)
      • [6.1 、参数范围](#6.1 、参数范围)
      • [6.2、 不要用 `char` 直接作为下标](#6.2、 不要用 char 直接作为下标)
      • [6.3 、与 `EOF` 的配合](#6.3 、与 EOF 的配合)
    • 7、总结
  • 二、代码示例

1、 引言

在 C 语言的标准库中,<ctype.h> 是一个短小却非常实用的头文件。它主要提供字符分类和字符转换两大类函数,用于判断一个字符是字母、数字、空白符,还是将大写字母转换为小写字母等。虽然它包含的函数数量不多,但在文本处理、输入校验、词法分析等场景中几乎无处不在。

本文将系统讲解 <ctype.h> 中所有函数的用法、返回值、注意事项,并通过大量可运行的示例帮助你彻底掌握它。

2、 头文件概述

<ctype.h> 是 C 标准库(C89/C99/C11)中定义的字符处理头文件。它声明了两类函数:

  • 字符分类函数:判断字符属于哪一类,如是否为数字、字母、空白符等。
  • 字符转换函数:进行大小写转换。

这些函数的共同特点是:

  • 参数类型为 int,但实际只接受 unsigned char 范围内的值或 EOF。
  • 返回值类型为 int,分类函数返回非零值表示"是",返回 0 表示"否";转换函数返回转换后的字符。

3、字符分类函数

以下函数均接受一个 int 参数,若参数不在 unsigned char 范围内且不是 EOF,行为是未定义的。

函数 判断条件
isalnum(c) 字母或数字(a-z、A-Z、0-9)
isalpha(c) 字母(a-z、A-Z)
isdigit(c) 十进制数字(0-9)
isxdigit(c) 十六进制数字(0-9、a-f、A-F)
islower(c) 小写字母(a-z)
isupper(c) 大写字母(A-Z)
isspace(c) 空白符(空格、\t、\n、\v、\f、\r)
isblank(c) 空白字符(空格、\t,C99 新增)
iscntrl(c) 控制字符(ASCII 0x00-0x1F 和 0x7F)
ispunct(c) 标点符号(可打印但非字母、数字、空白符)
isprint(c) 可打印字符(含空格)
isgraph(c) 可打印字符(不含空格)

3.1 、示例:分类函数综合演示

c 复制代码
#include <stdio.h>
#include <ctype.h>

int main(void) {
    char ch = 'A';

    if (isalpha(ch)) {
        printf("%c 是字母\n", ch);
    }
    if (isupper(ch)) {
        printf("%c 是大写字母\n", ch);
    }
    if (isalnum(ch)) {
        printf("%c 是字母或数字\n", ch);
    }

    char digit = '7';
    if (isdigit(digit)) {
        printf("%c 是数字\n", digit);
    }

    char space = ' ';
    if (isspace(space)) {
        printf("空格是空白符\n");
    }

    return 0;
}

运行结果:

复制代码
A 是字母
A 是大写字母
A 是字母或数字
7 是数字
空格是空白符

4、字符转换函数

<ctype.h> 提供两个字符转换函数:

函数 功能
tolower(c) 将大写字母转换为小写字母;若 c 不是大写字母,则原样返回
toupper(c) 将小写字母转换为大写字母;若 c 不是小写字母,则原样返回

4.1、 示例:大小写转换

c 复制代码
#include <stdio.h>
#include <ctype.h>

int main(void) {
    char upper = 'A';
    char lower = 'b';

    printf("tolower('%c') = '%c'\n", upper, tolower(upper));
    printf("toupper('%c') = '%c'\n", lower, toupper(lower));

    // 非字母字符原样返回
    printf("tolower('1') = '%c'\n", tolower('1'));
    printf("toupper(' ') = '%c'\n", toupper(' '));

    return 0;
}

运行结果:

复制代码
tolower('A') = 'a'
toupper('b') = 'B'
tolower('1') = '1'
toupper(' ') = ' '

5、常见使用场景

5.1、 统计字符串中各类字符的数量

c 复制代码
#include <stdio.h>
#include <ctype.h>

int main(void) {
    const char *text = "Hello, World! 123";
    int letters = 0, digits = 0, spaces = 0, puncts = 0;

    for (int i = 0; text[i] != '\0'; i++) {
        if (isalpha(text[i])) {
            letters++;
        } else if (isdigit(text[i])) {
            digits++;
        } else if (isspace(text[i])) {
            spaces++;
        } else if (ispunct(text[i])) {
            puncts++;
        }
    }

    printf("字母: %d\n", letters);
    printf("数字: %d\n", digits);
    printf("空白符: %d\n", spaces);
    printf("标点: %d\n", puncts);

    return 0;
}

运行结果:

复制代码
字母: 10
数字: 3
空白符: 2
标点: 2

5.2、 将字符串中的大写字母转换为小写

c 复制代码
#include <stdio.h>
#include <ctype.h>

void to_lower_string(char *str) {
    for (int i = 0; str[i] != '\0'; i++) {
        str[i] = tolower(str[i]);
    }
}

int main(void) {
    char text[] = "Hello C Language!";
    to_lower_string(text);
    printf("%s\n", text);
    return 0;
}

运行结果:

复制代码
hello c language!

5.3 、判断字符串是否为纯数字(常用于输入校验)

c 复制代码
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>

bool is_numeric(const char *str) {
    if (str[0] == '\0') {
        return false;
    }
    for (int i = 0; str[i] != '\0'; i++) {
        if (!isdigit(str[i])) {
            return false;
        }
    }
    return true;
}

int main(void) {
    printf("12345: %s\n", is_numeric("12345") ? "是数字" : "不是数字");
    printf("12a45: %s\n", is_numeric("12a45") ? "是数字" : "不是数字");
    printf("空串: %s\n", is_numeric("") ? "是数字" : "不是数字");
    return 0;
}

运行结果:

复制代码
12345: 是数字
12a45: 不是数字
空串: 不是数字

6、 注意事项

6.1 、参数范围

这些函数要求参数是 unsigned char 类型的值或 EOF。如果传入的是普通 char 类型变量,且该变量存储的是非 ASCII 字符(如扩展字符集),由于 char 可能是有符号类型,会发生符号扩展,导致未定义行为。安全做法是先转换为 unsigned char:

c 复制代码
char c = getchar();
if (isalpha((unsigned char)c)) {
    // 安全
}

6.2、 不要用 char 直接作为下标

<ctype.h> 的函数内部通常通过查表实现,因此不要用 char 直接作为数组下标访问,应先转换为 unsigned char。

6.3 、与 EOF 的配合

在读取文件或标准输入时,getchar() 返回 int 类型,可能是 EOF。此时可以直接将返回值传给 <ctype.h> 函数,因为 EOF 是合法参数:

c 复制代码
#include <stdio.h>
#include <ctype.h>

int main(void) {
    int ch;
    int count = 0;

    while ((ch = getchar()) != EOF) {
        if (isalpha(ch)) {
            count++;
        }
    }

    printf("字母总数: %d\n", count);
    return 0;
}

7、总结

<ctype.h> 虽然函数不多,但每个都经过高度优化,性能极佳。掌握这些函数可以让你写出更简洁、更健壮的字符处理代码,避免手写复杂的条件判断。建议在实际开发中优先使用标准库函数,而不是自己实现字符分类逻辑。

类别 函数
分类 isalnum、isalpha、isdigit、isxdigit、islower、isupper、isspace、isblank、iscntrl、ispunct、isprint、isgraph
转换 tolower、toupper

二、代码示例

c 复制代码
#include <stdio.h>
#include <ctype.h>
#include <Windows.h>

int main(void)
{
    SetConsoleOutputCP(CP_UTF8);
    char test_chars[] = "A b 3 !\t\n\x07";
    int c;

    printf("===== 1. 字符分类函数演示 =====\n");
    for (int i = 0; test_chars[i] != '\0'; i++)
    {
        // 转unsigned char再传入ctype函数,避免char为负数导致异常
        c = (unsigned char)test_chars[i];
        printf("字符: '%c' (ASCII:%3d) | ", test_chars[i], c);

        if (isalnum(c))  printf("字母或数字 ");
        if (isalpha(c))  printf("字母 ");
        if (islower(c))  printf("小写字母 ");
        if (isupper(c))  printf("大写字母 ");
        if (isdigit(c))  printf("十进制数字 ");
        if (isxdigit(c)) printf("十六进制数字 ");
        if (isspace(c))  printf("空白字符 ");
        if (isblank(c))  printf("空格/tab ");
        if (ispunct(c))  printf("标点符号 ");
        if (isgraph(c))  printf("可见非空格字符 ");
        if (isprint(c))  printf("可打印字符 ");
        if (iscntrl(c))  printf("控制字符 ");

        printf("\n");
    }

    printf("\n===== 2. toupper / tolower 大小写转换 =====\n");
    const char* str = "Hello Ctype 123 !";
    char buf[128];
    int idx = 0;
    while (str[idx] != '\0')
    {
        unsigned char ch = (unsigned char)str[idx];
        buf[idx] = (char)toupper(ch);
        idx++;
    }
    buf[idx] = '\0';
    printf("全部转大写:%s\n", buf);

    idx = 0;
    while (str[idx] != '\0')
    {
        unsigned char ch = (unsigned char)str[idx];
        buf[idx] = (char)tolower(ch);
        idx++;
    }
    buf[idx] = '\0';
    printf("全部转小写:%s\n\n", buf);


    printf("===== 3. 实战例子:过滤字符串,只保留数字 =====\n");
    char src[] = "a1b2c3d4!@#5";
    char dst[64] = { 0 };
    int p = 0;
    for (int i = 0; src[i] != '\0'; i++)
    {
        unsigned char ch = (unsigned char)src[i];
        if (isdigit(ch))
        {
            dst[p++] = src[i];
        }
    }
    printf("原串:%s\n提取数字:%s\n", src, dst);

    return 0;
}

运行结果:

c 复制代码
===== 1. 字符分类函数演示 =====
字符: 'A' (ASCII: 65) | 字母或数字 字母 大写字母 十六进制数字 可见非空格字符 可打印字符
字符: ' ' (ASCII: 32) | 空白字符 空格/tab 可打印字符
字符: 'b' (ASCII: 98) | 字母或数字 字母 小写字母 十六进制数字 可见非空格字符 可打印字符
字符: ' ' (ASCII: 32) | 空白字符 空格/tab 可打印字符
字符: '3' (ASCII: 51) | 字母或数字 十进制数字 十六进制数字 可见非空格字符 可打印字符
字符: ' ' (ASCII: 32) | 空白字符 空格/tab 可打印字符
字符: '!' (ASCII: 33) | 标点符号 可见非空格字符 可打印字符
字符: ' ' (ASCII:  9) | 空白字符 空格/tab 控制字符
字符: '
' (ASCII: 10) | 空白字符 控制字符
字符: '' (ASCII:  7) | 控制字符

===== 2. toupper / tolower 大小写转换 =====
全部转大写:HELLO CTYPE 123 !
全部转小写:hello ctype 123 !

===== 3. 实战例子:过滤字符串,只保留数字 =====
原串:a1b2c3d4!@#5
提取数字:12345

d:\user\01417804\桌面\CppProject\cppTest\x64\Debug\cppTest.exe (进程 32252)已退出,代码为 0 (0x0)。
要在调试停止时自动关闭控制台,请启用"工具"->"选项"->"调试"->"调试停止时自动关闭控制台"。
按任意键关闭此窗口. . .
相关推荐
阿钱真强道1 小时前
17 嵌入式操作系统 | uloop 事件循环:TCP 客户端
c语言·tcp/ip·tcp·事件循环·uloop
会员果汁3 小时前
函数调用和变长参数
c语言
白山编程大哥6 小时前
Lua 中使用 C 语言的用户自定义类型——userdata
c语言·junit·lua
无敌贵点大王7 小时前
RTThread学习记录13——关于要使用一个外设,RTThread与cubemx到底要怎么配合?
c语言·stm32·学习·rtthread
phltxy7 小时前
C 语言动态内存管理:从申请空间到安全释放
c语言·开发语言·ui
上位机妹子8 小时前
C 语言 数组删除指定元素(快慢指针法)
c语言·数据结构·算法
心中有你02148 小时前
【路径规划】A*寻路算法最通俗易懂讲解(C语言完整实现+详细注释)
c语言·开发语言·算法
大圣编蚕8 小时前
C语言入门:基本语法汇总
c语言·开发语言
en.en..9 小时前
C语言---宏
c语言·开发语言