2011-10-28 12 views
3

我想做出採取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?

短缺是現有記錄中的字段。有很多這樣的記錄有很多短串。爲了將數據從渦輪增強B-Tree Filer遷移到SQL數據庫,一步就是將記錄轉換爲數據集,並將數據轉換回記錄,以確認所有字段都在兩個方向上正確轉換。我一直在記錄上使用CompareMem來檢查這個問題,但它沒有提供足夠的信息來說明轉換錯誤在哪個字段中。因此創建了一個小程序,它可以從記錄定義中生成代碼來比較兩條記錄。這是代碼生成器,我需要一個函數來比較短字符串。它最終在短褲上使用了CompareMem

+5

爲什麼要使用短弦?對於我的生活,當他們有用時我無法解決。 –

+2

只需使用一個字符串數組。不要介意宣佈長度。你的生活會容易得多。 – Johan

+1

@David:前段時間我發現了一個很好用的東西。在一些大量遞歸的基於樹的解析器代碼中,我遇到了難以跟蹤的內存泄漏。通過將符號對象從符號名稱的**字符串**更改爲「ShortString」,該名稱在FastMM的FullDebugMode報告的內存轉儲中內聯顯示,使得查找問題變得更加容易。 –

回答

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; 

它不是作爲一種解決方案爲優雅內置到語言中可能會有點冒失,因爲它依賴於事實/希望/ ......陣列中的字符串是連續佈局的。但它現在對我來說已經有一段時間了。

7

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; 
+0

感謝您的回答。它只解決了string [5]的問題。我更新了我的問題,以更好地表明我想實現的目標。 – MGH

+4

@MGH這是不可能的。字符串[5]的數組和字符串[12]的數組是不兼容的類型。 –

0
type 
     shortStrings =array[1..2] of string[5]; 
    ... 
    a,b : shortString; 
    .. 
    procedure rock(a,b : shortStrings); 
    .. 
-1

要結合使用兩種不同類型的開放數組。

首先,經典的Turbo Pascal「字符串」(在Delphi IIRC中也稱爲「openstring」)基本上是字符串[255]。由於字符串[255]是所有短字符串的超集,開放數組方面只是將所有短字符串類型轉換爲它。

「xx數組」語法是Delphi(4+?)開放數組。它是一個任意類型的開放數組,不只是字符串,並且調用它的語法是f(nonarrayparam,[arrayelement0,arrayelement1]);

不知何故,您似乎混合了兩種語法,甚至通過添加CONST來解決這個問題,從而通過引用來傳遞並排除轉換。

我認爲你認爲短褲具有性能優勢。它有,在某些情況下。開放數組不是其中之一。甚至在TP :-)