C. 将 char 十进制值存储到数组可以 read/store 8 位字符

C. Storing char decimal value to array cant read/store 8bit characters

我有一个问题希望你能帮助我。

我正在尝试从我将对其执行频率分析的文件中读取字符。我决定最简单的方法是拥有一个索引为 0-255 的数组,并在每次读取 char 时将相应的索引(从读取的 chars 十进制值)递增 1。 我遇到的问题是似乎只保存了 7 位字符。在下面查看代码。

int frequency(FILE *freqfilep)
{    
    printf("frequency function called!\n");

    int start = 1;
    int *frqarray = calloc(256,sizeof(int));
    unsigned char tecken;

    FILE *fp;
    fp = fopen("freqfile.txt","r");

    if (fp == NULL) 
    {
        perror("Error in opening file");
        start = 0;
    }
    do
    {
        tecken = fgetc(fp);

        if (feof(fp))
        {
            start = 0;
        }
        else
        {
            frqarray[(int)tecken] ++;
        }
    }
    while (start != 0);

    printf("a%d\n", frqarray[97]);
    printf("b%d\n", frqarray[98]);
    printf("c%d\n", frqarray[99]);
    printf("1%d\n", frqarray[49]);
    printf("2%d\n", frqarray[50]);
    printf("3%d\n", frqarray[51]);
    printf("å%d\n", frqarray[134]);
    printf("ä%d\n", frqarray[132])
    printf("ö%d\n", frqarray[148]);

    fclose(fp);

    return 0;
}

我正在读取的文件包含以下字符:

aaa bbb ccc 111 222 333 ååå äää ööö

所以我代码底部的 printf 应该是:

a3
b3
c3
13
23
33
å3
ä3
ö3

但是结果是

a3
b3
c3
13
23
33
å0
ä0
ö0

所以我猜测读取 8 位字符存在一些问题,我在论坛上四处看了看,发现了一些相对相似的帖子,答案是我需要使用像这样的缓冲区这个 fread(&buffer, 256, 1, file); 但我不确定如何实现它。

这些字符很可能不是设置了高位的单字节字符,而是多字节字符。

这些字符由以下 UTF-8 代码点表示:

  • å: 0xc3 0xa5 (十进制 195 165)

  • ä: 0xc3 0xa4 (十进制 195 164)

  • ö: 0xc3 0xb6 (十进制 195 182)

将以下内容添加到您的代码中:

printf("195 %d\n", frqarray[195]);
printf("165 %d\n", frqarray[165]);
printf("164 %d\n", frqarray[164]);
printf("182 %d\n", frqarray[182]);

你可能会得到这个输出:

195 9
165 3
164 3
182 3

编辑:

如果需要对字符进行频率分析,请使用fgetwc读入字符。如果您希望所有字符都在基本的多语言集中(Unicode 个字符 U-0000 - U-FFFF),您可以创建一个大小为 65536 的数组并输出它。如果您希望字符超出该范围,您可能需要使用不同的方案。

您可能 运行 遇到了编码问题,您可以通过打印出 整个 频率 table 来验证这一点。您可能会发现,除了没有记录您期望的某些角色的任何出现外,它还会记录您没有期望的某些角色的出现。

这归结为 C chars,尤其是 unsigned chars 基本上是 bytes 的表示,而不是 "characters"比如说,在 Unicode 的术语意义上。如果您正在阅读的文件采用多字节编码(UTF-8 很可能),那么您的 fgetc() 将读取该编码的各个字节,并且不会将它们解码为代码点值。而且,不能确定你的C程序内部使用的字符编码和文件的编码是一样的。

如果要读取字符数据,则需要正确解码。如果您不想在程序本身中编写解码逻辑,那么您必须确保输入文件按照您的程序预期进行编码。诸如 iconv 之类的转码器可能会对此有所帮助,但您确实需要知道文件的当前编码以及要转换成的编码。