【问题标题】:Is there a way to see what characters are in the types in ctype.h?有没有办法查看 ctype.h 中的类型中有哪些字符?
【发布时间】:2016-08-03 21:16:57
【问题描述】:

我正在编写一个 C 程序,该程序涉及遍历 .txt 文件并查找文件中使用的所有可打印字符(或可能的图形字符)。我知道头文件 ctype.h 定义了几个字符类(例如数字、小写字母、大写字母等)并提供了检查给定字符是否属于每个类的函数,但我不确定是否有可能做相反的事情(即检查类中的 all 字符是否有某些东西)。我需要列出或定义每种类型中所有字符的东西,最好是数组或枚举类型。

【问题讨论】:

  • 你自己看看ctype.h好吗?
  • 宏的名称和描述还不够吗?
  • 可用字符数有限,根据您的编码可能低至 128 个。您只需调用ctype函数即可。
  • 你在找东西like this
  • @user3078414 - 如果它只是那么容易......你不能。准确确定每个字符类 中包含的内容的最佳位置是手册页。每个中包含的内容的信息摘要是ctype.hisdigit(3)

标签: c header-files


【解决方案1】:

不知道这是否有帮助,但我编写了一个程序来根据给定文件中找到的字符对字符进行分类。修复它以无条件地遍历 0..255 范围内的字符(字节)并不难。

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

static void classifier(FILE *fp, char *fn)
{
    int c;
    int map[UCHAR_MAX + 1];
    size_t i;

    printf("%s:\n", fn);
    for (i = 0; i < UCHAR_MAX + 1; i++)
        map[i] = 0;

    printf("Code Char Space Upper Lower Alpha AlNum Digit XDig  Graph Punct Print Cntrl\n");

    while ((c = getc(fp)) != EOF)
    {
        map[c] = 1;
    }

    for (c = 0; c < UCHAR_MAX + 1; c++)
    {
        if (map[c] == 1)
        {
            int sp = isspace(c)  ? 'X' : ' ';
            int up = isupper(c)  ? 'X' : ' ';
            int lo = islower(c)  ? 'X' : ' ';
            int al = isalpha(c)  ? 'X' : ' ';
            int an = isalnum(c)  ? 'X' : ' ';
            int dg = isdigit(c)  ? 'X' : ' ';
            int xd = isxdigit(c) ? 'X' : ' ';
            int gr = isgraph(c)  ? 'X' : ' ';
            int pu = ispunct(c)  ? 'X' : ' ';
            int pr = isprint(c)  ? 'X' : ' ';
            int ct = iscntrl(c)  ? 'X' : ' ';
            int ch = (pr == 'X') ?  c  : ' ';
            printf("0x%02X %-4c %-6c%-6c%-6c%-6c%-6c%-6c%-6c%-6c%-6c%-6c%-6c\n",
                    c, ch, sp, up, lo, al, an, dg, xd, gr, pu, pr, ct);
        }
    }
}

我的代码提取的额外技巧是使用setlocale() 在当前语言环境而不是 C 语言环境中工作:

#include <locale.h>

int main(int argc, char **argv)
{
    setlocale(LC_ALL, "");
    filter(argc, argv, 1, classifier);
    return(0);
}

filter()函数处理来自argv[1]的参数(通常是optind而不是1,但是这段代码中没有条件参数处理)到argv[argc-1],读取文件(或读取如果没有命名文件,则为标准输入)。它为打开的每个文件调用classifier()——并处理打开、关闭等操作。

【讨论】:

  • 好的,这很漂亮——每个字符类的表格输出都适用于每个文件中的每个字符(或stdin)。
【解决方案2】:

ctype.h 中没有可以帮助您的固定字符列表。事实上isprint() 取决于语言环境。

假设您说的是char 而不是宽字符,解决问题的一种方法是初始化一个包含 256 个元素的表,每个元素代表一个字符:

char mychars[256];  
memset(mychars, 0, 256);  

然后打开文件并读取所有字符,并标记存在的字符:

...
int c; 
while ( (c=fgetc(fp)) != EOF) {
    mychars[c] |= 1;  
}

然后你就可以遍历可打印的:

for (int i=0; i<256; i++) {
    if (isprint(i) && !mychars[i]) 
         printf ("%c not found\n", (char)i);
}

【讨论】:

  • isprint()(或isgraph())似乎是回答这个问题的关键。
【解决方案3】:

您可以遍历unsigned char 类型的所有值,从0UCHAR_MAX,并检查&lt;ctype.h&gt; 中的每个函数以确定类是什么。

例如,您可以使用以下命令列出所有数字:

printf("digits: ");
for (int c = 0; c <= UCHAR_MAX; c++) {
    if (isdigit(c))
        putchar(c);
}
printf("\n");

【讨论】:

    【解决方案4】:

    我的建议:

    1. 创建一个包含 256 个元素的 unsigned longs 数组,这些元素可以使 char 在文件中出现的次数变旧。

    2. 逐字符读取文件内容,更新数组中的数据。

    3. 处理完文件的所有字符后,遍历数组元素并打印必要的信息。


    int main()
    {
       unsigned long charOccurrences[256] = {0};
    
       // open the file.
       FILE* fin = fopen(....);
    
       int c;
       while ( (c = fgetc(fin)) != EOF )
       {
          // Increment the number of occurrences.
          charOccurrences[c]++;
       }
    
       // Process the data.
       for (int i = 0; i < 256; ++i )
       {
          if ( isprint(i) && charOccurrences[i] == 0 )
          {
             printf("%c was not found in the file.\n", i);
          }
       }
    
       // Close the file
       fclose(fin);
    }
    

    【讨论】:

    • 我打字比你慢一点 ;-) 我可以建议使用 long 数组而不是 int 数组,以便与可能的最大字符数一致期望在文件中(至少根据 ftell() 的返回值)?
    • @Christophe,很好的建议。我把它改成了unsigned long
    • printf("%s was not found in the file.\n"); 中缺少参数,而且格式可能不正确。
    • @chqrlie,感谢您指出错误。我还需要使用%c
    猜你喜欢
    • 2015-10-19
    • 1970-01-01
    • 2012-07-18
    • 1970-01-01
    • 1970-01-01
    • 2018-08-29
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    相关资源
    最近更新 更多