如何创建具有任意数量参数的函数?

时间:2011-11-26 20:36:36

标签: delphi function parameters delphi-7

我想创建一个接收多个字符串作为参数的函数。 就像C的函数printf("Hello %s",name);一样,但是我不想传递一个就绪数组,它就不可读了。

Edit1.text:=lang('Hello');

Edit2.text:=lang('Welcome to {1} guest',place);

Edit3.text:=lang('Hi {1}, is your {2} time in {3}','Victor','first','Disney');
输出应该是:

Hello
Welcome to Disney guest
Hi Victor is your first time in Disney

我如何创建function TForm1.lang(parameters:String):String;,我做了一项研究,但我无法让它发挥作用。

我还需要访问参数[]和parameters.length。

我需要将我的应用程序转换为multilang。

6 个答案:

答案 0 :(得分:4)

以下是如何执行此操作的示例函数:

function TForm1.lang(s: String; params: array of String): String;
var
  i: Integer;
begin
  for i := 0 to High(params) do
  begin
    ShowMessage(params[i]);
  end;
end;

这样称呼:

lang('My format string', ['this', 'that']);

或者像这样:

var
  b: String;
begin
  b := 'this';
  lang('My format string', [b, 'that']);
end;

答案 1 :(得分:3)

不确定你的意思是不可读

DoSomething(['Param1','Param2']);

代表

procedure DoSomething(args : Array of String);
Var
  Index : Integer;
Begin
  for index := Low(args) to High(args) Do
    ShowMessage(args[Index]);
End;

似乎对我好。当然如果你想从delphi外面调用它,那你就有问题了。

快速修复只是传入一个分隔的字符串,然后用户TStringList将其拆分。

你可以编写一个wee函数来做到这一点,不要忘记在完成后释放它。

答案 2 :(得分:1)

您可以使用SysUtils.Format修复所有三个示例:

Edit1.text := format('%s',['Hello']));
Edit1.text := format('Welcome to %s guest',[place]));
Edit1.text := format('Hi %s, is your %s time in %s',['Victor','first','Disney']));

我个人觉得它很可读。如果您可以从基本的sysutils函数中获得所需的内容,那么您应该认真考虑这样做,而不是编写自己的版本。另一方面,您可能需要更复杂的功能,而这些功能并未在您的问题中显示。如果是这种情况,我认为paulsm4建议使用字符串列表似乎是一个很好的方法。

答案 3 :(得分:1)

Delphi不支持使用vararg创建函数 - 样式参数与printf()完全相同。它仅支持从外部库中消耗此类函数。最接近Delphi的支持使用可变参数列表创建函数的方法是使用“开放数组”参数,就像SysUtils.Format()使用的那样。

答案 4 :(得分:0)

正如Tony上面提到的,我还建议使用一个删除字符串。除了,不仅仅是消除,而是使用更多的解析技术。如果我理解正确,你正在进行格式化的这个函数不应该在参数中包含一个数组,但从技术上讲,这并不意味着我们不能在任何地方使用数组(数组非常适合用于这个场景快速表现)。

此方法几乎可以在参数中传递任何内容,包括分隔符,而不会影响输出。想法是做A)参数字符串的大小,B)大小和参数之间的分隔符,以及C)参数字符串......并重复......

const
  MY_DELIM = '|';  //Define a deliminator

type
  TStringArray = array of String;

/////////////////////////////////

//Convert an array of string to a single parsable string
//  (Will be the first step before calling your format function)
function MakeParams(const Params: array of String): String;
var
  X: Integer;
  S: String;
begin
  Result:= '';
  for X:= 0 to Length(Params)-1 do begin
    S:= Params[X];
    Result:= Result + IntToStr(Length(S)) + MY_DELIM + S;
  end;
end;

//Convert a single parsable string to an array of string
//  (Will be called inside your format function to decode)
//  This is more or less called parsing
function ExtractParams(const Params: String): TStringArray;
var
  S: String;  //Used for temporary parsing
  T: String;  //Used for copying temporary data from string
  P: Integer; //Used for finding positions
  C: Integer; //Used for keeping track of param count
  Z: Integer; //Used for keeping track of parameter sizes
begin
  S:= Params;                   //Because we'll be using 'Delete' command
  C:= 0;                        //Set count to 0 to start
  SetLength(Result, 0);         //Prepare result array to 0 parameters
  while Length(S) > 0 do begin  //Do loop until nothing's left
    P:= Pos(MY_DELIM, S);       //Get position of next deliminator
    if P > 1 then begin         //If deliminator was found...       
      C:= C + 1;                  //We have a new parameter
      SetLength(Result, C);       //Set array length to new parameter count
      T:= Copy(S, 1, P-1);        //Get all text up to where deliminator was found
      Delete(S, 1, P);            //Delete what we just copied, including deliminator
      Z:= StrToIntDef(T, 0);      //Convert T:String to Z: Integer for size of parameter
      T:= Copy(S, 1, Z);          //Get all text up to 'Z' (size of parameter)
      Delete(S, 1, Z);            //Delete what we just copied
      Result[C-1]:= T;              //Assign the new parameter to end of array result
    end else begin              //If deliminator was NOT found...
      S:= '';                     //Clear S to exit loop (possible bad format if this happens)
    end;
  end;
end;

//Main formatting routine
function MyFormat(const Input: String; const Params: String): String;
var
  A: TStringArray;
  X: Integer;
  S: String;
  P: Integer;
  R: String;
begin
  R:= Input;
  A:= ExtractParams(Params);
  //At this point, A contains all the parameters parsed from 'Params'
  for X:= 0 to Length(A)-1 do begin
    S:= A[X];
    P:= Pos('%s', R);
    if P > 0 then begin
      Delete(R, P, 2);
      Insert(S, R, P);
    end;
  end;
  Result:= R;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Pars: String;
begin
  Pars:= MakeParams(['this', 'that', 'something else']);
  Edit1.Text:= MyFormat('%s is %s but not %s', Pars);
end;

答案 5 :(得分:-1)

您可能知道,SysUtils.Format()通过使用集合来实现“varargs”。

但是,在您的情况下,为什么不直接传递TStringList?该功能只需检查“list.Count”。瞧 - 你已经完成了!