Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/url/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Arrays 如何将短字符串数组传递给方法_Arrays_Delphi_Delphi 2007 - Fatal编程技术网

Arrays 如何将短字符串数组传递给方法

Arrays 如何将短字符串数组传递给方法,arrays,delphi,delphi-2007,Arrays,Delphi,Delphi 2007,我想制作一个以短字符串数组作为参数的过程 procedure f(const a, b: Array of shortstring); 我想用已知长度的数组和已知长度的短字符串来调用它 var A, B: array[1..2] of string[5]; C, D: array[1..40] of string[12]; begin f(A,B); f(C,D); end; 这将导致编译器错误E2008不兼容类型。 为什么呢?我可以写一个可以接受短字符串数组(任意长度的数组

我想制作一个以短字符串数组作为参数的过程

procedure f(const a, b: Array of shortstring);
我想用已知长度的数组和已知长度的短字符串来调用它

var
  A, B: array[1..2] of string[5];
  C, D: array[1..40] of string[12];
begin
  f(A,B);
  f(C,D);
end;
这将导致编译器错误E2008不兼容类型。 为什么呢?我可以写一个可以接受短字符串数组(任意长度的数组/字符串)的过程吗

为什么使用短字符串?


短消息是现有记录中的字段。有很多这样的记录有上千个短字符串。为了将数据从turbo power B-Tree文件管理器迁移到SQL数据库,一个步骤是将记录转换为数据集,然后再转换回记录,以确认所有字段在两个方向上都正确转换。我一直在使用记录上的
compareM
来检查这一点,但它没有提供足够的信息,说明转换错误在哪个字段中。因此,创建了一个小程序,它可以根据记录定义生成代码来比较两个记录。正是为了这个代码生成器,我需要一个函数来比较短字符串。它最后在短字符串上使用了
compareM

短字符串的长度为0到255个字符。短字符串的长度可以动态更改,但内存是静态分配的256字节,第一个字节存储字符串的长度,剩余的255字节可用于字符,而以这种方式声明的列表字符串[5]只分配类型所需的内存(长度为5字节+1字节)。 你可以用打字机

type
    MyString = string[5];
...
procedure f(const a, b: Array of MyString);
...

var
    A, B: array[1..2] of MyString;
begin
    f(A,B);
end;

您正在组合两种不同类型的开放阵列

首先,有一个经典的turbopascal“string”(在delphiiirc中也称为“openstring”),它本质上是string[255]。由于string[255]是所有短字符串的超集,因此开放数组特性仅将所有短字符串类型转换为它

“xx数组”语法是Delphi(4+?)开放数组。它是任何类型的开放数组,而不仅仅是字符串,调用它的语法是f(非ArrayParam,[arrayelement0,arrayelement1])

不知何故,您似乎混合了这两种语法,甚至通过添加CONST对其进行聚合,CONST通过引用传递并排除转换


我认为您假定短字符串具有性能优势。在某些情况下,它是这样的。开放式阵列不属于这种情况。即使在TP:-)

中,在类似的情况下,我也使用了以下方法:

type
  TOpenArrayOfOpenString = record
  strict private
    FSizeOfString: Integer;
    FpStart: PChar;
    FArrayLength: Integer;
    function GetItemPtr(AIndex: Integer): PShortString;
  public
    constructor Init(var AFirstString: Openstring; AArrayLength: Integer);
    function Equals(const AArray: TOpenArrayOfOpenString): Boolean;

    property SizeOfString: Integer read FSizeOfString;
    property pStart: PChar read FpStart;
    property ArrayLength: Integer read FArrayLength;
    property ItemPtrs[AIndex: Integer]: PShortString read GetItemPtr; default;
  end;

{ TOpenArrayOfOpenString }

constructor TOpenArrayOfOpenString.Init(var AFirstString: Openstring; AArrayLength: Integer);
begin
  FSizeOfString := SizeOf(AFirstString);
  FpStart := @AFirstString[0]; // incl. length byte!
  FArrayLength := AArrayLength;
end;

function TOpenArrayOfOpenString.Equals(const AArray: TOpenArrayOfOpenString): Boolean;
begin
  Result := CompareMem(pStart, AArray.pStart, SizeOfString * ArrayLength);
end;

function TOpenArrayOfOpenString.GetItemPtr(AIndex: Integer): PShortString;
begin
  Result := PShortString(pStart + AIndex * SizeOfString);
end;
您可以这样使用它:

procedure f(const a: TOpenArrayOfOpenString);
var
  i: Integer;
begin
  for i := 0 to Pred(a.ArrayLength) do
    Writeln(a[i]^);
end;

procedure Test;
var
  A: array[1..2] of string[5];
  C: array[1..40] of string[12];
begin
  f(TOpenArrayOfOpenString.Init(A[1], Length(A)));
  f(TOpenArrayOfOpenString.Init(C[1], Length(C)));
end;

它不像语言中内置的解决方案那样优雅,而且它依赖于事实/希望/…有点粗糙。。。数组中的字符串是连续排列的。但这对我来说已经有一段时间了。

谢谢你的回答。但它只解决了字符串[5]的问题。我更新了我的问题,以更好地显示我想要实现的目标。@MGH这是不可能的。字符串[5]数组和字符串[12]数组是不兼容的类型。为什么要使用短字符串?就我个人而言,我不知道它们什么时候有用。只需使用字符串数组。不要介意声明长度。你的生活会轻松得多。@David:我刚才发现它们有一个很好的用途。我越来越难以在一些高度递归的基于树的解析器代码中跟踪内存泄漏。通过将符号对象从符号名称的字符串更改为
短字符串
,该名称将内联显示在FastMM的FullDebugMode报告中的内存转储中,从而更容易找到问题。您可以通过不使用短字符串来简化此操作。声明动态数组类型并使用该类型将更加容易;如果项目使用
长度
,则可以找到数字,并且边界总是
0到高(ArrayVar)
,并将该类型的任何参数传递给您的方法。@DavidHeffernan更新了为什么使用短字符串的问题。
procedure f(const a: TOpenArrayOfOpenString);
var
  i: Integer;
begin
  for i := 0 to Pred(a.ArrayLength) do
    Writeln(a[i]^);
end;

procedure Test;
var
  A: array[1..2] of string[5];
  C: array[1..40] of string[12];
begin
  f(TOpenArrayOfOpenString.Init(A[1], Length(A)));
  f(TOpenArrayOfOpenString.Init(C[1], Length(C)));
end;