Kateme Hebi
Kateme Hebi

Reputation: 13

How strings differ from massive(array) of chars in Pascal?

I have a problem. Why I can't assign the value of strings to strings, but with chars it works. Why ^^^^^^? Where's string? Why There's the a[i]? Is it because internal representation of strings and chars?

 program massive.pas;
 
 type
         chars = array [1..255] of char;
 
 var
         s,s1: string;
         ch1,ch2: chars;
         i: integer;
 
 begin
         s1 := '';
         s := 'abrakadabra';
         for i := 1 to 5 do
         begin
                s1[i] := s[i];
                writeln(s1[i],#10,'^^^',s1,'^^^')
         end;
         ch2 := '';
         ch1 := 'abrakadabra';
         for i := 1 to 5 do   
         begin 
                ch2[i] := ch1[i]
                writeln(ch2[i])
         end;    
         writeln('%%%',ch2,'%%%');
         for i := 1 to 5 do 
                writeln('&&&',s1[i],'&&&');
 end.            

*Output

a
^^^^^^
b
^^^^^^
r
^^^^^^
a
^^^^^^
k
^^^^^^
a
b
r
a
k
%%%abrak%%%
&&&a&&&
&&&b&&&
&&&r&&&
&&&a&&&
&&&k&&&

Upvotes: 1

Views: 328

Answers (1)

Tom Brunberg
Tom Brunberg

Reputation: 21033

The main difference between type chars = Array[1..255] of Char and String is that a chars array has a fixed length, while the string has a dynamic length.

You did not say which compiler you use, but I do think that the String type is what in some Pascal editions is called a ShortString, with a max length of 255 chars. The space for 255 chars is preallocated and the structure includes a length field, that keeps track of assigned length of the string.

In your example, you assign s1 := ''; in other words the length is set to zero. Then you do a mistake in the for loop in assigning s1[i] := s[i]; without setting the length of s1.

Subsequent reading of s1 always return an empty string as the length field is 0.

If you would assign the characters to the string, e.g. as:

for i := 1 to 5 do
begin
  SetLength(s1, Length(s1)+1);
  s1[i] := s[i];
  writeln(s1[i],#10,'^^^',s1,'^^^');
end;

then the result would be what you originally expected. Still better to set the length to the final 5 before the for loop.

Of course there are other solutions too. One is to not set the length at all, but to concatenate the string in the loop and let it handle the length field by itself:

for i := 1 to 5 do
begin
  s1 := s1 + s[i];
  writeln(s1[i],#10,'^^^',s1,'^^^');
end;

Edit 24.12.2021:

In a comment you said: But I still don't understand, why, when i wrote s1[1] in the for loop, all worked?

...and presumably refer to this code just before end.:

for i := 1 to 5 do 
  writeln('&&&',s1[i],'&&&');

We need to look at the memory layout and know that the first byte of the memory allocated to s1 is the length of the string. It can be referred to as s[0]. Subsequent bytes hold the characters that make up the stored string and they can be referred to as s[1]..s[n].

The first byte was set to 0 when you wrote (in the very beginning):

s1 := '';
// memory content:
 0 
|_|_|_|_|_|_|_|_|_| ...

Then you added the characters to s1 by manipulating the memory directly when you wrote in the first for loop:

s1[i] := s[i];
// content after 5 characters
 0 a b r a k
|_|_|_|_|_|_|_|_|_| ...

Because you did not use concatenation (or adjusted the length while you added the characters) the length is still 0.

Then at the end in the last loop, you fetch the characters again by accessing the memory directly, and get the result you do, seemingly correct, but badly misusing the string structure.

Upvotes: 1

Related Questions