glibc 知:手册04:字符处理

1. 前言

The GNU C Library Reference Manual for version 2.35

2. 字符处理

Character Handling

处理字符和字符串的程序通常需要对字符进行分类——它是字母、数字、空格等等——并对字符执行大小写转换操作。为此目的提供了头文件 ctype.h 中的函数。

由于语言环境和字符集的选择可以改变特定字符代码的分类,所有这些功能都会受到当前语言环境的影响。(更准确地说,它们受当前为字符分类选择的语言环境的影响——LC_CTYPE 类别;请参阅语言环境类别)。

ISO C 标准规定了两组不同的功能。一组适用于 char 类型字符,另一组适用于 wchar_t 宽字符(请参阅扩展字符简介)。

2.1. 字符分类

Classification of Characters

本节介绍用于对字符进行分类的库函数。例如,isalpha 是测试字母字符的函数。它接受一个参数,即要测试的字符,如果字符是字母,则返回一个非零整数,否则返回零。你会像这样使用它:

if (isalpha (c))
  printf ("The character `%c' is alphabetic.\n", c);

本节中的每个函数都测试特定字符类别的成员资格;每个都有一个以“is”开头的名称。它们中的每一个都接受一个参数,这是一个要测试的字符,并返回一个被视为布尔值的 int。字符参数作为 int 传递,它可能是常量值 EOF 而不是真正的字符。

任何给定字符的属性都可能因语言环境而异。有关语言环境的更多信息,请参阅语言环境和国际化

这些函数在头文件 ctype.h 中声明。

函数:int islower (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是小写字母,则返回 true。字母不必来自拉丁字母,任何可表示的字母都是有效的。

函数:int isupper (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是大写字母,则返回 true。字母不必来自拉丁字母,任何可表示的字母都是有效的。

函数:int isalpha (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是字母字符(字母),则返回 true。如果 islower 或 isupper 对一个字符为真,那么 isalpha 也为真。

在某些语言环境中,可能存在 isalpha 为真的其他字符——既不是大写也不是小写的字母。但是在标准的“C”语言环境中,没有这样的附加字符。

函数:int isdigit (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是十进制数字(“0”到“9”),则返回 true。

函数:int isalnum (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是字母数字字符(字母或数字),则返回 true;换句话说,如果 isalpha 或 isdigit 对一个字符为真,那么 isalnum 也为真。

函数:int isxdigit (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是十六进制数字,则返回 true。十六进制数字包括正常的十进制数字“0”到“9”以及字母“A”到“F”和“a”到“f”。

函数:int ispunct (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是标点符号,则返回 true。这意味着任何不是字母数字或空格字符的打印字符。

函数:int isspace (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是空白字符,则返回 true。在标准的“C”语言环境中,isspace 仅对标准空白字符返回 true:

' '     空格
'\F'    换页
'\n'    新行
'\r'    回车
'\t'    水平制表符
'\v'    垂直制表符

函数:int isblank (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是空白字符,则返回 true;即空格或制表符。该功能最初是 GNU 扩展,但在 ISO C99 中添加。

函数:int isgraph (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是图形字符,则返回 true;也就是说,一个字符与一个字形相关联。空白字符不被视为图形。

函数:int isprint (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是打印字符,则返回 true。打印字符包括所有图形字符,加上空格(’ ')字符。

函数:int iscntrl (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是控制字符(即不是打印字符的字符),则返回 true。

函数:int isascii (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是适合美国/英国 ASCII 字符集的 7 位无符号字符值,则返回 true。该函数是 BSD 扩展,也是 SVID 扩展。

2.2. 大小写转换

Case Conversion

本节介绍用于执行转换的库函数,例如字符大小写映射。例如,如果可能, toupper 会将任何字符转换为大写。如果字符无法转换,则 toupper 将其原封不动地返回。

这些函数接受一个 int 类型的参数,即要转换的字符,并将转换后的字符作为 int 返回。如果转换不适用于给定的参数,则返回参数不变。

兼容性说明:在 pre-ISO C 方言中,当参数不适合转换时,这些函数可能会失败,而不是原样返回参数。因此为了可移植性,您可能需要编写 islower© ? toupper© : c 而不仅仅是 toupper©。

这些函数在头文件 ctype.h 中声明。

函数:int tolower (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是大写字母,则 tolower 返回对应的小写字母。如果 c 不是大写字母,则 c 原样返回。

函数:int toupper (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 c 是小写字母,则 toupper 返回对应的大写字母。否则 c 原封不动地返回。

函数:int toascii (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

此函数通过清除高位位将 c 转换为适合美国/英国 ASCII 字符集的 7 位无符号字符值。该函数是 BSD 扩展,也是 SVID 扩展。

函数:int _tolower (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

这与 tolower 相同,是为了与 SVID 兼容而提供的。请参阅 SVID(System V 接口描述)。

函数:int _toupper (int c)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

这与 toupper 相同,是为了与 SVID 兼容而提供的。

2.3. 宽字符的字符类别确定

Character class determination for wide characters

ISO C90 的修正案 1 定义了对宽字符进行分类的功能。尽管最初的 ISO C90 标准已经定义了 wchar_t 类型,但没有定义对其进行操作的函数。

宽字符分类函数的一般设计更通用。它允许对可用分类集进行扩展,超出那些始终可用的分类。 POSIX 标准指定了如何进行扩展,这已经在 localedef 程序的 GNU C 库实现中实现。

字符类函数通常使用位集实现,每个字符都有一个位集。对于给定的字符,从表中读取适当的位集,并测试是否设置了某个位。测试哪个位由类决定。

对于宽字符分类功能,这是可见的。定义了一个类型分类类型,一个为给定类检索该值的函数,以及一个使用分类值测试给定字符是否在该类中的函数。在此之上,可以定义用于 char 对象的常规字符分类函数。

数据类型:wctype_t

wctype_t 可以保存一个表示字符类的值。生成此类值的唯一定义方法是使用 wctype 函数。

此类型在 wctype.h 中定义。

函数:wctype_t wctype (const char *property)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

wctype 返回一个值,该值表示由字符串 property 标识的一类宽字符。除了一些标准属性外,每个语言环境都可以定义自己的属性。如果为 LC_CTYPE 类别选择的当前语言环境不知道具有给定名称的属性,则该函数返回零。

每个语言环境中已知的属性是:

"alnum"	"alpha"	"cntrl"	"digit"
"graph"	"lower"	"print"	"punct"
"space"	"upper"	"xdigit"

该函数在 wctype.h 中声明。

为了测试一个字符是否属于非标准类之一,ISO C 标准定义了一个全新的函数。

函数:int iswctype (wint_t wc, wctype_t desc)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 在 desc 指定的字符类中,则此函数返回一个非零值。 desc 必须事先通过成功调用 wctype 返回。

该函数在 wctype.h 中声明。

为了方便使用常用的分类函数,它们在 C 库中定义。如果属性字符串是已知字符类之一,则无需使用 wctype。在某些情况下,需要构造属性字符串,然后 wctype 也可以处理标准类很重要。

函数:int iswalnum (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是字母数字字符(字母或数字),则此函数返回非零值;换句话说,如果 iswalpha 或 iswdigit 对一个字符为真,那么 iswalnum 也是真的。

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("alnum"))

它在 wctype.h 中声明。

函数:int iswalpha (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是字母字符(字母),则返回 true。如果 iswlower 或 iswupper 对一个字符为真,那么 iswalpha 也为真。

在某些语言环境中,可能存在 iswalpha 为真的其他字符——既不是大写也不是小写的字母。但是在标准的“C”语言环境中,没有这样的附加字符。

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("alpha"))

它在 wctype.h 中声明。

函数:int iswcntrl (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是控制字符(即不是打印字符的字符),则返回 true。

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("cntrl"))

它在 wctype.h 中声明。

函数:int iswdigit (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是数字(例如,“0”到“9”),则返回 true。请注意,此函数不仅为十进制数字返回非零值,还为所有类型的数字返回非零值。结果是像下面这样的代码不能无条件地用于宽字符:

n = 0;
while (iswdigit (*wc))
  {
    n *= 10;
    n += *wc++ - L'0';
  }

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("digit"))

它在 wctype.h 中声明。

函数:int iswgraph (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是图形字符,则返回 true;也就是说,一个字符与一个字形相关联。空白字符不被视为图形。

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("graph"))

它在 wctype.h 中声明。

函数:int iswlower (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是小写字母,则返回 true。字母不必来自拉丁字母,任何可表示的字母都是有效的。

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("lower"))

它在 wctype.h 中声明。

函数:int iswprint (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是打印字符,则返回 true。打印字符包括所有图形字符,加上空格(’ ')字符。

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("print"))

它在 wctype.h 中声明。

函数:int iswpunct (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是标点符号,则返回 true。这意味着任何不是字母数字或空格字符的打印字符。

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("punct"))

它在 wctype.h 中声明。

函数:int iswspace (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是空白字符,则返回 true。在标准的“C”语言环境中,iswspace 仅对标准空白字符返回 true:

L' '    空格
L'\f'   换页
L'\n'   新行
L'\r'   回车
L'\t'   水平制表符
L'\v'   垂直制表符

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("space"))

它在 wctype.h 中声明。

函数:int iswupper (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是大写字母,则返回 true。字母不必来自拉丁字母,任何可表示的字母都是有效的。

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("upper"))

它在 wctype.h 中声明。

函数:int iswxdigit (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是十六进制数字,则返回 true。十六进制数字包括正常的十进制数字“0”到“9”以及字母“A”到“F”和“a”到“f”。

这个函数可以使用如下方式实现:

iswctype (wc, wctype ("xdigit"))

它在 wctype.h 中声明。

GNU C 库还提供了一个未在 ISO C 标准中定义但也可作为单字节字符版本的函数。

函数:int iswblank (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是空白字符,则返回 true;即空格或制表符。该功能最初是 GNU 扩展,但在 ISO C99 中添加。它在 wchar.h 中声明。

2.4. 使用宽字符类的注意事项

Notes on using the wide character classes

第一个注意可能并不令人惊讶,但仍然偶尔会引起问题。 iswXXX 函数可以使用宏来实现,事实上,GNU C 库就是这样做的。它们仍然可以作为实际函数使用,但是当包含 wctype.h 头文件时,将使用宏。这与这些函数的 char 类型版本相同。

第二个注意涵盖了一些新的东西。(现实世界)的例子可以很好地说明这一点。第一段代码是原始代码的摘录。它被截断了一点,但意图应该很清楚。

int
is_in_class (int c, const char *class)
{
  if (strcmp (class, "alnum") == 0)
    return isalnum (c);
  if (strcmp (class, "alpha") == 0)
    return isalpha (c);
  if (strcmp (class, "cntrl") == 0)
    return iscntrl (c);return 0;
}

现在,使用 wctype 和 iswctype 可以避免 if 级联,但是将代码重写如下是错误的:

int
is_in_class (int c, const char *class)
{
  wctype_t desc = wctype (class);
  return desc ? iswctype ((wint_t) c, desc) : 0;
}

问题是不能保证可以使用强制转换找到单字节字符的宽字符表示。事实上,这通常会惨遭失败。这个问题的正确解决方法是编写代码如下:

int
is_in_class (int c, const char *class)
{
  wctype_t desc = wctype (class);
  return desc ? iswctype (btowc (c), desc) : 0;
}

有关 btowc 的更多信息,请参阅转换单个字符。请注意,此更改可能不会大大提高程序的性能,因为 wctype 函数仍然必须进行字符串比较。如果为同一个类名多次调用 is_in_class 函数,这将变得非常有趣。在这种情况下,变量 desc 可以计算一次并用于所有调用。因此,上述函数形式可能不是最终形式。

2.5. 宽字符的映射

Mapping of wide characters

分类函数也被 ISO C 标准概括。一个语言环境不仅允许两个标准映射,还可以包含其他映射。同样,localedef 程序已经支持生成此类语言环境数据文件。

数据类型:wctrans_t

这种数据类型被定义为一个标量类型,它可以保存一个表示依赖于语言环境的字符映射的值。除了使用 wctrans 函数的返回值之外,没有其他方法可以构造这样的值。

此类型在 wctype.h 中定义。

函数:wctrans_t wctrans (const char *property)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

必须使用 wctrans 函数来查明是否在为 LC_CTYPE 类别选择的当前语言环境中定义了命名映射。如果返回值非零,您可以在调用 towctrans 之后使用它。如果返回值为零,则在当前语言环境中不知道此类映射。

除了特定于语言环境的映射之外,还有两个映射保证在每个语言环境中都可用:

"tolower"	"toupper"

这些函数在 wctype.h 中声明。

函数:wint_t towctrans (wint_t wc, wctrans_t desc)

Preliminary: | MT-Safe | AS-Safe | AC-Safe | See POSIX Safety Concepts.

towctrans 根据以 desc 为描述符的映射规则映射输入字符 wc,并返回它找到的值。 desc 必须通过成功调用 wctrans 来获得。

该函数在 wctype.h 中声明。

对于一般可用的映射,ISO C 标准定义了方便的快捷方式,因此不必为它们调用 wctrans。

函数:wint_t towlower (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是大写字母,则 towlower 返回相应的小写字母。如果 wc 不是大写字母,则 wc 原样返回。

towlower 可以使用如下方式来实现:

towctrans (wc, wctrans ("tolower"))

该函数在 wctype.h 中声明。

函数:wint_t towupper (wint_t wc)

Preliminary: | MT-Safe locale | AS-Safe | AC-Safe | See POSIX Safety Concepts.

如果 wc 是小写字母,则 towupper 返回相应的大写字母。否则 wc 原封不动地返回。

towupper 可以使用如下方式来实现:

towctrans (wc, wctrans ("toupper"))

该函数在 wctype.h 中声明。

上一节中针对使用宽字符分类函数给出的相同警告也适用于此处。不可能简单地将 char 类型值转换为 wint_t 并将其用作 towctrans 调用的参数。

3. 参考

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值