2010-03-18 28 views
5

Có ai biết 100% bản sao C/C++ printf cho Delphi không? Có, tôi biết Hệ thống. Format chức năng, nhưng nó xử lý mọi thứ một chút khác nhau.sprintf ở Delphi?

Ví dụ: nếu bạn muốn định dạng 3 thành "003", bạn cần "% 03d" trong C, nhưng "% .3d" trong Delphi.

Tôi có một ứng dụng được viết bằng Delphi có thể định dạng số bằng chuỗi định dạng C, vì vậy bạn có biết một đoạn mã/thư viện cho điều đó không?

Cảm ơn trước!

+0

Bạn không thể định dạng từ 3,14 đến "003" bằng "% 03d". – n0rd

+0

Xin lỗi, nên là một số nguyên, cố định;) Câu hỏi vẫn còn hiệu lực :) – kroimon

Trả lời

13

Bạn có thể sử dụng hàm wsprintf() từ Windows.pas. Đáng tiếc là chức năng này không được công bố một cách chính xác trong Windows.pas vì vậy đây là một khai báo lại:

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; 
+3

Wow ok, tôi hơi trễ trả lời câu hỏi của chính mình;) Cảm ơn bạn, tôi nghĩ đây là giải pháp tốt hơn nhiều so với nhập từ msvcrt .dll! Sẽ thử xem cái gì sau ... – kroimon

+0

Sau khi nhận ra rằng phương thức 'user32.wsprintf (W | A)' không thể xử lý các dấu phẩy động, bây giờ tôi quyết định sử dụng 'msvcrt._vsnw? Printf' bây giờ bằng cách sử dụng vararg-fix của bạn phía dưới. Cách tốt nhất sẽ là một phiên bản không có phụ thuộc bên ngoài, nhưng 'msvcrt.dll' sẽ có sẵn ở mọi nơi tôi cần. – kroimon

1

Vâng, tôi chỉ thấy điều này một:

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

Nó chỉ đơn giản sử dụng hàm sprintf gốc từ msvcrt.dll mà sau đó có thể được sử dụng như thế:

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

Tôi không biết đây có phải là giải pháp tốt nhất vì nó cần dll bên ngoài này và bạn phải đặt chuỗi chiều dài bằng tay mà làm cho nó dễ bị tràn bộ đệm, nhưng ít nhất nó hoạt động ... Bất kỳ ý tưởng tốt hơn?

9

Nếu bạn muốn cho các chức năng trông Delphi thân thiện với người dùng, bạn có thể sử dụng như sau:

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; 
+0

+1 cho phiên bản phức tạp này, cảm ơn bạn! – kroimon

+0

Tôi chưa bao giờ nghe nói về điều này !!! Làm thế nào bạn phát hiện ra nó, Andreas ??????? –

+0

Bằng cách đọc định nghĩa của C/C++ - macro va_start, va_list, va_end. –

3

Nó không được khuyến khích sử dụng (ws) printf vì họ dễ bị tràn bộ nhớ đệm, nó sẽ tốt hơn nếu sử dụng các biến thể an toàn (ví dụ: StringCchPrintF). Nó đã được tuyên bố trong Jedi Apilib (JwaStrSafe).

+0

Vì tôi không muốn bao gồm Jedi chỉ cho một chức năng này, tôi quyết định sử dụng '_vsnw? Printf' từ' msvcrt.dll' nên an toàn, vì tham số thứ hai là kích thước bộ đệm ... – kroimon

0

phương pháp sạch hơn mà không loại không cần thiết đúc

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; 

Nếu bạn tình cờ đi qua biên dịch cho Windows CE App. sử dụng coredll.dll thay vì msvcrt.dll