I wrote this program that counts the number of letters in random.txt file in the Pascal programming language.
It doesn't matter if the letters are capitalized. Other characters are ignored. When it finishes it writes every letter in a single line and then after it the number of appearences of that letter in the text file.
program letters;
var
random:text;
a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1,q1,r1,s1,t1,u1,v1,w1,x1,y1,z1:integer;
procedure counting(random:text; var a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1,q1,r1,s1,t1,u1,v1,w1,x1,y1,z1:integer);
var
c:char;
begin
a1:=0;
b1:=0;
c1:=0;
d1:=0;
e1:=0;
f1:=0;
g1:=0;
h1:=0;
i1:=0;
j1:=0;
k1:=0;
l1:=0;
m1:=0;
n1:=0;
o1:=0;
p1:=0;
q1:=0;
r1:=0;
s1:=0;
t1:=0;
u1:=0;
v1:=0;
w1:=0;
x1:=0;
y1:=0;
z1:=0;
while not eof(random) do
while not eoln do
begin
if (c='A') or (c='a') then a1:=a1+1;
if (c='B') or (c='b') then b1:=b1+1;
if (c='C') or (c='c') then c1:=c1+1;
if (c='D') or (c='d') then d1:=d1+1;
if (c='E') or (c='e') then e1:=e1+1;
if (c='F') or (c='f') then f1:=f1+1;
if (c='G') or (c='g') then g1:=g1+1;
if (c='H') or (c='h') then h1:=h1+1;
if (c='I') or (c='i') then i1:=i1+1;
if (c='J') or (c='j') then j1:=j1+1;
if (c='K') or (c='k') then k1:=k1+1;
if (c='L') or (c='l') then l1:=l1+1;
if (c='M') or (c='m') then m1:=m1+1;
if (c='N') or (c='n') then n1:=n1+1;
if (c='O') or (c='o') then o1:=o1+1;
if (c='P') or (c='p') then p1:=p1+1;
if (c='Q') or (c='q') then q1:=q1+1;
if (c='R') or (c='r') then r1:=r1+1;
if (c='S') or (c='s') then s1:=s1+1;
if (c='T') or (c='t') then t1:=t1+1;
if (c='U') or (c='u') then u1:=u1+1;
if (c='V') or (c='v') then v1:=v1+1;
if (c='W') or (c='w') then w1:=w1+1;
if (c='X') or (c='x') then x1:=x1+1;
if (c='Y') or (c='y') then y1:=y1+1;
if (c='Z') or (c='z') then z1:=z1+1;
end;
close(random);
end;
procedure result(a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1,q1,r1,s1,t1,u1,v1,w1,x1,y1,z1:integer);
begin
writeln('A','',a1);
writeln('B','',b1);
writeln('C','',c1);
writeln('D','',d1);
writeln('E','',e1);
writeln('F','',f1);
writeln('G','',g1);
writeln('H','',h1);
writeln('I','',i1);
writeln('J','',j1);
writeln('K','',k1);
writeln('L','',l1);
writeln('M','',m1);
writeln('N','',n1);
writeln('O','',o1);
writeln('P','',p1);
writeln('Q','',q1);
writeln('R','',r1);
writeln('S','',s1);
writeln('T','',t1);
writeln('U','',u1);
writeln('V','',v1);
writeln('W','',w1);
writeln('X','',x1);
writeln('Y','',y1);
writeln('Z','',z1);
end;
begin
assign(random,'random.txt');
reset(random);
counting(random,a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1,q1,r1,s1,t1,u1,v1,w1,x1,y1,z1);
result(a1,b1,c1,d1,e1,f1,g1,h1,i1,j1,k1,l1,m1,n1,o1,p1,q1,r1,s1,t1,u1,v1,w1,x1,y1,z1);
readln();
end.
I'm a beginner and I suppose this can be done a lot better and simpler without having to use 26 variables. How could I improve my code to make it work better? Could you give me some tips?
1 Answer 1
Declaring 26 individual counter variables: Now this is generally considered bad style. These 26 variables fulfill a common purpose, yet they are completely independent from each other. A simple solution would at least use
var chart: array[char] of integer;
Now this is quite wasteful, because the range
chr(0)..maxChar
which we’re using for this array’s first and only dimension contains lots of unused entries. Specifically, bothchart['A']
andchart['a']
coexist. We can remediate this situation and declare anarray
containing only 26integer
values, or we can leave this as is and simply printchart['A'] + chart['a']
in our final printing procedure.-
procedure counting(random:text; [...]
Parameters of the data type
file of ...
(including parameters of the data typetext
) always must be passed asvar
parameters. Any decent compiler will reject your code. -
var random:text; a1,...,z1:integer procedure counting(random:text; var a1,...,z1:integer); [...] procedure result(a1,...,z1:integer);
Now this shows that you have not understood the concept of scopes. Because you have declared your variables before the definitions of
counting
andresult
, you can access them directly incounting
andresult
. There is no need to pass all variables in parameters. The entire parameter list could be left out and yourprogram
would still work (you, of course, have to adjust the calls below accordingly).Generally speaking, global variables, i. e. the declaration of variables before any routines, is considered bad. I would simply move the
var
-section you have down below the procedures, right before the program’s "main"begin ... end
. -
a1:=0; ... z1:=0;
If you had an Extended Pascal (ISO standard 10206) compliant compiler, you could specify an initial value at the variable declaration, like so:
var a1, b1, c1: integer value 0;
You do not read anything in the reading loop:
while not {EOF / EOLn respectively} do [...] end;
Is an infinite loop, because your "reading cursor" remains at the same position. There is no
read(random, c)
. This also means yourc
remains uninitialized. You’re reading an uninitialized value which is very bad.In Pascal the expression
(c='A') or (c='a')
is usually written as
c in ['A', 'a']
Since any
Boolean
expression can be converted into aninteger
usingord
, you could rephrase your line(s)if (c='A') or (c='a') then a1:=a1+1;
to
a1 := a1 + ord(c in ['A', 'a']);
This will add
0
or1
toa1
. Some people find this more elegant instead of single-lineif ... then
s.-
writeln('A','',a1);
Writing an empty string (
''
) has no effect. Maybe you wanted append a minimum width specifier to create a tabular look?writeLn('A', '':4, a1);
-
\$\begingroup\$ Thanks for this great answer - I hope to see more from you in future! \$\endgroup\$Toby Speight– Toby Speight2022年10月18日 16:12:18 +00:00Commented Oct 18, 2022 at 16:12
-
1\$\begingroup\$ @TobySpeight Unfortunately there are very few pascal code review requests. It’s already weird to respond to a five year old request. Frankly I think Plexus (the requester) would not write such code today, so he does not need any feedback (anymore). \$\endgroup\$Kai Burghardt– Kai Burghardt2022年10月18日 19:27:53 +00:00Commented Oct 18, 2022 at 19:27
-
\$\begingroup\$ There are also few Pascal answerers, which makes your contribution the more welcome! Answering old questions is fine, as we aim to help all programmers improve their code (not just the askers), so please do continue doing that. I find that answering (in the languages I know - it's over 30 years since I touched any Pascal) also improves my own skills, too. \$\endgroup\$Toby Speight– Toby Speight2022年10月19日 06:47:52 +00:00Commented Oct 19, 2022 at 6:47
c >= 'A' and c <= 'Z'
and in case subtract'A'
to get index of array. Increment item at that index by 1. If your library does not have atolower()
function then repeat fora
. Then use proper indentation and meaningful names (random
as parameter name? Why?) \$\endgroup\$