跳转到内容

C 编程/ctype.h

来自维基教科书,开放的书籍,开放的世界

在 C 编程语言的 ANSI C 标准库中,标题 ctype.h 包含字符分类函数的声明。

早期的 C 语言工具开发者在 Unix 下开始快速开发习语来将字符分类成不同的类型。例如,在 ASCII 字符集中,以下测试可以识别字母

if ('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z')

但是,这种习语并不一定适用于其他字符集,例如 EBCDIC。

很快,程序中就充满了像上面一样的测试,或者更糟糕的是,几乎像上面一样的测试。程序员可以以几种不同的方式编写相同的习语,这会减慢理解速度并增加出错的机会。

不久之后,这些习语就被以下函数所取代:<ctype.h>.

与上面的示例不同,字符分类例程不是作为比较测试编写的。在大多数 C 库中,它们是作为静态表查找而不是宏或函数编写的。

例如,创建一个包含 256 个 8 位整数的数组,排列成位域,其中每个位对应字符的特定属性,例如,isdigit、isalpha。如果整数的最低有效位对应 isdigit 属性,则代码可以这样编写

#define isdigit(x) (TABLE[x] & 1)

早期版本的 Linux 使用了一种类似于第一个代码示例的潜在错误方法

#define isdigit(x) ((x) >= '0' && (x) <= '9')

如果出现以下情况,这可能会导致问题:x具有副作用——例如,如果调用isdigit(x++)或者isdigit(run_some_program()). 不会立即发现传递给isdigit的参数被评估了两次。因此,通常使用基于表的方案。

<ctype.h> 的内容

[编辑 | 编辑源代码]

<ctype.h> 包含十几个字符分类函数的原型。除 isdigitisxdigit 外,所有这些函数都是特定于区域设置的;如果区域设置发生变化,它们的运行行为可能会改变。

测试 形式为 int isfunc(int);
对于真返回非零数,对于假返回零。
isalnum 测试字母数字字符
isalpha 测试字母字符
isblank 测试空白字符(C99 中新增)
iscntrl 测试控制字符
isdigit 测试数字。不特定于区域设置。
isgraph 测试图形字符,不包括空格字符。
islower 测试小写字母
isprint 测试可打印字符,包括空格字符。
ispunct 测试标点符号字符
isspace 测试任何空白字符
isupper 测试大写字母
isxdigit 测试十六进制数字。不特定于区域设置。
字符转换 形式为 int tofunc(int);
除非不是字母,否则返回转换后的字符。
tolower 将字符转换为小写
toupper 将字符转换为大写

单一 Unix 规范版本 3 添加了类似于上述函数的函数

isascii 测试参数是否在 0 到 127 之间
toascii 将字符转换为 ASCII

错误使用

[编辑 | 编辑源代码]

标准指出(§7.4-1)

在所有情况下,参数都是一个 int,其值应可表示为 unsigned char 或者等于宏 EOF 的值。如果参数具有任何其他值,则行为未定义。

不幸的是,许多程序员忘记了 char 类型可能是带符号的或无符号的,具体取决于实现。如果 char 类型是带符号的,则从 charint 的隐式转换可能会生成负值,导致未定义的行为。这通常意味着,如果参数用作查找表的索引,它将访问超出正确表的区域,甚至可能使程序崩溃。

使用 char 参数的正确方法是在检查 EOF 条件后先将它们强制转换为 unsigned char

getchargetcfgetc 返回的 int 类型的值保证在 unsigned char(或 EOF)的范围内,因此在这些情况下不需要强制转换。

另请参阅

[编辑 | 编辑源代码]
[编辑 | 编辑源代码]
华夏公益教科书