linux中ctype.h字符判断函数实现原理
ctype.h是C和C++标准库中一个非常实用的头文件,提供了一系列用于字符分类的函数。这些函数可以帮助我们快速判断一个字符是否属于特定的类别,如字母、数字、大写字母等。本文将详细介绍这些函数的实现原理。
1、基本介绍
ctype.h中的函数通常以宏或函数的形式实现,它们接受一个init类型的参数(实际上是字符的ASCII码值),并返回一个布尔值(非零表示真,零表示假)。
这些函数的特点是:
- 只检查字符的ASCII码值,不考虑本地化设置
- 参数应为EOF或unsigned char类型的值
- 使用简单高效
2、代码实现
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_CTYPE_H
#define _LINUX_CTYPE_H/** NOTE! This ctype does not handle EOF like the standard C* library is required to.*/#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)
static inline int isdigit(int c)
{return '0' <= c && c <= '9';
}
#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)#define isascii(c) (((unsigned char)(c))<=0x7f)
#define toascii(c) (((unsigned char)(c))&0x7f)static inline unsigned char __tolower(unsigned char c)
{if (isupper(c))c -= 'A'-'a';return c;
}static inline unsigned char __toupper(unsigned char c)
{if (islower(c))c -= 'a'-'A';return c;
}#define tolower(c) __tolower(c)
#define toupper(c) __toupper(c)/** Fast implementation of tolower() for internal usage. Do not use in your* code.*/
static inline char _tolower(const char c)
{return c | 0x20;
}/* Fast check for octal digit */
static inline int isodigit(const char c)
{return c >= '0' && c <= '7';
}#endif
// SPDX-License-Identifier: GPL-2.0
/** linux/lib/ctype.c** Copyright (C) 1991, 1992 Linus Torvalds*/#include <linux/ctype.h>
#include <linux/compiler.h>
#include <linux/export.h>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);