对字符串中的字符进行分类

#include <ctype.h>
#include <stddef.h>

typedef struct {
  size_t space;
  size_t alnum;
  size_t punct;
} chartypes;

chartypes classify(const char *s) {
  chartypes types = { 0, 0, 0 };
  const char *p;
  for (p= s; p != '\0'; p++) {
    types.space += !!isspace((unsigned char)*p);
    types.alnum += !!isalnum((unsigned char)*p);
    types.punct += !!ispunct((unsigned char)*p);
  }

  return types;
}

classify 函数检查字符串中的所有字符,并计算空格数,字母数字和标点符号。它避免了几个陷阱。

  • 字符分类函数(例如 isspace)期望它们的参数可以表示为 unsigned char,或者 EOF 宏的值
  • *p 的表达式为 char,因此必须进行转换以匹配上述措辞。
  • char 类型定义为 signed charunsigned char
  • char 相当于 unsigned char 时,没有问题,因为 char 类型的每个可能值都可以表示为 unsigned char
  • char 相当于 signed char 时,必须将其转换为 unsigned char 才能传递给字符分类函数。尽管由于这种转换,角色的值可能会发生变化,但这正是这些函数所期望的。
  • 字符分类函数的返回值仅区分零(表示 false)和非零(表示 true)。为计算出现次数,需要将此值转换为 1 或 0,这由双重否定 !! 完成。