字符串与 Pascal 中的大量(数组)字符有何不同?

Posted

技术标签:

【中文标题】字符串与 Pascal 中的大量(数组)字符有何不同?【英文标题】:How strings differ from massive(array) of chars in Pascal? 【发布时间】:2022-01-24 05:34:12 【问题描述】:

我有问题。为什么我不能将字符串的值分配给字符串,但使用字符它可以工作。为什么^^^^^^?字符串在哪里?为什么会有 a[i]? 是因为字符串和字符的内部表示吗?

 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.            

*输出

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

【问题讨论】:

您使用的数据类型string 没有标准化。您可能想指出您正在使用哪个编译器。你能告诉我们你想做什么,你首先写了什么代码吗?如果你想为array[1..255] of char 分配一个值,你需要提供一个“赋值兼容”的值。对于数组,这意味着 恰好 255 个char 值的序列。但是,反过来通常也可以,因为有各种(非标准)算法可以容纳太多(或太少)char 值,例如默默地剪裁/丢弃(或在末尾插入空格)。 【参考方案1】:

type chars = Array[1..255] of CharString 的主要区别在于chars 数组具有固定长度,而字符串具有动态长度。

您没有说您使用哪个编译器,但我确实认为 String 类型在某些 Pascal 版本中被称为 ShortString,最大长度为 255 个字符。 255 个字符的空间是预先分配的,结构包括一个长度字段,用于跟踪字符串的分配长度。

在您的示例中,您分配s1 := '';,换句话说,长度设置为零。那么你在分配s1[i] := s[i];时在for loop中犯了一个错误没有设置s1的长度

s1 的后续读取总是返回一个空字符串,因为长度字段为 0。

如果您要将字符分配给字符串,例如如:

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

那么结果将是您最初所期望的。 最好将长度设置为for loop之前的最后5个。

当然还有其他解决方案。一种是根本不设置长度,而是将循环中的字符串串联起来,让它自己处理长度字段:

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

编辑 24.12.2021:

在你说的评论中:但我还是不明白,为什么,当我在 for 循环中写 s1[1] 时,一切正常?

...并且大概在end.之前参考了这段代码:

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

我们需要查看内存布局,知道分配给s1的内存的第一个字节是字符串的长度。可以参考s[0]。后续字节包含组成存储字符串的字符,它们可以称为 s[1]..s[n]。

当你写的时候(一开始)第一个字节被设置为0:

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

然后你在第一个for循环中写入时,通过直接操作内存将字符添加到s1

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

因为您没有使用连接(或在添加字符时调整长度),所以长度仍为 0。

然后在最后一个循环的最后,你通过直接访问内存再次获取字符,并得到你所做的结果,看似正确,但严重误用了字符串结构。

【讨论】:

但我还是不明白,为什么,当我在for循环中写s1[1]时,一切都奏效了? 你的问题和你在s1上的操作方式有关,所以重点说一下。 s1 使用的内存大小为 256 字节,由于它是全局变量,因此在程序执行期间永远不会被释放。否则你的评论是正确的,但只是重新表述:内容的解释取决于长度字节,s [0]。如果为 0,则字符串被认为是空的(不管其他字节包含什么)。如果 s[0] 的值是 1 .. 255,那么从 s[1] 向前考虑那么多字符。

以上是关于字符串与 Pascal 中的大量(数组)字符有何不同?的主要内容,如果未能解决你的问题,请参考以下文章

ORM 和 JDBC有何不一样

在delphi中,这个PChar指针的作用是啥?

使用 C# 将 JSON 字符串从 Camel 案例转换为 Pascal 案例

使用gdb时,如何在Pascal中打印数组中的一部分值

如何将文件中的字符存储到数组中

DELPHI清除TXT文件内重复字符串