对从流中读取的字符进行分类

#include <ctype.h>
#include <stdio.h>

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

chartypes classify(FILE *f) {
  chartypes types = { 0, 0, 0 };
  int ch;

  while ((ch = fgetc(f)) != EOF) {
    types.space += !!isspace(ch);
    types.alnum += !!isalnum(ch);
    types.punct += !!ispunct(ch);
  }

  return types;
}

classify 函数从流中读取字符并计算空格数,字母数字和标点符号。它避免了几个陷阱。

  • 当从流中读取字符时,结果被保存为 int,否则在读取 EOF(文件结束标记)和具有相同位模式的字符之间会存在歧义。
  • 字符分类函数(例如 isspace)期望它们的参数可以表示为 unsigned char,或者 EOF 宏的值。由于这正是 fgetc 返回的内容,因此无需在此处进行转换。
  • 字符分类函数的返回值仅区分零(表示 false)和非零(表示 true)。为计算出现次数,需要将此值转换为 1 或 0,这由双重否定 !! 完成。