2013-10-23 88 views
4

我正在實現一個解釋器,我的解釋器將支持的功能之一就像Delphi的Format。實際上,我正在使用SysUtils.Format來實現我的功能。但是,我在構建函數的第二個參數array of TVarRec時遇到了問題。如何構建一個const數組?

假設我有以下代碼。目前,我只是假設解釋代碼需要訪問哪些Delphi變量(iVar1iVar2),但我仍然不知道如何將它們放入Format要求的結構(arFormatArgs)中。

type TFormatArgs = array of TVarRec; 

procedure RunInterpretedFormatFunction; 
var 
    iMyAge: integer; 
    iMyIQ: integer; 
    sCode: string; 
    sText: string; 
begin 
    iMyAge := 5; 
    iMyIQ := -5; 
    sCode := 'Format(''My age is %d and my IQ is %d'', [iMyAge, iMyIQ])'; 
    sText := FormatThis(sCode, iMyAge, iMyIQ); 
end; 

function FormatThis(sFormatCode: string; iVar1: integer; iVar2: integer): string; 
var 
    sFormatString: string; 
    arFormatArgs: TFormatArgs; 
begin 
    sFormatString := GetFormatString(sFormatCode); // I can implement this function 
    arFormatArgs := ConstructFormatArgs(iVar1, iVar2); // NEED HELP HERE! 
    result := SysUtils.Format(sFormatString, arFormatArgs); 
end; 

如何在Delphi(不是Assembly)中實現我的ConstructFormatArgs函數?

+0

您是否看到http://docwiki.embarcadero.com/CodeExamples/XE2/en/SysUtilsFormat_%28Delphi%29示例?我不確定'consructformatargs'是什麼,但是你是否嘗試用ivar1和ivar2代替結果中的arformatargs? –

+0

嗯,我只是建議它導致它顯示'sysutils.format'的規則不知道'constructformatargs'在做什麼。我想你可以看看它,看arFormatARgs是否遵循這些規則。 –

+0

@Sam對不起,我不認爲我可以幫忙。如果你不知道'ConstructFormatArgs'是什麼,你會如何知道它遵循規則?如果它遵守規則,那麼問題是什麼?無論如何,祝你好運,我相信有人在這個更好,然後我可以幫助。 –

回答

4

const的數組讓你可以自由添加字符串,整數,浮點數等,並將它們格式化爲一個字符串。並且您可以添加多少項目沒有限制。

Delphi處理這個問題的方式是const數組真的是一個TVarRec數組。

甲TVarRec是以下類型的記錄:

TVarRec = record 
    case Byte of 
    vtInteger: (VInteger: Integer; VType: Byte); 
    vtBoolean: (VBoolean: Boolean); 
    vtChar:  (VChar: Char); 
    vtExtended: (VExtended: PExtended); 
    vtString:  (VString: PShortString); 
    vtPointer: (VPointer: Pointer); 
    vtPChar:  (VPChar: PChar); 
    vtObject:  (VObject: TObject); 
    vtClass:  (VClass: TClass); 
    vtWideChar: (VWideChar: WideChar); 
    vtPWideChar: (VPWideChar: PWideChar); 
    vtAnsiString: (VAnsiString: Pointer); 
    vtCurrency: (VCurrency: PCurrency); 
    vtVariant: (VVariant: PVariant); 

的類型TVarRec內的值是由VType值確定。

這給你靈活地添加任一鍵入要const的陣列,如在格式()函數:

格式(「%s是一個字符串,%d是整數」,[ 'string',10]);

在你自己的程序中使用const數組並不是什麼大事。看看這個例子:

procedure VarArraySample(AVarArray : array of const); 
    var 
    i : integer; 
    begin 
    for i := 0 to High(AVarArray) do 
     do_something; 
    end; 

函數High()返回數組的最後一個索引。

您也可以轉換TVarRec的內容。這個例子取自Delphi的在線幫助,並進行了一些修改。該功能的TVarRec轉換爲字符串:

function VarRecToStr(AVarRec : TVarRec) : string; 
    const 
    Bool : array[Boolean] of string = ('False', 'True'); 
    begin 
    case AVarRec.VType of 
     vtInteger: Result := IntToStr(AVarRec.VInteger); 
     vtBoolean: Result := Bool[AVarRec.VBoolean]; 
     vtChar:  Result := AVarRec.VChar; 
     vtExtended: Result := FloatToStr(AVarRec.VExtended^); 
     vtString:  Result := AVarRec.VString^; 
     vtPChar:  Result := AVarRec.VPChar; 
     vtObject:  Result := AVarRec.VObject.ClassName; 
     vtClass:  Result := AVarRec.VClass.ClassName; 
     vtAnsiString: Result := string(AVarRec.VAnsiString); 
     vtCurrency: Result := CurrToStr(AVarRec.VCurrency^); 
     vtVariant: Result := string(AVarRec.VVariant^); 
    else 
     result := ''; 
    end; 
    end; 

您可以結合上面的一個函數,常量數組中的所有元素轉換成一個字符串中的兩個功能:

function VarArrayToStr(AVarArray : array of const) : string; 
    var 
    i : integer; 
    begin 
    result := ''; 
    for i := 0 to High(AVarArray) do 
     result := result + VarRecToStr(AVarArray[i]); 
    end; 

你現在會能夠創建自己的Format()函數。 Format()函數根據格式說明符和精度說明符掃描%的值,並將const值替換爲const數組中的值。

2

如您所知,array of constarray of TVarRec相同。要構建一個,首先聲明一個數組,然後設置每個元素的值,就像其他數組一樣。

TVarRec是一個變體記錄,這意味着它可以容納許多不同類型的值。它有一個字段VType,用於指示它所保存的值的類型。在其他字段中,一次只有一個字段具有有效值。設置VType字段,然後設置相應的值字段,如VIntegerVString

請注意,某些字段實際上是指針,如VVariantVInt64。當您分配這些指針值時,您需要確保只要Format需要它,它們指向的任何內容都將保持可訪問和有效。

其他字段是其真實值類型的無類型版本。這些包括VAnsiStringVInterface。當您分配給這些字段時,請注意,它們不會保留通常的參考計數,即普通的AnsiStringIUnknown變量會再次觀察這些變量的生存期。

編譯器通常是生成這種數組的唯一東西,所以幾乎沒有可用的參考代碼來查看它們的構建方式。相反,你可以看看使用const數組的其他代碼。例如,我在幾年前實施了a Unicode-aware Format function for the JCL。它使用有限狀態機一次解析格式字符串一個字符。每次完成解析參數字符串時,它都會從輸入數組中獲取相應的參數,並根據字符串和參數類型對其進行格式化。

它使用最少的彙編程序,只是爲了一些次要的效率,並不是因爲它真的有必要。作爲參考,所有彙編程序在註釋中都附有相應的Delphi代碼。

1

https://groups.google.com/forum/#!topic/borland.public.delphi.objectpascal/-xb6O0qX2zc

procedure test(numArgs:integer; MyFormattingString:string);  
var 
    v:array of tvarrec; 
    i:integer; 
begin 
    setlength(v, numArgs); 
    for i:=1 to numArgs do 
    begin 
    v[i-1].vtype:=vtpchar; 
    v[i-1].vtpchar:=strnew(pchar(myDataSet.FieldByName(inttostr(i)).asstring)); 
    end; 
    memo1.lines.add(Format(MyFormattingString,v); 
    for i:=1 to numArgs do strdispose(v[i-1].vtpchar); 
end; 

發現這個代碼不回答我的一切都應付,但我想我知道如何構建TVarRec的陣列了。

+0

多數民衆贊成在同樣的答案,但我的顯示如何..無論如何高興你找到了答案 –

+1

@GlenMorse不,它與你的答案無關。這是相反的。 – Atys