![]() |
Unicode Ersatz für Format
Ich benutze folgende Funktion als Ersatz für die Funktion Format:
Delphi-Quellcode:
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.
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; Sieht da jemand einen Fehler in der Funktion oder kann mit einer alternativen Funktion aufwarten? |
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 |
Re: Unicode Ersatz für Format
Delphi-Quellcode:
pc soll wohl der Speicher für den (Rückgabe)String sein?
GetMem(pc, length(params) * sizeof(Pointer));
try ZeroMemory(pc, length(params) * sizeof(Pointer)); SetString(Result, pc, wvsprintfW(pc, PWIDECHAR(fmt), PCHAR(pdw1))); 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:
ok, die Arraylängen kannst dir ja noch dynamisch umbauen, aber ansonsten reicht es doch?
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; (und Delphi's Format hat doch auch nur einen statischen Speicher drin) Zitat:
|
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. ;) |
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. |
Re: Unicode Ersatz für Format
Wie müsste es denn lauten? BTW ist die statische Alternative auch in Ordnung.
|
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)); |
Re: Unicode Ersatz für Format
Ah, gut. Das wollte ich nur wissen.
|
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:
SetLength würde da sozusagen dem GetMem entsprechen, wobei sich ja Delphi um die Freigabe des String kümmert ... auch bei 'ner Exception.
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; |
Re: Unicode Ersatz für Format
Gibt es denn inzwischen eine erfolgreiche Umsetzung ins WideString?
Das scheint ja nur Integer abzubekommen: Zitat:
|
Re: Unicode Ersatz für Format
dieses VInteger ist nur etwas irreführend :roll:
da ist einfach nur entweder der Dateninhalt oder ein Zeiger auf den Dateninhalt (z.B. bei String) des entsprechenden Parameters drin. PS: schau mal nach "Variante offene Array-Parameter" oder einfach mal wie TVarRec definiert ist :zwinker: was tatsächlich möglich ist, das bestimmt nur ![]() |
Re: Unicode Ersatz für Format
Also ich bekomme eine Menge Japanischer (oder irgendwas anderes Ostasiatisches) Zeichen.
|
Re: Unicode Ersatz für Format
Kryptische Zeichen?
dann läuft was falsch ... wie sieht denn deine Funktion und der Aufruf aus? diese Funktionen sind Unicode, also falls bei dir was mit ANSI ist, dann liegt es wohl daran. wegen dem Int64: diese Funktion kennt nichts über 32 Byte (bis auf Strings, wo die Zeiger aber auch 32-Bit sind) konnte jedenfalls keine möglichen Paramerte für solche Datentypen entdecken. hab hier aber mal den Parameter %q für einen 64-Bit-Integer eingeführt:
Delphi-Quellcode:
hier also nochmal die wichtigsten Parameter
Function Format(S: WideString; Const Args: Array of Const): WideString;
Var StrBuffer2: Array[0..1023] of WideChar; A: Array[0..15] of Integer; i, i2: Integer; i8: Int64; Begin // aufpassen!!! es wird eine unicodefähige StringReplace-Variante benötigt. S := StringReplace(S, '%q', '%d%09d', [rfReplaceAll]); i2 := 0; For i := 0 to High(Args) do If Args[i].VType = vtInt64 Then Begin i8 := Args[i].VInt64^; A[i2] := i8 div 1000000000; If i8 < 0 Then i8 := -i8; A[i2 + 1] := i8 mod 1000000000; Inc(i2, 2); End Else Begin A[i2] := Args[i].VInteger; Inc(i2); End; wvsprintfW(@StrBuffer2, PWideChar(S), @A); Result := PWideChar(@StrBuffer2); End; procedure TForm1.FormCreate(Sender: TObject); var i: int64; begin i := 2345678901234567890; Caption := Format('%q %q', [1234567890123456789, i]); end; %d integer %q int64 %u cardinal %s WideString %S AnsiString/String %x lower(hex) %X upper(hex) und der Ausgabestring darf maximal 1023 Zeichen lang sein. für genauere Definitionen zu den Standardtypen siehe MSDN. |
Re: Unicode Ersatz für Format
Der Aufruf sieht folgendermaßen aus:
Delphi-Quellcode:
Selbst nativ (also ohne Übersetzung):
MessageBoxW(hDPM, PWideChar(Format(_('Error while downloading and processing updateinformation.' + #13#10 + 'Message: %s' + #13#10 + 'Errorclass: %s'), [e.Message, e.ClassName])), PWideChar(_('[Update Plugin] Downloading/Processingerror')), MB_OK or MB_ICONERROR);
Zitat:
|
Re: Unicode Ersatz für Format
e ist doch sicherlich eine stino Exception. Könnte es in diesem Falle vielleicht keine ganz so dumme Idee sein, einer Unicode-Funktion auch Unicode-String zu übergeben... ?
Delphi-Quellcode:
Writeln(Format('Hello %s', ['World'])); // 'Hello ??d'
Writeln(Format('Hello %S', ['World'])); // 'Hello World' Writeln(Format('Hello %s', [WideString('World')])); // 'Hello World' |
Re: Unicode Ersatz für Format
%s & %S ... siehe MSDN
in Deutsch: %s = selber Stringtyp (Ansi/Wide), wie die Aufzurufende Funktion %S = anderes Stringformat also bei wvsprintfW %s für PWideChar/WideString und %S für P(Ansi)Char/(Ansi)String und bei wvsprintf/wvsprintfA %s für P(Ansi)Char/(Ansi)String und %S für PWideChar/WideString
Delphi-Quellcode:
MessageBoxW(hDPM, PWideChar(Format('Error while downloading and processing updateinformation.'
+ #13#10'Message: %S'#13#10'Errorclass: %S', [e.Message, e.ClassName])), '[Update Plugin] Downloading/Processingerror', MB_OK or MB_ICONERROR); // dieses _( ) macht 'ne Typenumwandlung, oder wie? MessageBoxW(hDPM, PWideChar(Format('Error while downloading and processing updateinformation.' + #13#10'Message: %s'#13#10'Errorclass: %s', [_(e.Message), _(e.ClassName)])), '[Update Plugin] Downloading/Processingerror', MB_OK or MB_ICONERROR); |
Re: Unicode Ersatz für Format
Ich hätte da noch eine kleine Frage, passt ja zum Thema.
wvsprintf kann nur Integer aber keine Floads oder ? |
Re: Unicode Ersatz für Format
nicht nur, aber keine reelen Typen
wenn man jetzt nicht auf die API versichtet und alles selbermachen will, dann muß man entweder mit dem Fehlen einiger Formate leben, oder man muß versuchen den gewünschten Typen in die Grundtypen zu zerlegen (Bsp. siehe 1) oder muß diesen Typen selber z.B in einen String umwandeln (Bsp. siehe 2). OK und man kann natürlich auch eine der vielen "fertigen" Unicodesammlungen verwenden. :angel: 1:
Delphi-Quellcode:
2:
Function Format(S: WideString; Const Args: Array of Const): WideString;
Var StrBuffer2: Array[0..1023] of WideChar; A: Array[0..15] of Integer; i, i2: Integer; i8: Int64; Begin // aufpassen!!! es wird eine unicodefähige StringReplace-Variante benötigt. S := StringReplace(S, '%q', '%d%09d', [rfReplaceAll]); S := StringReplace(S, '%F', '%d%09d,%09d', [rfReplaceAll]); i2 := 0; For i := 0 to High(Args) do Case Args[i].VType of vtInt64: Begin i8 := Args[i].VInt64^; A[i2] := i8 div 1000000000; If i8 < 0 Then i8 := -i8; A[i2 + 1] := i8 mod 1000000000; Inc(i2, 2); End; vtExtended: Begin i8 := Trunc(Args[i].VExtended^); A[i2] := i8 div 1000000000; If i8 < 0 Then i8 := -i8; A[i2 + 1] := i8 mod 1000000000; A[i2 + 2] := Trunc(Args[i].VExtended^ * 1000000000); Inc(i2, 3); End; Else Begin A[i2] := Args[i].VInteger; Inc(i2); End; End; wvsprintfW(@StrBuffer2, PWideChar(S), @A); Result := PWideChar(@StrBuffer2); End;
Delphi-Quellcode:
Function Format(S: WideString; Const Args: Array of Const): WideString;
Var StrBuffer2: Array[0..1023] of WideChar; A: Array[0..15] of Integer; T: Array[0..15] of String; i: Integer; Begin // aufpassen!!! es wird eine unicodefähige StringReplace-Variante benötigt. S := StringReplace(S, '%q', '%S', [rfReplaceAll]); S := StringReplace(S, '%f', '%S', [rfReplaceAll]); For i := High(Args) downto 0 do Case Args[i].VType of vtInt64: Begin T[i] := IntToStr(Args[i].VInt64^); A[i] := PChar(T[i]); End; vtExtended: Begin T[i] := FloatToStr(Args[i].VInt64^); A[i] := PChar(T[i]); End; Else A[i] := Args[i].VInteger; End; wvsprintfW(@StrBuffer2, PWideChar(S), @A); Result := PWideChar(@StrBuffer2); End; |
Re: Unicode Ersatz für Format
Zitat:
Zitat:
_() macht eine Übersetzung (siehe GnuGettext) MfG xZise |
Re: Unicode Ersatz für Format
asoooo, dacht schon des se wieder irgend so'n neues Delphifeature :lol:
dann natürlich so :angel:
Delphi-Quellcode:
MessageBoxW(hDPM, PWideChar(Format('Error while downloading and processing updateinformation.'
+ #13#10'Message: %S'#13#10'Errorclass: %S', [_(e.Message), _(e.ClassName_)])), '[Update Plugin] Downloading/Processingerror', MB_OK or MB_ICONERROR); MessageBoxW(hDPM, PWideChar(Format('Error while downloading and processing updateinformation.' + #13#10'Message: %s'#13#10'Errorclass: %s', [WideString(_(e.Message)), WideString(_(e.ClassName_))])), '[Update Plugin] Downloading/Processingerror', MB_OK or MB_ICONERROR); |
Re: Unicode Ersatz für Format
Zitat:
Delphi-Quellcode:
Ich muss zuerst einen String mit Platzhaltern übersetzt werden (_())! Dann die Variablen einsetzen (Format) und dann in WideString umwandeln!
Format(_('string %s'), [e.Message]);
Der letzte Schritt ist das Problem. :) |
Re: Unicode Ersatz für Format
Zitat:
Delphi-Quellcode:
Wie wärs, wenn die Formatfunktion auch noch C-Formatierungssymbole erkennen würde? z.b. \r\n für Windows Zeilenumbruch, statt #13#10.
MessageBoxW(hDPM, PWideChar(Format('Error while downloading and processing updateinformation.'
+ #13#10'Message: %S'#13#10'Errorclass: %S', [_(e.Message), _(e.ClassName_)])), '[Update Plugin] Downloading/Processingerror', MB_OK or MB_ICONERROR); MessageBoxW(hDPM, PWideChar(Format('Error while downloading and processing updateinformation.' + #13#10'Message: %s'#13#10'Errorclass: %s', [WideString(_(e.Message)), WideString(_(e.ClassName_))])), '[Update Plugin] Downloading/Processingerror', MB_OK or MB_ICONERROR); Der obige Code ist meiner Meinung nach nicht wirklich toll. |
Re: Unicode Ersatz für Format
Zitat:
aber dann wäre beides FormatString und das einzufügende wohl nicht schlecht.
Delphi-Quellcode:
aber mal 'ne Frage, diese _(...) arbeitet doch nur mit Strings/AnsiStrings?
Format(_('string %s'), [_(e.Message)]);
// oder alles zusammen _(Format('string %s', [e.Message])); da würde es doch eigentlih alle UnicodeInformationen zerstören, weshalb man gleich bei delphi's Format-Version (Ansi) bleiben könnte. :gruebel: |
Re: Unicode Ersatz für Format
Zitat:
Das scheint hier wohl noch ein paar Probleme zu geben! 1. _(<string>) übersetzt einen String (z.B. <string>="Hallo Welt"; Dann guckt er in der Datei nach "Hallo Welt" und würde die jetzt in "Hello World" übersetzten). 2. _() Arbeitet mit WideStrings! (Ein/Ausgabe) Zu den Ersten: Das kann er übersetzen: "Zahl: %d" => "Number %d" => Format(...) Erfolg Wenn ich aber das so wie dein zweiten Vorschlag machen würde: "Zahl: %d" => Format(...) => "Zahl: 123456789" => Kein Erfolg Deshalb muss ich irgendwie Format auf WideStrings anwenden. MfG xZise |
Re: Unicode Ersatz für Format
Also irgendwie will das nicht funktionieren!
Gibt es denn keine Möglichkeit dieses Format auch für WideStrings hinzubekommen? Irgendwie scheinen die Übergabeparameter nicht ganz zu stimmen:
Delphi-Quellcode:
Er übersetzt das zwar, setzt aber anstelle des Strings irgendwelche komischen (japanisch/chinesisch?) Zeichen ein.
Format(_(<string>), [<string>]);
Auch das die Bytereihenfolge falsch ist, stimmt nicht, da ein swapen der Reihenfolge des Strings nichts bringt! [edit=1]ICH HABE ES :) Es funktioniert wenn ich statt "<string>" als Variable "WideString(<string>)" einsetze.[/edit] MfG xZise |
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:06 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz