在C中,我需要一些帮助来修复我的代码以读取文件中每个字符的频率,并将其显示在屏幕上



所以我用C写了一段代码来打印一个名为"harrypotter1.txt"文件中每个字符的频率。(哈利波特第一部)。它的工作范围是有随机的空格打印": 0,应该只打印文件中的字符。下面我将列出我的代码,并显示它打印到屏幕上的输出,如果有人能帮助我解决这个问题。注意:我需要使用结构体!

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

struct pair //struct to store frequency and value 
{
int frequency;
char value;
};

int main()
{
struct pair table[128]; //set to 128 because these are the main characters

int fd; // file descriptor for opening file
char buffer[1]; // buffer for reading through files bytes

fd = open("harrypotter1.txt", O_RDONLY); // open a file in read mode

for(int j = 0; j < 128; j++)//for loop to initialize the array of pair (struct)
{
table[j].value = j; // table with index j sets the struct char value to equal the index
table[j].frequency = 0; // then the table will initialize the frequency to be 0
}

while((read(fd, buffer, 1)) > 0) // read each character and count frequency
{
int k = buffer[0]; //index k is equal to buffer[0] with integer mask becasue each letter has a ASCII number.
table[k].frequency++; //using the struct pair table with index k to count the frequency of each character in text file
}

close(fd); // close the file

for (int i = 0; i < 128; i++) // use for loop to print frequency of characters
{       
printf("%c: %dn",table[i].value, table[i].frequency); // print characters and its frequency
}

return 0; //end of code
}

输出:

: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 3

: 10702

: 0

: 0
: 10702
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
: 0
0
: 0
: 0
: 0
: 0
: 70803
!: 474
": 4758
#: 0
$: 0
%: 0
&: 0
': 3141
(: 30
): 33
*: 2
+: 0
,: 5658
-: 1990
.: 6136
/: 0
0: 5
1: 11
2: 3
3: 8
4: 6
5: 2
6: 1
7: 4
8: 1
9: 4
:: 69
;: 135
<: 0
=: 0
>: 0
?: 754
@: 0
A: 703
B: 348
C: 293
D: 685
E: 287
F: 426
G: 492
H: 2996
I: 1393
J: 51
K: 79
L: 209
M: 665
N: 488
O: 332
P: 639
Q: 203
R: 660
S: 844
T: 1055
U: 193
V: 192
W: 653
X: 2
Y: 326
Z: 5
[: 0
: 1
]: 0
^: 0
_: 0
`: 0
a: 25887
b: 4980
c: 6403
d: 15932
e: 39628
f: 6431
g: 8127
h: 19535
i: 19422
j: 319
k: 3930
l: 14385
m: 6729
n: 21337
o: 25809
p: 4909
q: 217
r: 20990
s: 18870
t: 27993
u: 9562
v: 2716
w: 7744
x: 381
y: 8293
z: 259
{: 0
|: 0
}: 0
~: 1
: 0
*/

Allan Wind的C答案就产生正确的结果而言是好的,但它确实分配了比解决问题所需的最小值更大的字符数组。这种空间浪费是由于C数组的下标必须从0开始,并且第一个可打印字符' '的值为32,最后一个可打印字符'~'的值为126。

with Ada.Text_IO; use Ada.Text_IO;
procedure count_graphic_characters is
subtype graphix is Character range ' ' .. '~';
counts   : array (graphix) of Natural := (Others => 0);
The_file : File_Type;
C        : Character;
begin
Open
(File => The_file, Mode => In_File,
Name => "srccount_graphic_characters.adb");
while not End_Of_File (The_file) loop
Get (File => The_file, Item => C);
counts (C) := counts (C) + 1;
end loop;
Close (The_file);
for I in counts'Range loop
Put_Line (I & ": " & counts (I)'Image);
end loop;
end count_graphic_characters;

该程序使用Ada编程语言计算其源文件中字符的频率。

子类型graphix被定义为包含以' '开始到'~'结束的所有图形字符。数组名称计数由子类型graphix中的字符索引。数组的每个元素都是预定义子类型Natural的一个实例,初始化为0。该数组包含足够的元素来计算源文件中的每个图形字符。

如果无法找到Open过程中指定的文件,程序将引发异常。

当从文件中读取每个字符时,将该字符用作计数数组的索引,并增加相应的元素。

创建一个128个元素的数组不会浪费空间。而是使用95个字符的数组。也不需要检查每个数组元素来确定索引所表示的字符是否为可打印字符,因为数组索引值只是可打印字符。

程序的输出是:

:  132
!:  0
":  4
#:  0
$:  0
%:  0
&:  2
':  6
(:  10
):  10
*:  0
+:  1
,:  3
-:  0
.:  5
/:  0
0:  1
1:  1
2:  0
3:  0
4:  0
5:  0
6:  0
7:  0
8:  0
9:  0
::  6
;:  14
<:  0
=:  8
>:  6
?:  0
@:  0
A:  2
B:  0
C:  7
D:  0
E:  1
F:  5
G:  1
H:  0
I:  8
J:  0
K:  0
L:  1
M:  1
N:  2
O:  5
P:  1
Q:  0
R:  1
S:  0
T:  8
U:  0
V:  0
W:  0
X:  0
Y:  0
Z:  0
[:  0
:  1
]:  0
^:  0
_:  18
`:  0
a:  26
b:  3
c:  21
d:  9
e:  43
f:  8
g:  9
h:  18
i:  22
j:  0
k:  0
l:  17
m:  3
n:  20
o:  22
p:  13
q:  0
r:  24
s:  15
t:  23
u:  13
v:  0
w:  2
x:  4
y:  3
z:  0
{:  0
|:  0
}:  0
~:  1

您可以使用数组而不是结构体,因为值只是数组索引:table[j].value = j;。初始化数组,而不是在循环中分配初始值。增加了打开时的错误检查。使用isprint()来确定我们是否应该打印给定的字符:

#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
// assumes 2^i to make the bitwise & work below
#define LEN 128
int main() {
unsigned frequency[LEN] = { 0 };
int fd = open("harrypotter1.txt", O_RDONLY);
if(fd == -1) {
printf("%sn", strerror(errno));
return 1;
}
unsigned char buffer;
while((read(fd, &buffer, 1)) > 0) {
frequency[buffer & (LEN-1)]++;
}
close(fd);
for (int i = 0; i < LEN; i++) {
if(isprint(i))
printf("%c: %un", i, frequency[i]);
}
return 0;
}

和使用放置内容"hello world"在输入文件中,我得到以下输出:

: 1
!: 0
": 0
#: 0
$: 0
%: 0
&: 0
': 0
(: 0
): 0
*: 0
+: 0
,: 0
-: 0
.: 0
/: 0
0: 0
1: 0
2: 0
3: 0
4: 0
5: 0
6: 0
7: 0
8: 0
9: 0
:: 0
;: 0
<: 0
=: 0
>: 0
?: 0
@: 0
A: 0
B: 0
C: 0
D: 0
E: 0
F: 0
G: 0
H: 0
I: 0
J: 0
K: 0
L: 0
M: 0
N: 0
O: 0
P: 0
Q: 0
R: 0
S: 0
T: 0
U: 0
V: 0
W: 0
X: 0
Y: 0
Z: 0
[: 0
: 0
]: 0
^: 0
_: 0
`: 0
a: 0
b: 0
c: 0
d: 1
e: 1
f: 0
g: 0
h: 1
i: 0
j: 0
k: 0
l: 3
m: 0
n: 0
o: 2
p: 0
q: 0
r: 1
s: 0
t: 0
u: 0
v: 0
w: 1
x: 0
y: 0
z: 0
{: 0
|: 0
}: 0
~: 0

前32个ASCII字符(值0 - 31)为" non-printable ";从某种意义上说,它们代表了具有特殊意义或行为的人物。您可以保持代码原样,但是限制实际打印输出仅包含"printable"字符。您可以从空格' '(值32)开始,以'z'(122)结束,这将给出大多数可打印文件(尽管不仅仅是字母)。

for (int i = ' '; i <= 'z'; i++) // use for loop to print frequency of characters
{       
printf("%c: %dn",table[i].value, table[i].frequency); // print characters and its frequency
}
从你的打印输出中可以看到10702CR(值13)和10702LF(值10)显示文本文件有10702个换行符,并且是一个Windows文本文件。

最新更新