简介
C 标准库的 ctype.h 头文件提供了一些函数,可用于测试和映射字符。
这些函数接受 int 作为参数,它的值必须是 EOF 或表示为一个无符号字符。
如果参数 c 满足描述的条件,则这些函数返回 非0。如果参数 c 不满足描述的条件,则这些函数返回 0。
库函数
下面列出了头文件 ctype.h 中定义的函数:
序号 | 函数 | 描述 |
---|---|---|
1 | int isalnum(int c) | 检查所传的字符是否是字母或数字 |
2 | int isalpha(int c) | 检查所传的字符是否是字母 |
3 | int iscntrl(int c) | 检查所传的字符是否是控制字符 |
4 | int isdigit(int c) | 检查所传的字符是否是十进制数字 |
5 | int isxdigit(int c) | 检查所传的字符是否是十六进制数字 |
6 | int isgraph(int c) | 检查所传的字符是否有图形表示法 |
7 | int islower(int c) | 检查所传的字符是否是小写字母 |
8 | int isupper(int c) | 检查所传的字符是否是大写字母 |
9 | int isprint(int c) | 检查所传的字符是否是可打印的 |
10 | int ispunct(int c) | 检查所传的字符是否是标点符号字符 |
11 | int isspace(int c) | 检查所传的字符是否是空白字符 |
标准库还包含了两个转换函数,它们接受并返回一个 “int”
序号 | 函数 | 描述 |
---|---|---|
1 | int tolower(int c) | 把大写字母转换为小写字母 |
2 | int toupper(int c) | 把小写字母转换为大写字母 |
字符集
序号 | 字符集 | 描述 |
---|---|---|
1 | 数字 | 完整的数字集合 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 } |
2 | 十六进制数字 | 集合 { 0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f } |
3 | 小写字母 | 集合 { a b c d e f g h i j k l m n o p q r s t u v w x y z } |
4 | 大写字母 | 集合 {A B C D E F G H I J K L M N O P Q R S T U V W X Y Z } |
5 | 字母 | 小写字母和大写字母的集合 |
6 | 字母数字字符 | 数字、小写字母和大写字母的集合 |
7 | 标点符号字符 | 集合 ! " # $ % & ’ ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ |
8 | 图形字符 | 字母数字字符和标点符号字符的集合 |
9 | 空格字符 | 制表符 \t、换行符 \n、垂直制表符 \v、换页符 \f、回车符 \r、空格符的集合。 |
10 | 可打印字符 | 字母数字字符、标点符号字符和空格字符的集合。 |
11 | 控制字符 | 在 ASCII 编码中,这些字符的八进制代码是从 000 到 037,以及 177(DEL) |
12 | 空白字符 | 包括空格符和制表符 |
源码分析
ctype.h 部分源码
#define _U 0x01 /* upper */ //二进制的第一位
#define _L 0x02 /* lower */ //二进制的第二位
#define _D 0x04 /* digit */ //二进制的第三位
#define _C 0x08 /* cntrl */ //二进制的第四位
#define _P 0x10 /* punct */ //二进制的第五位
#define _S 0x20 /* white space (space/lf/tab) */ //二进制的第六位
#define _X 0x40 /* hex digit */ //二进制的第七位
#define _SP 0x80 /* hard space (0x20) */ //二进制的第八位
extern const unsigned char _ctype[];
#define __ismask(x) (_ctype[(int)(unsigned char)(x)])
#define isalnum(c) ((__ismask(c)&(_U|_L|_D)) != 0)
#define isalpha(c) ((__ismask(c)&(_U|_L)) != 0)
#define iscntrl(c) ((__ismask(c)&(_C)) != 0)
#define isdigit(c) ((__ismask(c)&(_D)) != 0)
#define isgraph(c) ((__ismask(c)&(_P|_U|_L|_D)) != 0)
#define islower(c) ((__ismask(c)&(_L)) != 0)
#define isprint(c) ((__ismask(c)&(_P|_U|_L|_D|_SP)) != 0)
#define ispunct(c) ((__ismask(c)&(_P)) != 0)
/* Note: isspace() must return false for %NUL-terminator */
#define isspace(c) ((__ismask(c)&(_S)) != 0)
#define isupper(c) ((__ismask(c)&(_U)) != 0)
#define isxdigit(c) ((__ismask(c)&(_D|_X)) != 0)
ctype.c 部分源码
const unsigned char _ctype[] = {
_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */
_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */
_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */
_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */
_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */
_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */
_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */
_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */
_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */
_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */
_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */
_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */
_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */
_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */
_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */
_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */
_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */
_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */
_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */
_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */
_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */
_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */
EXPORT_SYMBOL(_ctype); /* EXPORT_SYMBOL标签内定义的函数或者符号对全部内核代码公开,不用修改内核代
码就可以在您的内核模块中直接调用,即使用EXPORT_SYMBOL可以将一个函数以符 号的方式导出给其他模块使用*/
ascii码对照表:
比如程序执行 int r = isdigit(‘8’); 语句,从上面的源码中可以看出,int r = ((__ismask(‘8’)&(_D)) != 0);展开__ismask宏,int r = ( ( ( _ctype[(int)(unsigned char)(‘8’)] ) &(_D) ) != 0 ); 即 int r = ( ( (_ctype[56]) &(_D) ) != 0 ); 所以 int r = isdigit(‘8’); 为真,从源码和分析,以及对应ascii码对照表可知。ctype的实现中,定义了一个const unsigned char类型, 256个字节大小的数组,这个数组的下标对应这个字符的ascii码大小,存放的值对应的是这个字符对应的字符类型
使用例子以及部分简单功能实现
#include <stdio.h>
#include <ctype.h>
int is_alnum(int c); //是否是字母或数字
int is_alpha(int c); //是否是字母
int is_cntrl(int c); //是否是控制字符
int is_digit(int c); //是否是十进制数字
int is_xdigit(int c); //是否是十六进制数字
int is_graph(int c); //是否是有图形表示法
int is_lower(int c); //是否是小写字母
int is_upper(int c); //是否是大写字母
int is_print(int c); //字符是否可打印
int is_punct(int c); //是否是标点符号
int is_isspace(int c); //是否是空格字符
int to_lower(int c); //从大写字母转为小写字母
int to_upper(int c); //从小写字母转为大写字母
int main()
{
char c = '8';
char *p = isalnum(c) ? "是" : "不是";
printf("isalnum--- %c %s---数字或字母\n", c, p);
p = is_alnum(c) ? "是" : "不是";
printf("is_alnum--- %c %s---数字或字母\n", c, p);
c = 'A';
p = isalpha(c) ? "是" : "不是";
printf("isalpha--- %c %s---是字母\n", c, p);
p = is_alpha(c) ? "是" : "不是";
printf("is_alpha--- %c %s---字母\n", c, p);
c = '\t';
p = iscntrl(c) ? "是" : "不是";
printf("iscntrl--- %c %s---控制符\n", c, p);
c = '8';
p = isdigit(c) ? "是" : "不是";
printf("isdigit--- %c %s---数字\n", c, p);
p = is_digit(c) ? "是" : "不是";
printf("is_digit--- %c %s---数字\n", c, p);
c = 'F';
p = isxdigit(c) ? "是" : "不是";
printf("isxdigit--- %c %s---十六进制数字\n", c, p);
p = is_xdigit(c) ? "是" : "不是";
printf("is_xdigit--- %c %s---十六进制数字\n", c, p);
c = 'e';
p = isgraph(c) ? "是" : "不是";
printf("isgraph--- %c %s---有图形表示法\n", c, p);
c = 'e';
p = islower(c) ? "是" : "不是";
printf("islower--- %c %s---小写字母\n", c, p);
p = is_lower(c) ? "是" : "不是";
printf("is_lower--- %c %s---小写字母\n", c, p);
c = 'F';
p = isupper(c) ? "是" : "不是";
printf("isupper--- %c %s---大写字母\n", c, p);
p = is_upper(c) ? "是" : "不是";
printf("is_upper--- %c %s---大写字母\n", c, p);
c = 'F';
printf("tolower--- %c 的小写字母为 %c\n", c, tolower(c));
printf("to_lower--- %c 的小写字母为 %c\n", c, to_lower(c));
c = 'g';
printf("toupper--- %c 的大写字母为 %c\n", c, toupper(c));
printf("to_upper--- %c 的大写字母为 %c\n", c, to_upper(c));
return 0;
}
//是否是字母或数字
int is_alnum(int c)
{
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'))
return 1;
return 0;
}
//是否是字母
int is_alpha(int c)
{
if ((c >= 'A' && c <='Z') || (c >= 'a' && c <='z'))
return 1;
return 0;
}
//是否是控制字符
int is_cntrl(int c)
{
}
//是否是十进制数字
int is_digit(int c)
{
if (c >= '0' && c <= '9')
return 1;
return 0;
}
//是否是十六进制数字
int is_xdigit(int c)
{
if ((c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
return 1;
return 0;
}
//是否是有图形表示法
int is_graph(int c)
{
}
//是否是小写字母
int is_lower(int c)
{
if (c >= 'a' && c <='z')
return 1;
return 0;
}
//是否是大写字母
int is_upper(int c)
{
if (c >= 'A' && c <='Z')
return 1;
return 0;
}
//字符是否可打印
int is_print(int c)
{
}
//是否是标点符号
int is_punct(int c)
{
}
//是否是空格字符
int is_isspace(int c)
{
}
//从大写字母转为小写字母
int to_lower(int c)
{
if (is_upper(c))
return c -= 'A' - 'a';
return c;
}
//从小写字母转为大写字母
int to_upper(int c)
{
if (is_lower(c))
return c -= 'a' - 'A';
return c;
}