C语言 - isgraph()函数

4

有人知道C语言中isgraph()函数是如何工作的吗?我了解它的用途和结果,但我对其背后的代码很感兴趣。

例如,它是否仅查看其char值并将其与ASCII表进行比较?还是实际检查它是否可以显示?如果是这样,它是如何做到的呢?

4个回答

6

isgraph()函数的代码因平台(或更准确地说,因实现)而异。一种常见的技术是使用一个已初始化的位域数组,每个字符在(单字节)代码集中都有一个位域,加上EOF(必须被函数接受),然后选择相关位。这样可以简单地实现为一个宏,它是安全的(只评估其参数一次)和一个简单的(可能是内联的)函数。

#define isgraph(x) (__charmap[(x)+1]&__PRINT)

其中__charmap__PRINT是保留给实现的名称。 +1的部分处理了常见情况,即EOF-1


根据C标准(ISO/IEC 9899:1999):

§7.4.1.6 The isgraph function

Synopsis

#include <ctype.h>
int isgraph(int c);

Description

The isgraph function tests for any printing character except space (' ').

并且:

§7.4 字符处理 <ctype.h>

¶1 头文件声明了几个有用的函数,用于分类和映射字符。166) 在所有情况下,参数都是int类型,其值应该可表示为unsigned char或等于宏EOF的值。如果参数具有任何其他值,则行为是未定义的。

¶2 这些函数的行为受当前区域设置的影响。只有在“C”区域之外时才具有区域设置特定方面的功能的函数如下所示。

¶3 打印字符一词指的是区域设置特定字符集中的成员,每个成员占用显示设备上的一个打印位置;控制字符一词指的是区域设置特定字符集中不是打印字符的成员。167) 所有字母和数字都是打印字符。

166) 参见“未来库方向”(7.26.2)。

167) 在使用七位US ASCII字符集的实现中,打印字符是那些值从0x20(空格)到0x7E(波浪号)的字符;控制字符是那些值从0(NUL)到0x1F(US)以及字符0x7F(DEL)的字符。


2
它被称为isgraph,而不是isGraph(以及char,而不是Char),POSIX程序员手册说:
isgraph()函数应测试c是否为程序当前区域设置中类别为图形的字符;请参见IEEE Std 1003.1-2001的基本定义卷,第7章,语言环境。
因此,是的,它在表格中查找(或等效代码)。它无法检查它是否实际可显示,因为这将取决于输出设备,其中许多设备可以显示除isgraph返回true之外的字符。

isgraph是ISO标准的一部分,因此很少需要参考POSIX。 - paxdiablo
@ISO标准对实现提供了最低要求。POSIX通常对实际实现更有用。 - Jim Balter

0

isgraph()宏只查看ASCII表,或者你所在的位置/国家/省份/星球/银河系的ASCII表版本。

这里有一个测试代码计算单词数, 它发现你可以通过编写自己的版本来提高性能,该版本使用isgraph()初始化一个bool数组[256]。代码中还附有基准测试结果。

由于bool变量/数组实际上是BYTE而不是位,如果您使用位数组并进行测试,那么从内存效率的角度来看,您可以做得更好。它只占用32个字节。在任何通用现代处理器上都会被缓存。

重要的是,如果您想要比这里提供的标准测试略有不同的测试(请参见字符测试的图形描述), 您可以自由更改标准测试提供的初始化以包括您自己的异常。

Truth table for various character test macros


它只查看基于ASCII的系统上的ASCII表。例如,仍然有使用EBCDIC的系统。 - Keith Thompson
@KeithThompson,那听起来是有道理的Keith。你是否有各种字符测试的图表,就像我刚刚插入的那个一样?这可能会很有帮助,而我的COBOL日子已经过去了,所以我没有那张图片可用。如果有的话,请多关照! :) - user2548100
看起来EBCDIC是一团糟,没有简单的BYTE整数范围检查可以做。如果在这些环境中有类似于上面isxxxxxxx宏的等效物,我猜想它们会受到高度重视。另一方面,什么样的受虐狂会忍受这样的环境呢? :-O
http://en.wikipedia.org/wiki/EBCDIC
- user2548100
我看不出问题。对于ASCII的典型<ctype.h>实现使用查找表,每个条目一个字节,每个位表示一个属性。同样的方法在EBCDIC上同样适用。 - Keith Thompson
啊,所以你想比较 isprint 的实用性和硬编码(非可移植)的测试,例如 (c >= 32 && c <= 126)isprint(' ') 为真)。我误解了你的观点。但是无论你是使用 ASCII、EBCDIC 还是苏美尔楔形文字,我都不认为没有使用 <ctype.h> 有什么意义,所以我没想到要进行比较。 - Keith Thompson
显示剩余2条评论

0

isgraph 检查“可打印”字符,但“可打印”的定义可能因您的语言环境而异。您的语言环境可能使用不在 ASCII 表中的字符。在内部,它很可能是一个表查找、基于范围的测试((x >= 'a') && (x <= 'z') 等)或两者的组合。不同的实现可能会略有不同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接