Sprintf in Delphi?
-
20-09-2019 - |
Frage
Kennt jemand einen 100% igen Klon des C/C ++? printf Für Delphi? Ja, ich kenne das System.Format Funktion, aber es behandelt die Dinge ein wenig anders.
Wenn Sie beispielsweise 3 auf "003" formatieren möchten, brauchen Sie in C "%03d", aber "%.3d" in Delphi.
Ich habe eine Anwendung in Delphi geschrieben, die in der Lage sein muss, Zahlen mit C -Format -Zeichenfolgen zu formatieren. Kennen Sie dafür ein Ausschnitt/eine Bibliothek?
Danke im Voraus!
Lösung
Sie können die WSPRINTF () -Funktion von Windows.pas verwenden. Leider wird diese Funktion in den Windows.pas nicht korrekt deklariert. Hier finden Sie eine erneute Redaktion:
function wsprintf(Output: PChar; Format: PChar): Integer; cdecl; varargs;
external user32 name {$IFDEF UNICODE}'wsprintfW'{$ELSE}'wsprintfA'{$ENDIF};
procedure TForm1.FormCreate(Sender: TObject);
var
S: String;
begin
SetLength(S, 1024); // wsprintf can work only with max. 1024 characters
SetLength(S, wsprintf(PChar(S), '%s %03d', 'Hallo', 3));
end;
Andere Tipps
Wenn Sie die Funktion für den Benutzer delphi freundlicher aussehen möchten, können Sie Folgendes verwenden:
function _FormatC(const Format: string): string; cdecl;
const
StackSlotSize = SizeOf(Pointer);
var
Args: va_list;
Buffer: array[0..1024] of Char;
begin
// va_start(Args, Format)
Args := va_list(PAnsiChar(@Format) + ((SizeOf(Format) + StackSlotSize - 1) and not (StackSlotSize - 1)));
SetString(Result, Buffer, wvsprintf(Buffer, PChar(Format), Args));
end;
const // allows us to use "varargs" in Delphi
FormatC: function(const Format: string): string; cdecl varargs = _FormatC;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(FormatC('%s %03d', 'Hallo', 3));
end;
Es wird nicht empfohlen, Printf (WS) zu verwenden, da sie anfällig für Pufferüberlauf sind. Es wäre besser, die sicheren Varianten zu verwenden (z. B. StringCChPrintf). Es wird bereits im Jedi -Apilib (JWastrsafe) deklariert.
Nun, ich habe gerade das gefunden:
function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer;
cdecl; varargs; external 'msvcrt.dll';
Es verwendet einfach die ursprüngliche Sprintf -Funktion von msvcrt.dll
was dann so verwendet werden kann:
procedure TForm1.Button1Click(Sender: TObject);
var s: AnsiString;
begin
SetLength(s, 99);
sprintf(PAnsiChar(s), '%d - %d', 1, 2);
ShowMessage(S);
end;
Ich weiß nicht, ob dies die beste Lösung ist, da sie diese externe DLL benötigt und Sie die Länge der Saite manuell einstellen müssen, was es anfällig für Pufferüberläufe macht, aber zumindest funktioniert es ... irgendwelche besseren Ideen?
Weiterer sauberer Ansatz ohne unnötiges Typ Casting
function sprintf(CharBuf: PChar; const Format: PAnsiChar): Integer;
cdecl; varargs; external 'msvcrt.dll';
procedure TForm1.Button1Click(Sender: TObject);
var CharBuf: PChar;
begin
CharBuf:=StrAlloc (99);
sprintf(CharBuf, 'two numbers %d - %d', 1, 2);
ShowMessage(CharBuf);
StrDispose(CharBuf);
end;
Wenn Sie zufällig für die Windows CE -App kompilieren. Verwenden Sie coredll.dll anstelle von msvcrt.dll