
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)。
要在调试停止时自动关闭控制台,请启用"工具"->"选项"->"调试"->"调试停止时自动关闭控制台"。
按任意键关闭此窗口. . .

