2015-10-16 56 views
2

如何使用可變參數打印出多個字符串?我試過這個,但我不能確定數組的大小。它只是打印垃圾。如何使用可變參數打印字符串?

program Project1; 

{$APPTYPE CONSOLE} 
{$POINTERMATH ON} 

function _Print(const S: String): string; cdecl; 
var 
    Args: Array[0..100] of Pointer absolute S; 
    I: Integer; 
begin 
    I := 0; 
    while Args[I] <> nil do 
    begin 
    WriteLn(PString(@Args[I])^); 
    Inc(I); 
    end; 
end; 

const Print: function(const S: String): string; cdecl varargs = _Print; 

var 
    A, B: String; 
begin 
    A := 'ABC'; 
    B := 'CDE'; 
    Print(a, b, 'asdasd', 'fasd', ' ') 
end. 
+0

爲什麼你需要做的這一切? Delphi支持數組,並且具有允許您在數組中獲得'Length','Low'索引和'High'索引值的函數。你可以簡單地將數組傳遞給你的函數並遍歷它,而不用試圖跳過所有這些箍。你的函數聲明就變成了'procedure Print(Values:string of array);'。 –

+0

這不是*更快*。你從哪裏得到這個荒謬的想法? *我更喜歡指針*是無稽之談。對於你在這裏試圖做的事情,沒有速度的提高,這是一個不必要的複雜程度。 (即使您刪除了您在我發佈此回覆後立即回覆的評論,但我仍然留下該評論。爲了其他人的利益,它說*因爲它更快,我更喜歡ponters *)。 –

回答

3

一個varargs功能沒有自動化的方式來確定被傳遞的參數數目,因爲只有在調用方知道多少個參數,它被調用堆棧上的投入。該函數必須手動確定的參數,或者通過:

  1. 要求調用者傳遞的參數的實際數量爲固定參數:

    function _Print(NumStrings: Integer; const Strings: string): string; cdecl; 
    var 
        Args: Array[0..100] of Pointer absolute Strings; 
        I: Integer; 
    begin 
        for I := 0 to NumStrings-1 do 
        begin 
        WriteLn(PString(@Strings[I])^); 
        end; 
    end; 
    
    const 
        Print: function(NumStrings: Integer; const Strings: string): string; cdecl varargs = _Print; 
    
    var 
        A, B: String; 
    begin 
        A := 'ABC'; 
        B := 'CDE'; 
        Print(5, a, b, 'asdasd', 'fasd', ' '); 
    end. 
    
  2. 把一個崗哨值在的端部該函數可以查找的參數列表。你的功能已經被編碼爲這個(它正在尋找nil指針),所以只傳遞一個:

    Print(a, b, 'asdasd', 'fasd', ' ', nil); 
    

話雖這麼說,這兩種方法是受調用者的錯誤,因此潛在的危險,如果濫用,這就是爲什麼varargs型功能不經常使用。你應該考慮使用開放數組參數,而不是:

program Project1; 

{$APPTYPE CONSOLE} 
{$POINTERMATH ON} 

function _Print(const Args: array of string): string; 
var 
    I: Integer; 
begin 
    for I := Low(Args) to High(Args) do 
    begin 
    WriteLn(Args[I]); 
    end; 
end; 

const 
    Print: function(const Args: array of string): string = _Print; 

var 
    A, B: String; 
begin 
    A := 'ABC'; 
    B := 'CDE'; 
    Print([a, b, 'asdasd', 'fasd', ' ']); 
end. 
+0

這不是真的。它用於RTL。 'UStrCatN' – user15124

+1

@ user15124:我沒有說他們根本沒用過。我說他們不常使用。即使在RTL中也沒有。另外,如果你仔細看看'UStrCatN'的實現,你會看到它有一個'ArgCnt'固定參數。編譯器填充該值,因爲它知道它連接在一起的多少個字符串。 –

+0

@ user15124:在RTL中,特別是在System.pas中,有一些函數在它們後面有相當多的編譯器魔術。 IIRC,有些甚至比EAX,EDX,ECX有不同的參數,所以系統單元很難被看作是純Delphi的主要例子。事實是,德爾福不(沒有技巧)允許你寫可變參數函數。改爲使用const數組。 –