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 char
s,尤其是 unsigned char
s 基本上是 bytes 的表示,而不是 "characters"比如说,在 Unicode 的术语意义上。如果您正在阅读的文件采用多字节编码(UTF-8 很可能),那么您的 fgetc()
将读取该编码的各个字节,并且不会将它们解码为代码点值。而且,不能确定你的C程序内部使用的字符编码和文件的编码是一样的。
如果要读取字符数据,则需要正确解码。如果您不想在程序本身中编写解码逻辑,那么您必须确保输入文件按照您的程序预期进行编码。诸如 iconv
之类的转码器可能会对此有所帮助,但您确实需要知道文件的当前编码以及要转换成的编码。
我有一个问题希望你能帮助我。
我正在尝试从我将对其执行频率分析的文件中读取字符。我决定最简单的方法是拥有一个索引为 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 char
s,尤其是 unsigned char
s 基本上是 bytes 的表示,而不是 "characters"比如说,在 Unicode 的术语意义上。如果您正在阅读的文件采用多字节编码(UTF-8 很可能),那么您的 fgetc()
将读取该编码的各个字节,并且不会将它们解码为代码点值。而且,不能确定你的C程序内部使用的字符编码和文件的编码是一样的。
如果要读取字符数据,则需要正确解码。如果您不想在程序本身中编写解码逻辑,那么您必须确保输入文件按照您的程序预期进行编码。诸如 iconv
之类的转码器可能会对此有所帮助,但您确实需要知道文件的当前编码以及要转换成的编码。