C标准库源码解剖(3):字符处理函数ctype.h和wctype.h
分类:C 2009-10-05 18:47 525人阅读评论(0) 收藏举报
字符处理包括分类(即属性判断)和转换函数。ASCII字符主要可分类为控制字符、空白字符、可打印字符、数字字符、字母字符(大写和小写)、标点符号等。
1、ctype.h:标准的属性判断函数有
isalnum,isalpha,iscntrl,isdigit,isxdigit,isgraph,isprint,ispunct,islower,isupper,isspace, isblank(C99中引入)共12个函数。标准的属性转换函数有tolower和toupper。当然具体的实现中还会提供一些非标准函数作为扩展,如glibc的实现中提供了
isctype,isascii,toascii。
view plaincopy to clipboardprint?
1. /* ISO C99 Standard 7.4: 字符处理 <ctype.h> */
2. #ifndef _CTYPE_H
3. #define _CTYPE_H 1
4. #include <features.h> /* 定义了一些表示编译选项的宏 */
5. #include <bits/types.h>
6. __BEGIN_DECLS
7. #ifndef _ISbit
8. /* 下面这些是所有的字符属性,如果超过16种不同的属性,那很多使用
unsigned short int的
9. 的函数代码都要改变。这些属性被存储为网络字节序(大端字节序),我们为
每个属性定义一个
10. 依赖于机器字节序的比特位解释 */
11. # include <endian.h>
12. # if __BYTE_ORDER == __BIG_ENDIAN /* 如果是大端字节序 */
13. # define _ISbit(bit) (1 << (bit))
14. # else /* 否则__BYTE_ORDER==__LITTLE_ENDIAN,是小端字节序 */
15. # define _ISbit(bit) ((bit) < 8 ? ((1 << (bit)) << 8) : ((1 << (bit)) >> 8))
16. # endif
17. enum
18. {
19. _ISupper = _ISbit (0), /* 大写字母字符A~Z:0x41~0x5A */
20. _ISlower = _ISbit (1), /* 小写字母字符a~z:0x61~0x7A */
21. _ISalpha = _ISbit (2), /* 字母字符A~Za~z */
22. _ISdigit = _ISbit (3), /* 十进制数字字符0~9:0x30~0x39 */
23. _ISxdigit = _ISbit (4), /* 十六进制数字字符0~9A~Fa~f */
24. _ISspace = _ISbit (5), /* 空白字符:0x9~0xD,0x20。包括水平制表符/t,换
行符/n,
25. 垂直制表符/v,换页符/f,回车符/r,空格符' ' */
26. _ISprint = _ISbit (6), /* 可打印字符:0x20~0x7E。即任何非控制字符 */
27. _ISgraph = _ISbit (7), /* 图形字符:除空格以外的可打印字符 */
28. _ISblank = _ISbit (8), /* 空白分隔符:通常是空格符和水平制表符(Space和
Tab键) */
29. _IScntrl = _ISbit (9), /* 控制字符:0x0~0x1F,0x7F */
30. _ISpunct = _ISbit (10), /* 标点符号 */
31. _ISalnum = _ISbit (11) /* 字母和数字字符 */
32. };
33. #endif /* ! _ISbit */
34. /* 这些函数定义在ctype-info.c中。这里的描述必须与localeinfo.h中的一致。
35. 在依赖于线程的区域模型中(参看<local.h>中的uselocale),我们不能像过
去那样对这些
36. 函数使用全局变量,现在这些访问函数返回每个变量的地址,这是多线程环境
中当前线程的本
37. 地地址。
38. 这些指针指向一个大小为384的数组中,因此它们可以通过以下几种下标值
来访问:任何[0,255]内的
39. unsigend char值;EOF(-1);任何[-128,-1)内的signed char值。ISO C要求
ctype中
40. 的函数工作在unsigend char或EOF上;这里我们同时也支持负的
signed char值以兼容老的程序。
41. 大小写转换数组是int的,而不是unsigned char,因为tolower(EOF)的结果
必须是EOF,这并不
42. 是一个unsigned char。但是今天更重要的是数组也会在多字节字符集中使
用 */
43. extern __const unsigned short int **__ctype_b_loc (void)
44. __attribute__ ((__const));
45. extern __const __int32_t **__ctype_tolower_loc (void)
46. __attribute__ ((__const));
47. extern __const __int32_t **__ctype_toupper_loc (void)
48. __attribute__ ((__const));
49. #define __isctype(c, type) /
50. ((*__ctype_b_loc ())[(int) (c)] & (unsigned short int) type)
51. #define __isascii(c) (((c) & ~0x7f) == 0) /* 如果C是一个7比特的值,说明是
一个ascii字符(0~127) */
52. #define __toascii(c) ((c) & 0x7f) /* 屏蔽掉高位 */
53. /* 用宏来声明ctype中的各个函数原型,以简化代码 */
54. #define __exctype(name) extern int name (int) __THROW
55. __BEGIN_NAMESPACE_STD
56. /* 下面的名称是所有的函数:
57. int isCHARACTERISTIC(int c);
58. 当且仅当C有属性CHARACTERISTIC时返回非0值(真),
59. 对CHARACTERISTIC名称的含义,参看上面的enum
60. 函数形参是一个字符,用int类型描述 */
61. __exctype (isalnum); /* 这里是各个函数原型声明 */
62. __exctype (isalpha);
63. __exctype (iscntrl);
64. __exctype (isdigit);
65. __exctype (islower);
66. __exctype (isgraph);
67. __exctype (isprint);
68. __exctype (ispunct);
69. __exctype (isspace);
70. __exctype (isupper);
71. __exctype (isxdigit);
72. /* 返回C的小写形式 */
73. extern int tolower (int __c) __THROW;
74. /* 返回C的大写形式 */
75. extern int toupper (int __c) __THROW;
76. __END_NAMESPACE_STD
77.
78. /* ISO C99引入了一个新函数 */
79. #ifdef __USE_ISOC99
80. __BEGIN_NAMESPACE_C99
81. __exctype (isblank);
82. __END_NAMESPACE_C99
83. #endif
84. #ifdef __USE_GNU
85. /* 根据掩码MASK来测试C是否属于某个字符集 */
86. extern int isctype (int __c, int __mask) __THROW;
87. #endif
88. #if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPEN
89. /* 返回非0值,当且仅当C是ASCII字符集中(例如,不足7比特的宽度) */
90. extern int isascii (int __c) __THROW;
91. /* 返回C中在ASCII字符集中的那部分(例如,C的低位7比特) */
92. extern int toascii (int __c) __THROW;
93. /* 下面的原型与toupper和tolower相同,唯一不同的它们不检查实参是否在char
的范围内 */
94. __exctype (_toupper);
95. __exctype (_tolower);
96. #endif /* Use SVID or use misc. */
97. /* 下面代码用于优化的转换函数中 */
98. #define __tobody(c, f, a, args) /
99. (__extension__ /
100. ({ int __res; /
101. if (sizeof (c) > 1) /
102. { /
103. if (__builtin_constant_p (c)) /
isalpha 函数104. { /
105. int __c = (c); /
106. __res = __c < -128 || __c > 255 ? __c : (a)[__c]; /
107. } /
108. else /
109. __res = f args; /
110. } /
111. else /
112. __res = (a)[(int) (c)]; /
113. __res; }))
114. #if !defined __NO_CTYPE && !defined __cplusplus
115. # define isalnum(c) __isctype((c), _ISalnum)
116. # define isalpha(c) __isctype((c), _ISalpha)
117. # define iscntrl(c) __isctype((c), _IScntrl)
118. # define isdigit(c) __isctype((c), _ISdigit)
119. # define islower(c) __isctype((c), _ISlower)
120. # define isgraph(c) __isctype((c), _ISgraph)
121. # define isprint(c) __isctype((c), _ISprint)
122. # define ispunct(c) __isctype((c), _ISpunct)
123. # define isspace(c) __isctype((c), _ISspace)
124. # define isupper(c) __isctype((c), _ISupper)
125. # define isxdigit(c) __isctype((c), _ISxdigit)
126. # ifdef __USE_ISOC99
127. # define isblank(c) __isctype((c), _ISblank)
128. # endif
129. # ifdef __USE_EXTERN_INLINES
130. __extern_inline int
131. __NTH (tolower (int __c))
132. {
133. return __c >= -128 && __c < 256 ? (*__ctype_tolower_loc ())[__c] : __c; 134. }
135. __extern_inline int
136. __NTH (toupper (int __c))
137. {
138. return __c >= -128 && __c < 256 ? (*__ctype_toupper_loc ())[__c] : __c; 139. }
140. # endif
141. # if __GNUC__ >= 2 && defined __OPTIMIZE__ && !defined __cplusplus 142. # define tolower(c) __tobody (c, tolower, *__ctype_tolower_loc (), (c)) 143. # define toupper(c) __tobody (c, toupper, *__ctype_toupper_loc (), (c)) 144. # endif /* Optimizing gcc */
145. # if defined __USE_SVID || defined __USE_MISC || defined __USE_XOPE N
146. # define isascii(c) __isascii (c)
147. # define toascii(c) __toascii (c)
148. # define _tolower(c) ((int) (*__ctype_tolower_loc ())[(int) (c)])
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论