Як перадаць масіў ShortString да спосабу

Я хацеў бы зрабіць працэдуру, узяць масіў з ShortString ў якасці аргументу

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

Я хацеў бы назваць гэта з масівамі вядомай даўжыні і shortstrings вядомай даўжыні, напрыклад,

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 Несумяшчальныя тыпы. Чаму гэта? Ці магу я напісаць працэдуру, якая можа прымаць масівы ShortString (любой даўжыні масіваў/радкоў)?

<Моцны> Навошта выкарыстоўваць ShortString?

У shortstings з'яўляюцца поля ў існуючай запісу. Ёсць шмат гэтых запісаў з тысячамі shortstrings. У спробе пераносу дадзеных з турба магутнасці B-Tree Filer да баз дадзеных SQL адзін крок, каб пераўтварыць запіс у наборы дадзеных, і спіной да запісу, каб пацвердзіць усе палі пераўтворацца правільна ў абодвух напрамках. Я выкарыстоўваю CompareMem на запісы, каб праверыць гэта, але гэта не дае дастаткова інфармацыі аб тым, якія поля памылкі пераўтварэнні. Такім чынам была створана невялікая праграма, якая з вызначэння запісу можа генераваць код для параўнання двух запісаў. Менавіта для гэтага генератара кода мне патрэбна функцыя для параўнання shortstrings. Гэта ў канчатковым выніку, выкарыстоўваючы CompareMem на shortstrings.

3
@David: Я знайшоў адно добрае прымяненне для іх некаторы час таму. Я атрымліваю ўцечкі цяжка паддаецца следу памяці ў некаторай ступені рэкурсіўнага дрэва на аснове сінтаксічнага аналізу кода. Змяняючы аб'ект знака з радок для імя сімвала ў ShortString , назва з'явіўся ўбудаваны ў дамп памяці ў справаздачы FullDebugMode FastMM, што робіць яго значна лягчэй знайсці праблема.
дададзена аўтар Mason Wheeler, крыніца
Проста выкарыстоўвайце масіў радка. Нічога пра абвяшчэнне даўжыні. Ваша жыццё будзе нашмат прасцей.
дададзена аўтар Johan, крыніца
Чаму вы хочаце выкарыстоўваць shortstrings? Для жыцця мяне я не магу працаваць, калі яны карысныя.
дададзена аўтар David Heffernan, крыніца
Вы можаце зрабіць гэта значна лягчэй на сябе, не выкарыстоўваючы ShortString. Аб'яву дынамічнага тыпу масіва і выкарыстаць гэты тып будзе працаваць значна лягчэй; вы можаце знайсці лік, калі элементы выкарыстоўваючы Даўжыня і межы заўсёды будзе 0 да высокага (ArrayVar) , і перадаць любы аргумент гэтага тыпу да вашага метаду.
дададзена аўтар Ken White, крыніца
@DavidHeffernan Абноўлены пытанне з тым, чаму выкарыстоўваюцца shortstrings.
дададзена аўтар MGH, крыніца

4 адказы

ShortString даўжынёй ад 0 да 255 знакаў. Даўжыня ShortString можа дынамічна змяняцца, але памяць ўяўляе сабой статычны 256 байт, першы байт захоўвае даўжыню радка, а астатнія 255 байт даступныя для сімвалаў, whilist радкі [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;
7
дададзена
@MGH Гэта немагчыма. Масіў радкі [5] і масіў радкі [12] ня сумяшчальныя тыпы.
дададзена аўтар Ondrej Kelle, крыніца
Дзякуй за адказ. Гэта вырашае толькі праблему для радкі [5], хоць. Я абнавіў мой пытанне, каб лепш паказаць, што я хацеў бы дасягнуць.
дададзена аўтар MGH, крыніца

Вы аб'ядноўваеце два розных тыпу адкрытага масіва.

Па-першае, гэта класічны Турба Паскаль «радок» (таксама званы «openstring» у Delphi IIRC), які, па сутнасці, радок [255]. У радку [255] з'яўляецца падмноствам усіх shortstrings, адкрыты аспект масіва проста пераўтворыць ўсе тыпы ShortString да яго.

«Масіў ого» сінтаксіс з'яўляецца Delphi (4 +?) Адкрытым масівам. Гэта адкрыты масіў любога тыпу, а не толькі радкі і сінтаксіс для выкліку яго ў е (nonarrayparam, [arrayelement0, arrayelement1]);

Неяк вы, здаецца, змешваць абодва сінтаксісу, і нават aggrevate, дадаўшы CONST які sollicits праходу даведачных і не ўключаюць пераўтварэнні.

Я думаю, што вы мяркуеце ShortString мае перавагу ў прадукцыйнасці. Яна мае, у некаторых выпадках. Адкрыты масіў не адзін з тых выпадкаў. Нават не ў TP :-)

1
дададзена

У падобнай сітуацыі я выкарыстаў наступнае:

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, як належала ў факт/надзея/... што радкі ў масіве размяшчаюцца сумежна. Але ён працаваў на мяне на працягу некаторага часу.

1
дададзена
   type
      shortStrings =array[1..2] of string[5];  
    ...
    a,b : shortString;
    ..
    procedure rock(a,b : shortStrings);
    ..
0
дададзена