Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Unicode Ersatz für Format (https://www.delphipraxis.net/90206-unicode-ersatz-fuer-format.html)

Luckie 13. Apr 2007 12:21


Unicode Ersatz für Format
 
Ich benutze folgende Funktion als Ersatz für die Funktion Format:
Delphi-Quellcode:
function FormatW(fmt: WideString; params: array of const): WideString;
var
  pdw1, pdw2        : PDWORD;
  i                : integer;
  pc               : PWIDECHAR;
begin
  pdw1 := nil;
  if length(params) > 0 then
    GetMem(pdw1, length(params) * sizeof(Pointer));
  pdw2 := pdw1;
  for i := 0 to high(params) do
  begin
    pdw2^ := DWORD(PDWORD(@params[i])^);
    inc(pdw2);
  end;
  GetMem(pc, length(params) * sizeof(Pointer));
  try
    ZeroMemory(pc, length(params) * sizeof(Pointer));
    SetString(Result, pc, wvsprintfW(pc, PWIDECHAR(fmt), PCHAR(pdw1)));
  except
    Result := '';
  end;
  if (pdw1 <> nil) then
    FreeMem(pdw1);
  if (pc <> nil) then
    FreeMem(pc);
end;
Allerdings bekomme ich da hin und wieder eine "invalid pointer operation" in der Zeile FreeMem(pdw1);. Ich kann das jetzt auch nicht genau sagen unter welchen Bedingungen sie auftritt.

Sieht da jemand einen Fehler in der Funktion oder kann mit einer alternativen Funktion aufwarten?

Bernhard Geyer 13. Apr 2007 12:31

Re: Unicode Ersatz für Format
 
Eigentlich gibt es WideFormat bei Delphi aber diese kommt bei großen (Format-) Strings durcheinandern.
Ich verwende als Ersatz TNTSysUtils.Tnt_WideFormat

himitsu 13. Apr 2007 12:33

Re: Unicode Ersatz für Format
 
Delphi-Quellcode:
GetMem(pc, length(params) * sizeof(Pointer));
try
  ZeroMemory(pc, length(params) * sizeof(Pointer));
  SetString(Result, pc, wvsprintfW(pc, PWIDECHAR(fmt), PCHAR(pdw1)));
pc soll wohl der Speicher für den (Rückgabe)String sein?

ich denk mal, da stimmt dann was mit der länge nicht :stupid:
1 parameter = 4 Byte ... ich glaub da darf man ruhig sagen "ein Glück daß es nicht öfters kracht"


hab grad das erfolgreich im Einsatz:
Delphi-Quellcode:
Function Format(Msg: LongWord; Const Args: Array of Const): WideString;
  Var StrBuffer, StrBuffer2: Array[0..1023] of WideChar;
    A: Array[0..15] of LongWord;
    i: Integer;

  Begin
    LoadStringW(HInstance, Msg, @StrBuffer, Length(StrBuffer));
    For i := High(Args) downto 0 do A[i] := Args[i].VInteger;
    wvsprintfW(@StrBuffer2, @StrBuffer, @A);
    Result := PWideChar(@StrBuffer2);
  End;

//ich hoff grad so müßte es dann mit 'nem String aussehn
Function Format(Const S: WideString Const Args: Array of Const): WideString;
  Var StrBuffer2: Array[0..1023] of WideChar;
    A: Array[0..15] of LongWord;
    i: Integer;

  Begin
    For i := High(Args) downto 0 do A[i] := Args[i].VInteger;
    wvsprintfW(@StrBuffer2, PWideChar(S), @A);
    Result := PWideChar(@StrBuffer2);
  End;
ok, die Arraylängen kannst dir ja noch dynamisch umbauen, aber ansonsten reicht es doch?
(und Delphi's Format hat doch auch nur einen statischen Speicher drin)

Zitat:

Zitat von Bernhard Geyer
Eigentlich gibt es WideFormat bei Delphi aber diese kommt bei großen (Format-) Strings durcheinandern.

die Länge ist halt aufgrund des statischen Speichers begrenzt :angel2:

Luckie 13. Apr 2007 12:38

Re: Unicode Ersatz für Format
 
Oh, die kannte ich noch gar nicht. Danke für den Hinweis. Hier in diesem Projekt kann ich das benutzen, allerdings bräuchte ich das auch manchmal in nonVCL Anwendungen, deswegen, wäre es schon gut, wenn ich die obige Funktion stabil zum Laufenbringen könnte.

Da war wieder jemand schneller. Dank dir. Und mehr als 1024 Parameter wird man wohl kaum formatieren wollen. ;)

Robert Marquardt 13. Apr 2007 13:26

Re: Unicode Ersatz für Format
 
GetMem(pc, length(params) * sizeof(Pointer));

pc ist doch der Puffer in den der ganze String per wvsprintfW zusammengebaut wird. Selbiger sollte 1024 Zeichen (also hier WideChar) gross sein. wvsprintf ist dokumentiert mit dieser Puffergroesse. Du alloziierst 2 Zeichen pro Parameter (sizeof(Pointer) = 4 = 2 WideChar). Das ist einfach Unsinn.

Luckie 13. Apr 2007 13:28

Re: Unicode Ersatz für Format
 
Wie müsste es denn lauten? BTW ist die statische Alternative auch in Ordnung.

Robert Marquardt 13. Apr 2007 13:36

Re: Unicode Ersatz für Format
 
Die lokale Puffer-Version von Himitsu ist auch in Ordnung. alles was du brauchst ist schliesslich Puffer geeigneter Groesse.
Ansonsten GetMem(pc, 1024*SizeOf(WideChar));

Luckie 13. Apr 2007 13:39

Re: Unicode Ersatz für Format
 
Ah, gut. Das wollte ich nur wissen.

himitsu 13. Apr 2007 13:44

Re: Unicode Ersatz für Format
 
Was auch ginge, wäre einen String mit genügend Länge zu reservieren und dann direkt da reinzuschreiben ... sowas gefällt mir auch immer (ersparrt einem ebenfall dieses ganze Try-Finally-Zeugs, da sich Delphi drum kümmert)
Code:
Function Format(Const S: WideString Const Args: Array of Const): WideString;
  Var A: Array[0..15] of LongWord;
    i: Integer;

  Begin
    For i := High(Args) downto 0 do A[i] := Args[i].VInteger;
    [color=#ff0000]SetLength(Result, 1024);
    SetLength(Result, wvsprintfW(PWideChar(Result), PWideChar(S), @A));[/color]
  End;
SetLength würde da sozusagen dem GetMem entsprechen, wobei sich ja Delphi um die Freigabe des String kümmert ... auch bei 'ner Exception.

xZise 29. Okt 2007 14:58

Re: Unicode Ersatz für Format
 
Gibt es denn inzwischen eine erfolgreiche Umsetzung ins WideString?
Das scheint ja nur Integer abzubekommen:
Zitat:

Zitat von himitsu
Delphi-Quellcode:
Function Format(Msg: LongWord; Const Args: Array of Const): WideString;
  Var StrBuffer, StrBuffer2: Array[0..1023] of WideChar;
    A: Array[0..15] of LongWord;
    i: Integer;

  Begin
    LoadStringW(HInstance, Msg, @StrBuffer, Length(StrBuffer));
    For i := High(Args) downto 0 do A[i] := Args[i].VInteger;
    wvsprintfW(@StrBuffer2, @StrBuffer, @A);
    Result := PWideChar(@StrBuffer2);
  End;

//ich hoff grad so müßte es dann mit 'nem String aussehn
Function Format(Const S: WideString Const Args: Array of Const): WideString;
  Var StrBuffer2: Array[0..1023] of WideChar;
    A: Array[0..15] of LongWord;
    i: Integer;

  Begin
    For i := High(Args) downto 0 do A[i] := Args[i].VInteger;
    wvsprintfW(@StrBuffer2, PWideChar(S), @A);
    Result := PWideChar(@StrBuffer2);
  End;



Alle Zeitangaben in WEZ +1. Es ist jetzt 23:21 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz