Guest
|
Posted: Mon Jan 29, 2007 7:17 am Post subject: Delphi and sprintf |
|
|
I've been looking around trying to find a function that works
something like sprintf, so that escape sequences like \n, \t, \r, \0
are converted over. To date I haven't found one, and became pretty
bored of searching around.
Since I wasn't able to find one, I went ahead and typed one up. I'm
submitting it here for anyone else who might have been looking for
one; but most importantly so it can be reviewed by others and perhaps
improved upon. It's pretty basic, but it covers my needs of simple
formatting for routines that are not called all that often. I provide
no warranty or guarantee as to the quality of the code or successful
usage of it. I've tested it, it looks to work.. and I don't see any
problems with it, though.
(*
* 01/28/2007 sprintf() routine, Michael Martinek
* Simulates basic sprintf() actions to convert escape sequences
* in combination with using Format() to convert an argument array.
*
*)
function sprintf(AStyle: String; const AArgs: array of const): String;
var
pPos, pFinalByte: PChar;
pResultPos: PChar;
bDefinedEscape: Boolean;
begin
//first perform the format conversion
AStyle := Format(AStyle, AArgs);
//at this point, since we're converting 2 characters to 1, our
result will be no larger than
//what we have now. \\ = \, \0 = #0, \n = #10, etc.
SetLength(Result, Length(AStyle));
pResultPos := PChar(Result);
pPos := PChar(AStyle);
//get the final byte and stay under it.. if it's \, it doesn't
matter because it contains no escape
//definition
pFinalByte := PChar(Integer(pPos) + Length(AStyle));
while (Integer(pPos) < Integer(pFinalByte)) do
begin
//is there a possible escape delimiter?
if (pPos^ = '\') then
begin
//what is the next character? Something we have defined?
//PByteArray(pPos)[0] = pPos
bDefinedEscape := true;
case (Char(PByteArray(pPos)[1])) of
'0': pResultPos^ := #0;
'r': pResultPos^ := #13;
'n': pResultPos^ := #10;
't': pResultPos^ := #9;
else //not a defined delimiter, skip.
begin
pResultPos^ := Char(PByteArray(pPos)[1]);
bDefinedEscape := false;
end;
end;
//was the escape defined? if so, we need to skip the next
character
if (bDefinedEscape) then
Inc(pPos);
end
else
pResultPos^ := pPos^;
Inc(pPos);
Inc(pResultPos);
end;
//size result in case we did some conversions.. length = pResultPos
- start
SetLength(Result, Integer(pResultPos) - Integer(@Result));
end;
Usage Example:
Memo1.Lines.Add(sprintf('This is %s #%d, [Tab:\t]\\\t\r\nWhee.',
['test', 1]));
Needs SysUtils for the Format() to work, and also PByteArray() is
defined in it. Although, PByteArray could easily be duplicated in
another unit.
-- Michael |
|