Here's an example function of how you can do this.
Here's an example function of how you can do this: function TForm1. Lang(s: String; params: array of String): String; var i: Integer; begin for I := 0 to gh(params) do begin ShowMessage(paramsi); end; end; Call it like this: lang('My format string', 'this', 'that'); or like this: var b: String; begin be := 'this'; lang('My format string', b, 'that'); end.
That seems ok to me. But I can make the second parameter optional? – Vitimtk Nov 26 at 21:23 Q: Do you mean "can I eliminate passing the array"?
A: No. Because of the "Pascal calling convention" mentioned above. – paulsm4 Nov 26 at 21:28 1 Vitimtk, you can pass as many array elements as you want.
Use to pass in an empty array. With an empty array, – Marcus Adams Nov 26 at 21:28 PS: Delphi Lists are easy; Delphi variable arrays are easy. Both are readable.
If in doubt, compare them with C++ STL containers ;) – paulsm4 Nov 26 at 21:31 I think I will need just the array parameter like @TonyHopkinson answer. Thank you! – Vitimtk Nov 26 at 21:38.
Not sure what you mean by not readable DoSomething('Param1','Param2'); for procedure DoSomething(args : Array of String); Var Index : Integer; Begin for index := Low(args) to gh(args) Do ShowMessage(argsIndex); End; Seems okay to me. Course if you want to call it from outside delphi then you have an issue. Quick fix is just to pass in a delimited string and then user TStringList to split it.
You could write a wee function to do that, don't forget to free it when you are done.
All your three examples could be fixed by using SysUtils. Format: Edit1. Text := format('%s','text := format('Welcome to %s guest',place)); Edit1.
Text := format(' is your %s time in %s','Victor','first','Disney')); Personally I think it's quite readable. If you can have what you need from a basic sysutils function, you should seriously consider doing that, rather than to write your own version. On the other hand, you may need more complex functionality that doesn't show in your question.
If that's the case, I think paulsm4's suggestion of using a stringlist seems like a good way to go.
I didn't know this function, but I want to write my own because, I don't just replace the text to respective %s, but also select the corret language, lang('Welcome {1}','Svein') can return Ben-venido Svein if your system is in spanish. Don't know if you got it... – Vitimtk Nov 26 at 23:39.
Delphi does not support CREATING functions withvararg-style parameters that work exactly like printf() does. It only supports CONSUMING such functions from external libraries. The closest Delphi comes to supporting the creation of functions with variable parameter lists is to use "open array" parameters, like what SysUtils.Format() uses.
Variant open array, in the fact, as in the name of online manual topic – user539484 Nov 27 at 21:43.
As Tony mentions above, I also recommend using a deliminated string. Except, a little more than just deliminating, but using more of a parsing technique. If I understand right, this function you're making for formatting shall NOT include an array in the parameters, but technically, that doesn't mean we can't use arrays anywhere at all (arrays are very ideal to use for this scenario for fast performance).
This method will allow virtually anything to be passed in the parameters, including the deliminator, without affecting the output. The idea is to do A) Size of parameter string, B) Deliminator between size and parameter, and C) parameter string... And repeat... 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:= ParamsX; 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 ResultC-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:= AX; 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.
I used this approach when designing a custom server/client packet system. I started with the raw TServerSocket and TClientSocket and built around them - using the technique above, it becomes 20 times easier to send/receive commands through these sockets. Method can also be re-used for many other things, for example, if you want to save an array of strings to a text file.
– Jerry Dodge Nov 27 at 17:20 Wasn't expecting downvotes – Jerry Dodge Nov 27 at 22:11 Not sure why you got them either. Looks like a creditable start to me. – Tony Hopkinson Nov 27 at 23:26.
As you probably know, SysUtils.Format() implements "varargs" by using a set. In your case, however, why not just pass a TStringList? The function will simply check "list.
Count". Voila - you're done!
PS: The reason C varargs work they way they do is because, in the "C calling convention", the CALLER cleans up the stack. The CALLER knows to pop 5 variables here, and 10 variables there. Delphi uses the "Pascal calling convention", where the CALLEE cleans up the stack.
This is slightly more efficient, but it means that subroutines must accept a fixed #/arguments. So you're left with passing some kind of "list" (an array, a list, a set - whatever). But "one thing" as "one argument".'Hope that helps ... – paulsm4 Nov 26 at 20:47 because I would need to declare a variable instance TStringList, and then pass as parameter... It is by far not easy to do, and not even readable.
And i'm just a newbie on delphi. – Vitimtk Nov 26 at 20:52 I have no clue about how implement "varargs" – Vitimtk Nov 26 at 22:01 4 "SysUtils.Format() implements "varargs" by using a set" is factually incorrect – David Heffernan Nov 26 at 22:41 @paulsm4: By the sounds of it, this function will get some heavy activity, which if that's true, a TStringList will be way too heavy for this. – Jerry Dodge Nov 27 at 16:15.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.