2015-10-16 2 views
2

Как использовать varargs для печати нескольких строк? Я пробовал это, но я не могу определить размер массива. Он просто печатает мусор.Как использовать varargs для печати строк?

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 поддерживает массивы и имеет функции, которые позволяют вам получать индексы индекса «Длина», «Низкий» и «Высокий» в массиве. Вы можете просто передать массив своей функции и пропустить ее, не пытаясь перепрыгнуть через все эти обручи. Объявление вашей функции затем становится 'procedure Print (Значения: массив строки);'. –

+0

Это не * быстрее *. Откуда у вас эта смешная идея? * Я предпочитаю указатели * ерунда. Для того, что вы пытаетесь сделать здесь, нет улучшения скорости, и это лишний уровень сложности. (Я оставляю этот комментарий, даже если вы удалили свой комментарий, на который он ответил, сразу после того, как я разместил этот ответ. В интересах других он сказал * Потому что он быстрее. Я предпочитаю понтеры *.) –

ответ

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 -style используются не очень часто. Вы должны рассмотреть возможность использования параметра открытого массива вместо:

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. Факт в том, что Delphi не делает (без трюков) позволяет писать функции varargs. Вместо этого используйте массив const. –

Смежные вопросы