ショートストリングの配列をメソッドに渡す方法

ショートストリングを引数に取る手順を作りたいと思います

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ツリー・ファイラーからSQLデータベースへデータを移行するには、レコードをデータセットに変換し、レコードを元に戻して、すべてのフィールドが両方向に正しく変換されていることを確認します。レコードの CompareMem を使用してこれをチェックしていますが、変換エラーがどのフィールドにあるかについて十分な情報を提供していません。したがって、レコード定義から生成できる小さなプログラムが作成されました2つのレコードを比較するコード。このコードジェネレータでは、ショートストリングを比較する関数が必要でした。それは、ショートストリングで CompareMem を使用して終了しました。

3
@デイビッド:私はそれらのために良い一使用をしばらく前に見つけた。非常に再帰的なツリーベースのパーサーコードでは、トレースが困難なメモリリークが発生していました。シンボルオブジェクトの文字列から ShortString に変更することで、その名前がFastMMのFullDebugModeレポートのメモリダンプにインラインで表示され、問題。
追加された 著者 Mason Wheeler,
文字列の配列を使用するだけです。長さを宣言することは決して気にしないでください。あなたの人生ははるかに簡単になります。
追加された 著者 Johan,
なぜショートストリングを使いたいのですか?私の人生のために、私は彼らが役に立つときにはうまくいかない。
追加された 著者 David Heffernan,
ShortStringを使わないことでこれをもっと簡単にすることができます。動的配列型を宣言し、その型を使用するとはるかに簡単に動作します。 Length を使用して項目が常に 0からHigh(ArrayVar)になり、そのタイプの引数をメソッドに渡す場合は、数値を見つけることができます。
追加された 著者 Ken White,
@DavidHeffernanショートストリングが使われる理由についての質問を更新しました。
追加された 著者 MGH,

4 答え

ShortStringの長さは0〜255文字です。 ShortStringの長さは動的に変更することができますが、メモリは静的に割り当てられた256バイトです。最初のバイトは文字列の長さを格納し、残りの255バイトは文字に使用でき、whilist 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;
7
追加された
@MGHそれは不可能です。 string [5]の配列とstring [12]の配列は互換性のない型です。
追加された 著者 Ondrej Kelle,
答えをありがとう。それは文字列[5]の問題を解決するだけです。私は、私が達成したいことをより良く示すために質問を更新しました。
追加された 著者 MGH,

2種類のオープンアレイを組み合わせています。

まず、本質的に文字列[255]である古典的なTurbo Pascal "文字列"(Delphi IIRCの "openstring"とも呼ばれます)があります。 string [255]はすべてのショートストリングのスーパーセットであるため、オープン・アレイのアスペクトはすべてのショートストリング・タイプを単純にそのストリング・タイプに変換します。

「xxの配列」の構文は、Delphi(4+?)オープンアレイです。それは文字列だけでなく、あらゆるタイプのオープンな配列であり、それを呼び出す構文はf(nonarrayparam、[arrayelement0、arrayelement1])です。

どういうわけか、両方の構文を混在させて、CONSTを追加することによってもそれをaggrevateするように見えます。これは、ソルリッツが参照渡しでコンバートを除外します。

ショートストリングにはパフォーマンス上の利点があると思います。場合によってはそれがあります。 Open Arrayはそうしたケースの1つではありません。 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;

言語に組み込まれたソリューションが可能であるほどエレガントではないし、配列内の文字列が連続して配置されているという事実/希望/に依存しているのでちょっとハッキリです。しかし、それは私のためにしばらくの間働いた。

1
追加された
   type
      shortStrings =array[1..2] of string[5];  
    ...
    a,b : shortString;
    ..
    procedure rock(a,b : shortStrings);
    ..
0
追加された