6

有谁知道 Delphi 的 C/C++ printf的 100% 克隆?是的,我知道系统。格式化函数,但它处理的事情有点不同。

例如,如果要将 3 格式化为“003”,则在 C 中需要“%03d”,而在 Delphi 中需要“%.3d”。

我有一个用 Delphi 编写的应用程序,它必须能够使用 C 格式字符串格式化数字,所以你知道一个片段/库吗?

提前致谢!

4

5 回答 5

16

您可以使用 Windows.pas 中的 wsprintf() 函数。不幸的是,这个函数在 Windows.pas 中没有正确声明,所以这里重新声明:

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;
于 2010-03-18T17:42:36.880 回答
9

如果你想让函数看起来对用户更友好,你可以使用以下内容:

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;
于 2010-03-18T17:57:26.990 回答
3

不建议使用 (ws)printf ,因为它们容易出现缓冲区溢出,最好使用安全的变体(例如StringCchPrintF)。它已经在 J​​edi Apilib (JwaStrSafe) 中声明。

于 2010-03-19T07:24:16.703 回答
2

好吧,我刚刚找到了这个:

function sprintf(S: PAnsiChar; const Format: PAnsiChar): Integer;
    cdecl; varargs; external 'msvcrt.dll';

它只是使用原始的 sprintf 函数msvcrt.dll,然后可以这样使用:

procedure TForm1.Button1Click(Sender: TObject);
var s: AnsiString;
begin
  SetLength(s, 99);
  sprintf(PAnsiChar(s), '%d - %d', 1, 2);
  ShowMessage(S);
end;

我不知道这是否是最好的解决方案,因为它需要这个外部 dll 并且您必须手动设置字符串的长度,这使得它容易发生缓冲区溢出,但至少它可以工作......有更好的想法吗?

于 2010-03-18T17:46:32.993 回答
0

更干净的方法,没有不必要的类型转换

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;

如果您碰巧为 Windows CE App 进行交叉编译。使用 coredll.dll 而不是 msvcrt.dll

于 2013-10-07T07:09:32.153 回答