Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi GetLocaleInfo() Aufruf, ist es so richtig? (https://www.delphipraxis.net/195865-getlocaleinfo-aufruf-ist-es-so-richtig.html)

KodeZwerg 2. Apr 2018 16:33

GetLocaleInfo() Aufruf, ist es so richtig?
 
Hallo, ich würde mich gerne absichern ob folgender Code korrekt ist:

Delphi-Quellcode:
function ThousandSeparator : String;
var
  buf: PChar; // temp puffer
begin
  Result := '#'; // falsch initialisieren, gegebenfalls später mit einem Default-Wert bei Fehler ersetzen
  try
  buf := StrAlloc(10); // puffer eine größe zusichern
  GetLocaleInfo(
    LOCALE_SYSTEM_DEFAULT,
    LOCALE_STHOUSAND,
    buf,
    10); // GetLocaleInfo() direkt abfragen ohne die Länge vom Trennzeichen zu kennen, aber über 10 sollten es wohl nicht werden
  finally
   Result := StrPas(buf); // in einen String konvertieren
   StrDispose(buf); // speicher bereinigen
  end;
end;
Ziel soll sein das ich in einem String das/die Zeichen für's Lokale Tausender-Trennzeichen bekomme.
Oder ist es generell so falsch und es gibt aktuellere Methoden um das Zeichen (als String) zu bekommen?

Zacherl 2. Apr 2018 16:38

AW: GetLocaleInfo() Aufruf, ist es so richtig?
 
Zitat:

Zitat von KodeZwerg (Beitrag 1397884)
Oder ist es generell so falsch und es gibt aktuellere Methoden um das Zeichen (als String) zu bekommen?

Delphi hat diese Schnittstelle gekapstelt:
http://docwiki.embarcadero.com/CodeE...ttings_(Delphi)

Ansonsten noch zum WinAPI Ansatz:
"Theoretisch" kann
Delphi-Quellcode:
StrAlloc
fehlschlagen. In diesem Falle läuft dein
Delphi-Quellcode:
StrDispose
im
Delphi-Quellcode:
finally
Block ins Leere. Und die fixe Länge von 10 wird sicherlich auch funktionieren, aber korrekter wäre es die API einmal mit
Delphi-Quellcode:
nil
Buffer und 0 Länge aufzurufen und den Rückgabewert zu verwenden. Alternativ einen fixen Anfangsbuffer, Rückgabe prüfen, MSDN-Library durchsuchenGetLastError auf
Delphi-Quellcode:
ERROR_INSUFFICENT_BUFFER
prüfen, Buffer verdoppeln, Aufruf wiederholen, etc.

KodeZwerg 2. Apr 2018 17:09

AW: GetLocaleInfo() Aufruf, ist es so richtig?
 
Wäre es so korrekt? (mit Verzicht auf WinApi)

Delphi-Quellcode:
function ThousandSeparator : String;
var
  FS: TFormatSettings;
begin
  FS := TFormatSettings.Create;
  Result := FS.ThousandSeparator;
end;
Muss ich da noch Speicher bereinigen?

Zacherl 2. Apr 2018 17:14

AW: GetLocaleInfo() Aufruf, ist es so richtig?
 
Zitat:

Zitat von KodeZwerg (Beitrag 1397889)
Muss ich da noch Speicher bereinigen?

Nee, ist ja ein
Delphi-Quellcode:
record
. Alternativ beinhaltet
Delphi-Quellcode:
System.SysUtils
auch die globale Variable
Delphi-Quellcode:
FormatSettings
, die du direkt verwenden kannst.

günni0 2. Apr 2018 17:15

AW: GetLocaleInfo() Aufruf, ist es so richtig?
 
Zitat:

Zitat von KodeZwerg (Beitrag 1397889)
Wäre es so korrekt? (mit Verzicht auf WinApi)

Delphi-Quellcode:
function ThousandSeparator : String;
var
  FS: TFormatSettings;
begin
  FS := TFormatSettings.Create;
  Result := FS.ThousandSeparator;
end;
Muss ich da noch Speicher bereinigen?

So ungefähr mache ich es auch. Bisher hat sich, trotz internationalem Gebrauch meines Programms, keiner beschwert. Ich erstelle TFormatSettings aber nur einmalig bei Programmstart und nutze die so gewonnenen Daten dann weiter.

KodeZwerg 2. Apr 2018 17:33

AW: GetLocaleInfo() Aufruf, ist es so richtig?
 
Nun aber hoffentlich Ok:

Delphi-Quellcode:
function ThousandSeparator : String;
begin
  Result := FormatSettings.ThousandSeparator;
end;
Vielen Dank für so schnelle Hilfe!

günni0 2. Apr 2018 17:34

AW: GetLocaleInfo() Aufruf, ist es so richtig?
 
Jetzt noch alles in eine eigene Unit und alles ist sauber, schön und leicht erweiterbar (jedenfalls würde ich es so machen).

Delphi-Quellcode:
unit MyUnitX;

interface

type
 TUnitX = record
 private
 var
  MyFormatSettings: TFormatSettings;
 public
  class function ThousandSeparator : string; static;
 end;

implementation

var
 UnitX: TUnitX;

class function TUnitX.ThousandSeparator : String;
begin
  Result := FormatSettings.ThousandSeparator;
end;

initialization

UnitX.MyFormatSettings := TFormatSettings.Create(GetUserDefaultLCID);
So eine ähnliche Unit habe ich. Grund für MyFormatSettings ist, weil ich FormatSettings überschreibe und immer noch die originalen Werte haben möchte.

KodeZwerg 2. Apr 2018 17:41

AW: GetLocaleInfo() Aufruf, ist es so richtig?
 
Ich portiere gerade Code der auf System.ThousandSeperator aufbaute, kommt nur in einer Unit vor, hab da nun meine funktion drinn, klappte auch beim ersten Post, ich wollte mich nur absichern das ich da kein Fehler mache, da ich die WinApi Antwort leider nicht ganz Verstanden habe erschien mir das was ich Verstanden habe einfacher umzusetzen. :mrgreen:
[EDIT]Also das mit dem StrDispose() das es fehlschlagen könnte hab ich Verstanden aber den Rest noch nicht.[/EDIT]

himitsu 2. Apr 2018 17:51

AW: GetLocaleInfo() Aufruf, ist es so richtig?
 
Zitat:

Zitat von KodeZwerg (Beitrag 1397884)
Hallo, ich würde mich gerne absichern ob folgender Code korrekt ist
...
Oder ist es generell so falsch und es gibt aktuellere Methoden um das Zeichen (als String) zu bekommen?

Gegenfrage: Warum hörst du nicht auf deinen Compiler? (vonwegen Variable nicht initialisiert)

Delphi-Quellcode:
buf := StrAlloc(10); // puffer eine größe zusichern
gehört vor das TRY
und
Delphi-Quellcode:
Result := StrPas(buf);
gehört vor Finally oder hinter das End.

Falls StrAlloc knallt, führst du dennoch StrDispose aus, es knallt nochmal und verfälscht den eigentlichen Fehler
und wenn es knallt, greifst du auch noch auf buf zu, was ebenfalls nicht gut ist.

UND, diese API löst keine Exceptions aus,
also hilft Try-Finally/Except garnichts.
Und falls es doch knallt, dann hattest DU "buf" falsch/nicht initialisiert
oder es ist so viel kaputt, dass eine Fehlerbehandlung eh sinnlos ist. (ist = war vorher schon)

Zitat:

falsch initialisieren, gegebenfalls später mit einem Default-Wert bei Fehler ersetzen
Und wie willst du erkennen, ob es einen Fehler gab, wenn du das Result dieser API nicht auswertest?


PS: Wenn ich Code als "Delphi/Pascal" implementiere, dann lasse ich das C-typische StrAlloc weg und nutzte einen passenden Delphi-String (AnsiString/UnicodeString/String)
und das StrDispose macht Delphi für mich.
Nach der API mit SetLength oder einem billigen PChar-Cast den String kürzen, falls der Inhalt doch kleiner war.

Oder ich nutze ein statisches Char-Array und Delphi-Referenz durchsuchenSetString

KodeZwerg 2. Apr 2018 18:17

AW: GetLocaleInfo() Aufruf, ist es so richtig?
 
So war mein Ansatz nach Zacherl's erstem Post:

Delphi-Quellcode:
function ThousandSeparator : String;
var
  buf: PChar;
begin
  Result := ','; // falls was schiefläuft einen default Wert
  buf := StrAlloc(10);
  if GetLastError() = ERROR_SUCCESS then
   if GetLocaleInfo(
       LOCALE_SYSTEM_DEFAULT,
       LOCALE_STHOUSAND,
       buf,
       10) <> 0 then Result := StrPas(buf);
   if GetLastError() <> ERROR_INSUFFICIENT_BUFFER then StrDispose(buf);
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:06 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