Как передать массив коротких строк в метод - PullRequest
3 голосов
/ 28 октября 2011

Я хотел бы сделать процедуру, которая принимает массив коротких строк в качестве аргумента

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 Filer в базы данных SQL одним шагом является преобразование записи в набор данных и обратно в запись, чтобы убедиться, что все поля правильно преобразованы в обоих направлениях.Я использовал CompareMem в записях, чтобы проверить это, но он не предоставляет достаточно информации о том, в каком поле находится ошибка преобразования. Таким образом, была создана небольшая программа, которая из определения записи может сгенерировать код для сравнения двухзаписей.Именно для этого генератора кода мне нужна была функция для сравнения коротких строк.В итоге получилось использовать CompareMem на коротких струнах.

Ответы [ 4 ]

7 голосов
/ 28 октября 2011

ShortString имеет длину от 0 до 255 символов.Длина ShortString может изменяться динамически, но память статически выделяется 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;
1 голос
/ 31 октября 2011

В аналогичной ситуации я использовал следующее:

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;

Это не так элегантно, как решение, встроенное в языкможет быть, и это немного странно, так как полагается на тот факт, что / надеюсь / ... что строки в массиве расположены последовательно.Но у меня это работало какое-то время.

0 голосов
/ 28 октября 2011

Вы комбинируете два разных типа открытого массива.

Во-первых, есть классическая «строка» Turbo Pascal (также называемая «openstring» в Delphi IIRC), которая по сути является строкой [255]. Поскольку строка [255] является надмножеством всех коротких строк, аспект открытого массива просто преобразует в нее все типы коротких строк.

Синтаксис «массив хх» - это открытый массив Delphi (4+?). Это открытый массив любого типа, а не только строки, и синтаксис для его вызова: f (nonarrayparam, [arrayelement0, arrayelement1]);

Каким-то образом вы, похоже, смешиваете оба синтаксиса и даже усиливаете его, добавляя CONST, который запрашивает передачу по ссылке и исключает преобразования.

Я думаю, вы предполагаете, что шортстрин имеет преимущество в производительности. В некоторых случаях так и есть. Открытый массив не является одним из таких случаев. Даже в ТП: -)

0 голосов
/ 28 октября 2011
   type
      shortStrings =array[1..2] of string[5];  
    ...
    a,b : shortString;
    ..
    procedure rock(a,b : shortStrings);
    ..
...