我可以在 pascal 中定义自己的字符串类型吗?

问题描述 投票:0回答:2

我读过我不能真正在 pascal 中动态分配数组,但我也在考虑实现一个字符串结构。
在 C 中,我将通过创建一个

struct
来解决这个问题,其中包含一个指向字符数组(包含字符)的指针、一个长度整数和一个大小一。然后,当需要调整大小时,我会
malloc
char *
realloc
它。

typedef struct {
    size_t size;
    size_t length;
    char* contents;
} String;

这可以在 (ISO) pascal 中完成吗?如果是这样,人们会怎样做呢?我不想使用内置的 pascal 动态数组,因为它有点违背了创建我自己的字符串类型的目的。

从评论来看,ISO pascal(标准的和扩展的)似乎不支持这样的东西。那么我该如何在 free pascal 中做到这一点呢?

memory-management pascal
2个回答
3
投票

在 Free Pascal 中,它可以类似于前面提到的 C 方法来实现:

type
TMyString = record
  size: SizeUInt;
  length: SizeUInt;
  contents: PAnsiChar;
end;

...

procedure AllocMyString(var S: TMyString; L: SizeUInt);
begin
  S.size := 0;
  S.length := L;
  GetMem(Pointer(S.contents), L);
end;

procedure ReallocMyString(var S: TMyString; L: SizeUInt);
begin
  S.size := 0;
  S.length := L;
  ReAllocMem(Pointer(S.contents), L);
end;

0
投票

我可以在 Pascal 中定义自己的字符串类型吗?

您需要观察字符串数据类型的以下特征: ISO 标准 7185 和 10206 定义的 Pascal a 字符串数据类型 is a

  • 线性(恰好一维)
  • packed
  • array of
  • 内置数据类型)
    char
  • integer
    索引
    1
    开始,并且
  • 以大于
    integer
    1
    指数结束。

例如

packed array[1..2] of char
是字符串数据类型。 如果目标是
write
文件,则可以将此类字符串变量传递给内置过程
writeLn
text
;如果源是 read,则还可以将此类字符串变量传递给 readLn
text
 
in
 扩展 Pascal 
文件。

我读过我无法真正在 Pascal 中动态分配数组 [...]

是/否:

  • 对于 ISO 标准 7185 定义的标准 Pascal,这种说法在实践中是正确的,在理论上(通常)是错误的。 根据实现的不同,您可以动态分配不同数量的内存,但开销是非常不切实际的:

    program variableLengthStringDemo(output);
        const
            stringMaximumLength = 4;
        type
            integerNonNegative = 1..maxInt;
            stringLength       = 0..stringMaximumLength;
            stringCapacity     = 1..stringMaximumLength;
            string = record
                    length: stringLength;
                    case capacity: stringCapacity of
                        1: (character:           packed array[1..1] of char);
                        2: (characterPair:       packed array[1..2] of char);
                        3: (characterTriplet:    packed array[1..3] of char);
                        4: (characterQuadruplet: packed array[1..4] of char);
                end;
        var
            word: ^string;
        begin
            new(word, 3);
            word^.characterTriplet := 'ABC';
            word^.length := 3;
            writeLn(word^.characterTriplet)
        end.
    

    对于已识别的

    record
    变量(identified 在 ISO 术语中本质上是指指针),内置过程
    new
    dispose
    接受更多参数来选择特定变体。 这允许处理器的实现者“仅分配所需的内存”,但标准并未强制要求这样做。 然而,强制规定的是这样的变量不能再改变变体。 在上面的代码中,word^.capacity
    锁定
    3
    此外,由于所有 

    record

    变体中的标识符必须是唯一的,因此您也必须在代码中处理多个标识符。 这使得使用这种方法处理字符串来达到生产目的几乎毫无用处。 您不能每次在代码中进行分支只是为了为当前活动的变体选择正确的标识符。 这太疯狂了。

    
    

  • 对于 ISO 标准 10206 定义的
  • Extended Pascal

    ,这种说法是完全错误的。 EP 定义了模式数据类型的概念。 模式数据类型表示“一组”数据类型。 你需要区分这个集合,从包里“选择”一个数据类型,来使用它。 判别式也可以提供给 newdispose

    program variableLengthArrayDemo(output);
        type
            characterSequence(capacity: integer)
            = packed array[1..capacity] of char;
        var
            cheerfulMessage: ^characterSequence;
        begin
            new(cheerfulMessage, 12);
            cheerfulMessage^ := 'Hello world!';
            writeLn(cheerfulMessage^)
        end.
    
    EP中还有其他实现变长数组的方法,这只是其中一种。

    
    

    注意: 在 EP 和 SP 中,如果您

    dispose
  • 识别了变量,
dispose

需要与相应的

new
完全相同的参数。
new(variable, 3)
 →
dispose(variable, 3)
: 实际上,有

固定字符串类型

(这里介绍),可变字符串类型(EP的string模式)和规范字符串类型(纯粹用于定义目的的元数据类型),统称为

字符串类型
. [...] 那么我该如何在 Free Pascal 中做到这一点?


在 FreePascal 中
  • 任何类型的

    array of

    • char
    • char
    • 的衍生物作为其基本类型
      具有单一维度
      这是一个内置序数数据类型或其派生
    • 是一个字符串。 FreePascal 方言允许您对变量进行类型转换。

    New
  • (和
  • dispose

    )仅在

    {$mode ISO}
    {$mode extendedPascal}
    中接受进一步的参数。
    
    
    截至 2024 年,

    FreePascal 编译器(仍然)打算支持 ISO 10206
  • ,但仍缺少对架构数据类型的支持。
© www.soinside.com 2019 - 2024. All rights reserved.