1

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

我正在尝试从我将对其执行频率分析的文件中读取字符。我决定最简单的方法是拥有一个索引为 0-255 的数组,并在每次读取 char 时将相应的索引(从读取的 chars 十进制值)增加一。我遇到的问题是,似乎只保存了 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);但我不知道如何实现它。

4

2 回答 2

2

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

这些字符由以下 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 的数组并输出它。如果您期望超出该范围的字符,您可能需要使用不同的方案。

于 2016-02-02T16:18:54.750 回答
1

您可能会遇到编码问题,您可以通过打印出整个频率表来验证。您可能会发现,除了没有记录您所期待的某些角色的任何外观之外,它还会记录一些您未曾期待的角色的外观。

这归结为这样一个事实,即 C chars 尤其是unsigned chars 基本上是字节的表示,而不是 Unicode 术语意义上的“字符”的表示。如果您正在阅读的文件以多字节编码(很可能是 UTF-8)编码,那么您fgetc()将读取该编码的各个字节,并且不会将它们解码为代码点值。此外,您的 C 程序内部使用的字符编码与文件的编码是否相同并不确定。

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

于 2016-02-02T16:25:49.660 回答