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

发布于 2024-12-12 09:22:57 字数 638 浏览 0 评论 0原文

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

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 不兼容类型。 这是为什么?我可以编写一个可以接受短字符串数组(任意长度的数组/字符串)的过程吗?

为什么使用短字符串?

短字符串是现有记录中的字段。有很多这样的唱片有数千个短弦。为了将数据从涡轮增压 B-Tree Filer 迁移到 SQL 数据库,第一步是将记录转换为数据集,然后再转换回记录,以确认所有字段都在两个方向上正确转换。我一直在记录上使用 CompareMem 来检查这一点,但它没有提供足够的信息来说明转换错误位于哪个字段。因此创建了一个小程序,可以从记录定义生成比较两条记录的代码。对于这个代码生成器,我需要一个函数来比较短字符串。它最终在短字符串上使用了CompareMem。

I would like to make a procedure that take array of shortstring as argument

procedure f(const a, b: Array of shortstring);

I would like to call this with arrays of known length and shortstrings of known length e.g.

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;

This result in an compiler error E2008 Incompatible types.
Why is that? Can I write a procedure that can take arrays of shortstring (any length of arrays/strings)?

Why use shortstring?

The shortstings are fields in an existing record. There are alot of these record with thousand of shortstrings. In an effort to migrate data from turbo power B-Tree Filer to SQL databases one step is to convert the record to a dataset, and the back to a record, to confirm all fields are converted correctly both directions. I have been using CompareMem on the records to check this, but it does not provide enough information as to which field a conversion error is in. Thus a small program was created, which from the record definition can generate code to compare the two records. It was for this code generator I needed a function to compare shortstrings. It ended up using CompareMem on the shortstrings.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

夏花。依旧 2024-12-19 09:22:57

ShortString 的长度为 0 到 255 个字符。 ShortString 的长度可以动态改变,但内存是静态分配的 256 个字节,第一个字节存储字符串的长度,其余 255 个字节可用于字符,而以这种方式声明的 string[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;

A ShortString is 0 to 255 characters long. The length of a ShortString can change dynamically, but memory is a statically allocated 256 bytes, the first byte stores the length of the string, and the remaining 255 bytes are available for characters, whilist string[5] declared in this way allocate only as much memory as the type requires (5 byte + 1 byte for length).
you could use type

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;
梦萦几度 2024-12-19 09:22:57

在类似的情况下,我使用了以下内容:

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;

它不像语言中内置的解决方案那么优雅,而且它有点hacky,因为它依赖于事实/希望/...数组中的字符串是连续排列的。但它对我有用了一段时间。

In a similar situation I've used the following:

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;

You could use it like this:

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;

It's not as elegant as a solution built into the language could be and it is a bit hacky as it relies on the fact/hope/... that the strings in the array are laid out contiguously. But it worked for me for some time now.

老娘不死你永远是小三 2024-12-19 09:22:57
   type
      shortStrings =array[1..2] of string[5];  
    ...
    a,b : shortString;
    ..
    procedure rock(a,b : shortStrings);
    ..
   type
      shortStrings =array[1..2] of string[5];  
    ...
    a,b : shortString;
    ..
    procedure rock(a,b : shortStrings);
    ..
心是晴朗的。 2024-12-19 09:22:57

您正在组合两种不同类型的开放数组。

首先,有经典的 Turbo Pascal“字符串”(在 Delphi IIRC 中也称为“openstring”),它本质上是 string[255]。由于 string[255] 是所有短字符串的超集,因此开放数组方面只是将所有短字符串类型转换为它。

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

不知怎的,你似乎混合了两种语法,甚至通过添加 CONST 来聚合它,它要求通过引用传递并排除转换。

我认为您认为短弦具有性能优势。在某些情况下确实如此。开放阵列不是其中之一。即使在 TP 中也没有:-)

You are combining two different kinds of open array.

First, there is the classic Turbo Pascal "string" (also called "openstring" in Delphi IIRC) which is essentially string[255]. As string[255] is a superset of all shortstrings, the open array aspect simply converts all shortstring types to it.

The "array of xx" syntax is the Delphi (4+?) open array. It is an open array of any type, not just strings, and the syntax to call it is f(nonarrayparam,[arrayelement0,arrayelement1]);

Somehow you seem to mix both syntaxes, and even aggrevate it by adding CONST which sollicits pass by reference and excludes conversions.

I think you assume shortstring has an performance advantage. It has, in some cases. Open array is not one of those cases. Not even in TP :-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文