Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   string to Float, für lesen aus einer Datei (https://www.delphipraxis.net/195684-string-float-fuer-lesen-aus-einer-datei.html)

bernhard_LA 17. Mär 2018 14:00

string to Float, für lesen aus einer Datei
 
ich muss Zahlen aus einer Datei einlesen, die entweder mit deutschem (1,234) oder amerikanischem Decimalsparator (1.234) erstellt wurden.
Die Anwendung soll auf Windows Systemen mit Sprache Deutsch oder Englisch dann laufen und die eingelesenen Strings immer richtig interpretieren

Gibt es hier eine bessere Lösung als meine ?

Delphi-Quellcode:
  function ChangeLocalFloatStr (FloatStr : String ) : String;
var usedDecimalSeparator : Char ;
    NOTusedDecimalSeparator : Char ;
begin
   //   egal was der user eingestellt hat ......
   usedDecimalSeparator := TFormatsettings.Invariant.DecimalSeparator;

   if usedDecimalSeparator=',' then NOTusedDecimalSeparator:='.'
          else NOTusedDecimalSeparator :=',';


   if pos (usedDecimalSeparator , FloatStr) > 0   then
       begin
          result := FloatStr;
       end
       else
       begin
          result := stringreplace(FloatStr, NOTusedDecimalSeparator , usedDecimalSeparator,
                          [rfReplaceAll, rfIgnoreCase]);
       end;

end;

Aufruf :


Delphi-Quellcode:
a : real;
astr : String ;


 a := FloatToStr(   ChangeLocalFloatStr (astr)) ;

Zacherl 17. Mär 2018 14:27

AW: string to Float, für lesen aus einer Datei
 
Rein von der Lösungsmöglichkeit her würde ich es auch so machen. Statt
Delphi-Quellcode:
StringReplace
würde ich allerdings direkt
Delphi-Quellcode:
FloatStr[DelimPos] := '.'
setzen, also den Parameter als
Delphi-Quellcode:
var
übergeben. So sparst du dir das Rumkopieren im Speicher. Mehrere Vorkommen des Dezimalseparators innerhalb eines einzelnen Wertes sind ja eh nicht zulässig, weshalb
Delphi-Quellcode:
StringReplace
mit
Delphi-Quellcode:
rfReplaceAll
auch Overkill sein sollte.

Delphi-Quellcode:
function ChangeLocalFloatStr(var FloatStr: String): String;
var
  I: Integer;
begin
  I := Pos(',', FloatStr);
  if (I > 0) then
  begin
    FloatStr[I] := TFormatSettings.Invariant.DecimalSeparator;
  end;
end;
Die ganzen zusätzlichen Variablen würde ich mir auch sparen. Achso, dann musst du den
Delphi-Quellcode:
StrToFloat
Aufruf natürlich abändern in
Delphi-Quellcode:
StrToFloat(FloatStr, TFormatSettings.Invariant)
.

Alternativ alles ganz kompakt (dann sparst du dir beim Aufrufen die zusätzliche Variable):
Delphi-Quellcode:
function LocalStrToFloat(FloatStr: String): Double;
var
  I: Integer;
begin
  I := Pos(',', FloatStr);
  if (I > 0) then
  begin
    FloatStr[I] := TFormatSettings.Invariant.DecimalSeparator;
  end;
  Result := StrToFloat(FloatStr, TFormatSettings.Invariant);
end;

Neumann 17. Mär 2018 15:16

AW: string to Float, für lesen aus einer Datei
 
Es gibt dann aber noch folgende Schreibweise für Zahlen, die berücksichtigt werden müssten:

10,000,000.34 oder ev. auch 10.000.000,34

markus5766h 17. Mär 2018 18:20

AW: string to Float, für lesen aus einer Datei
 
Zitat:

Zitat von Neumann (Beitrag 1396468)
Es gibt dann aber noch folgende Schreibweise für Zahlen, die berücksichtigt werden müssten:

10,000,000.34 oder ev. auch 10.000.000,34

. . . siehe Post #2 :
"Mehrere Vorkommen des Dezimalseparators innerhalb eines einzelnen Wertes sind ja eh nicht zulässig, ..."

bei "10.000.000,34" könnt' ich mir glatt überlegen, ob dies eine IP-Adresse sein soll :-D

aber mal ernsthaft : ich hab' solche Schreibweisen mit mehreren Separatoren auch schon gesehen und dann gegrübelt, was das denn nun sein soll - man kann von einer Software nicht erwarten, dass sie die Absicht oder Meinung desjenigen errät, der sich bei der Schreibweise von Zahlenwerten nicht an gängige Normen hält.
Im obigen Beispiel fallen mir gleich 4 mögliche Lösungen ein, die ich dann abfragen bzw. auswerten müsste . . .

KodeZwerg 17. Mär 2018 21:46

AW: string to Float, für lesen aus einer Datei
 
Zitat:

Zitat von markus5766h (Beitrag 1396479)
"Mehrere Vorkommen des Dezimalseparators innerhalb eines einzelnen Wertes sind ja eh nicht zulässig, ..."
Im obigen Beispiel fallen mir gleich 4 mögliche Lösungen ein, die ich dann abfragen bzw. auswerten müsste . . .

Ich bin der Meinung das bei dem Beispiel nur ein Dezimalseperator vorhanden ist.
Als Lösung für so eine Situation schwebt mir so etwas vor:
String in einer Schleife nach "." und "," suchen lassen, das zuletzt gefundene wird als Seperator genommen, im gleichen Atemzug werden die 100'er Markierungen entfernt.

Delphi.Narium 18. Mär 2018 09:58

AW: string to Float, für lesen aus einer Datei
 
Und was passiert hierbei?

1.001
1,001
100,001
100.001

Was ist jetzt Eintausendeins und was Einskommanullnulleins?
Was ist Einhundertkommanullnulleins und was Einhunderttausendeins?

Für eine sichere Erkennung des Dezimalseparators benötigt man mindestens zwei Tausenderseperatoren und damit Werte über einer Million.

KodeZwerg 18. Mär 2018 10:38

AW: string to Float, für lesen aus einer Datei
 
Ich verstehe was Du meinst, da wird es schnell chaotisch.
Na dann Fragen wir doch mal den TE ob 1000'er Markierungen überhaupt vorliegen.

So hier könnte man testen ob eine Konvertierung gelingt bevor man es konvertiert:
Code:
funtion TestFloatStr ( S : String ) : Boolean;
begin
  try
    StrToFloat(s); // normal aufrufen
    result := true; // scheint keine Exception auszulösen also ist Wert gut
  except
    result := false; // oh-oh, fehler!
  end;
end;

Uwe Raabe 18. Mär 2018 10:50

AW: string to Float, für lesen aus einer Datei
 
Zitat:

Zitat von KodeZwerg (Beitrag 1396514)
So hier könnte man testen ob eine Konvertierung gelingt bevor man es konvertiert:

Oder man benutzt gleich
Delphi-Quellcode:
TryStrToFloat
oder
Delphi-Quellcode:
Double.TryParse
mit den erwarteten
Delphi-Quellcode:
FormatSettings
. Das hat den Nebeneffekt, daß es auch gleich konvertiert, wenn das denn möglich ist.

KodeZwerg 18. Mär 2018 14:05

AW: string to Float, für lesen aus einer Datei
 
Das mit dem Double.TryParse war mir neu und klingt interessant, ich habe jetzt ein wenig darüber gelesen, per CultureInfo/InvariantCulture kann man das "." und "," Problem in den Griff bekommen. Aber wenn die Quelle gemixt ist, da hilft sowas auch nicht weiter, vermute ich, Danke für den Tipp!

Uwe Raabe 18. Mär 2018 14:27

AW: string to Float, für lesen aus einer Datei
 
Zitat:

Zitat von KodeZwerg (Beitrag 1396536)
Aber wenn die Quelle gemixt ist, da hilft sowas auch nicht weiter, vermute ich

Das ist auch nicht allein aus den Daten zu ermitteln.

Zitat:

Zitat von Delphi.Narium (Beitrag 1396509)
1.001
1,001
100,001
100.001

Schönes Beispiel. Je nach Dezimal- und Tausndertrenner sind alle vier Zahlen in beiden Systemen gültig, haben halt nur unterschiedliche Bedeutung.


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:26 Uhr.
Seite 1 von 2  1 2      

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