AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

"Sicheres" Umwandeln von Zeichenkette in Zahl

Ein Thema von stifflersmom · begonnen am 29. Sep 2017 · letzter Beitrag vom 30. Sep 2017
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.633 Beiträge
 
Delphi 12 Athens
 
#1

AW: "Sicheres" Umwandeln von Zeichenkette in Zahl

  Alt 29. Sep 2017, 15:50
Nur ist das Problem der 1000-er Formatierung damit nicht erschlagen.
Eine Test mit 1.024,23 ergibt dann ein False mit einer 0 als Ergebnis.
Ah ja, ich vergaß! Nein, dann funktioniert das so nicht. Dann muss man erst den Dezimalseparator ermitteln und dann die Tausendertrenner eliminieren. Ist dann allerdings nicht mehr so kompakt:
Delphi-Quellcode:
function TryStrToFloatAll(const S: string; out Value: Double): Boolean;
var
  sep: set of Char;
  dez: Char;
  I: Integer;
begin
  Result := False;

  { collect possible decimal separators }
  sep := [];
  for I := 0 to Length(AllFormatSettings) - 1 do begin
    Include(sep, AllFormatSettings[I].DecimalSeparator);
  end;

  { determine current decimal separator }
  dez := #0;
  for I := Length(S) downto 0 do begin
    if S[I] in Sep then begin
      dez := S[I];
      Break;
    end;
  end;
  { no decimal separator => wrong input. Try StrToInt instead. }
  if dez = #0 then Exit;

  Result := True;
  for I := 0 to Length(AllFormatSettings) - 1 do begin
    { try all formatsettings with found decimal separator }
    if dez = AllFormatSettings[I].DecimalSeparator then begin
      { eliminate thousand separator before conversion }
      if TryStrToFloat(StringReplace(S, AllFormatSettings[I].ThousandSeparator, '', [rfReplaceAll]), Value, AllFormatSettings[I]) then Exit;
    end;
  end;
  Result := False;
end;
Wenn sicher ist, daß nur Punkt und Komma als Separatoren auftreten können, dann ließe sich der Code natürlich auch etwas schlanker gestalten. Ich habe mir aber jetzt die Settings der einzelnen Länder nicht angeschaut.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
stifflersmom

Registriert seit: 8. Dez 2005
Ort: 24994 Holt
383 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#2

AW: "Sicheres" Umwandeln von Zeichenkette in Zahl

  Alt 29. Sep 2017, 15:54
Hallo Uwe,

von dem Code bin ich auf jeden Fall erst Mal beeindruckt.
Den werde ich mir gleich mal genauer zu Gemüte führen.

Danke erst mal
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#3

AW: "Sicheres" Umwandeln von Zeichenkette in Zahl

  Alt 29. Sep 2017, 16:17
Mal 'ne etwas altertümliche Idee:

Es gibt doch die Prozedure VAL. Könnte man damit nicht "austesten"?
Delphi-Quellcode:
var
  I : Float; // oder sowas
  Code: Integer;
begin
  { Text aus Zeichenfolge übernehmen }
  Val(Zeichenfolge, I, Code);
  { Fehler bei der Konvertierung in Zahl? }
  if Code <> 0 then begin
    // In Code haben wir jetzt die Position des Zeichens,
    // dass eine Konvertierung in eine Zahl verhindert.
    // Dieses Zeichen könnte man jetzt auswerten, um zu erfahren
    // ob es der Tausendertrenner oder der Dezimalseparator ist.
    // Einen derartigen Test müsste man dann (hoffentlich nur) für die erste Zeile
    // einer CSV-Datei machen und könnte damit ermitteln, welche Zeichen
    // zu tauschen sind.
  end;
end;
  Mit Zitat antworten Zitat
stifflersmom

Registriert seit: 8. Dez 2005
Ort: 24994 Holt
383 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#4

AW: "Sicheres" Umwandeln von Zeichenkette in Zahl

  Alt 29. Sep 2017, 17:13
Mal 'ne etwas altertümliche Idee:

Es gibt doch die Prozedure VAL. Könnte man damit nicht "austesten"?
Delphi-Quellcode:
var
  I : Float; // oder sowas
  Code: Integer;
begin
  { Text aus Zeichenfolge übernehmen }
  Val(Zeichenfolge, I, Code);
  { Fehler bei der Konvertierung in Zahl? }
  if Code <> 0 then begin
    // In Code haben wir jetzt die Position des Zeichens,
    // dass eine Konvertierung in eine Zahl verhindert.
    // Dieses Zeichen könnte man jetzt auswerten, um zu erfahren
    // ob es der Tausendertrenner oder der Dezimalseparator ist.
    // Einen derartigen Test müsste man dann (hoffentlich nur) für die erste Zeile
    // einer CSV-Datei machen und könnte damit ermitteln, welche Zeichen
    // zu tauschen sind.
  end;
end;
Hab ich jetzt mal kurz ausgetestet.
ein Test mit 1.024,15 ergibt die Fehlerposition '6', das bedeutet dann, erst alle Punkte zu entfernen und anschließend eine Umwandlung des Kommas in einen Punkt.
Ja, auch as funktioniert dann.
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#5

AW: "Sicheres" Umwandeln von Zeichenkette in Zahl

  Alt 29. Sep 2017, 17:24
Ok, das Problem ist aber, dass man dann zwar weiß, wo der erste Fehler ist, aber das andere Zeichen quasi erraten muss.

Konkret: bei 1.024,15 und Fehler beim , sagt ja nicht, dass wir nach 'nem . suchen müssen, um ihn vorher zu entfernen. Hier ist ja irgendwie auch noch raten angesagt.

So gut war meine Idee dann auch wieder nicht, da immernoch interpretierbare Unwägbarkeiten übrigbleiben

Das ginge nur dann verlässlich, wenn man definitiv weiß, das nur . und , als Problemfälle in Frage kommen, man nur nicht weiß, in welcher Reihenfolge.

Kann man sicherstellen, dass immer dann, wenn der Fehler bei einem , auftritt, der . zu entfernen ist und das , durch einen . zu ersetzen und im umgekehren Fall bei einem Fehler bei einem . das , zu entfernen ist und der . durch ein , zu ersetzen ist, mag das angehen. Können aber auch noch andere Alternativen (wobei mir keine einfällt) bestehen, wird's schon wieder unsicher.
  Mit Zitat antworten Zitat
stifflersmom

Registriert seit: 8. Dez 2005
Ort: 24994 Holt
383 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#6

AW: "Sicheres" Umwandeln von Zeichenkette in Zahl

  Alt 29. Sep 2017, 17:27
Kann man sicherstellen, dass immer dann, wenn der Fehler bei einem , auftritt, der . zu entfernen ist und das , durch einen . zu ersetzen und im umgekehren Fall bei einem Fehler bei einem . das , zu entfernen ist und der . durch ein , zu ersetzen ist, mag das angehen. Können aber auch noch andere Alternativen (wobei mir keine einfällt) bestehen, wird's schon wieder unsicher.
Magst Du diesen Satz mal aufnehmen und als Anhang einfügen...

Gruß
  Mit Zitat antworten Zitat
nahpets
(Gast)

n/a Beiträge
 
#7

AW: "Sicheres" Umwandeln von Zeichenkette in Zahl

  Alt 29. Sep 2017, 17:46
Nö, lieber nicht, das ist so eine meiner tückischen Formulierungen, die dabei rauskommen, wenn ich vergeblich versuche, mich präzise auszudrücken. Man merkt daran, dass ich mich über viele Jahre mit Juristerei rumschlagen musste. Da muss dann in einem Satz alles Mögliche so sicher und korrekt und widerspruchsfrei formuliert werden, dass es am Ende doch wieder nur unverständlich ist. Oder kurz: Beamtendeutsch

Und bei 'ner Aufnahme würd' ich vermutlich sehr arg ins Stottottottottotteren kommen
  Mit Zitat antworten Zitat
stifflersmom

Registriert seit: 8. Dez 2005
Ort: 24994 Holt
383 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#8

AW: "Sicheres" Umwandeln von Zeichenkette in Zahl

  Alt 29. Sep 2017, 17:14
Nur ist das Problem der 1000-er Formatierung damit nicht erschlagen.
Eine Test mit 1.024,23 ergibt dann ein False mit einer 0 als Ergebnis.
Ah ja, ich vergaß! Nein, dann funktioniert das so nicht. Dann muss man erst den Dezimalseparator ermitteln und dann die Tausendertrenner eliminieren. Ist dann allerdings nicht mehr so kompakt:
Delphi-Quellcode:
function TryStrToFloatAll(const S: string; out Value: Double): Boolean;
var
  sep: set of Char;
  dez: Char;
  I: Integer;
begin
  Result := False;

  { collect possible decimal separators }
  sep := [];
  for I := 0 to Length(AllFormatSettings) - 1 do begin
    Include(sep, AllFormatSettings[I].DecimalSeparator);
  end;

  { determine current decimal separator }
  dez := #0;
  for I := Length(S) downto 0 do begin
    if S[I] in Sep then begin
      dez := S[I];
      Break;
    end;
  end;
  { no decimal separator => wrong input. Try StrToInt instead. }
  if dez = #0 then Exit;

  Result := True;
  for I := 0 to Length(AllFormatSettings) - 1 do begin
    { try all formatsettings with found decimal separator }
    if dez = AllFormatSettings[I].DecimalSeparator then begin
      { eliminate thousand separator before conversion }
      if TryStrToFloat(StringReplace(S, AllFormatSettings[I].ThousandSeparator, '', [rfReplaceAll]), Value, AllFormatSettings[I]) then Exit;
    end;
  end;
  Result := False;
end;
Wenn sicher ist, daß nur Punkt und Komma als Separatoren auftreten können, dann ließe sich der Code natürlich auch etwas schlanker gestalten. Ich habe mir aber jetzt die Settings der einzelnen Länder nicht angeschaut.
Auf jeden Fall ist das für mich großes Kino!
Klasse Code.
Wo stehen eigentlich genau diese
Delphi-Quellcode:
  cLocales: array[0..5] of Integer
      = (
         1031, { German }
         1033, { English }
         1040, { Italian }
         1055, { Turkish }
         3082, { Spanish }
         LOCALE_USER_DEFAULT);
Länderkosntanten?
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.633 Beiträge
 
Delphi 12 Athens
 
#9

AW: "Sicheres" Umwandeln von Zeichenkette in Zahl

  Alt 29. Sep 2017, 17:46
Wo stehen eigentlich genau diese
Delphi-Quellcode:
  cLocales: array[0..5] of Integer
      = (
         1031, { German }
         1033, { English }
         1040, { Italian }
         1055, { Turkish }
         3082, { Spanish }
         LOCALE_USER_DEFAULT);
Länderkosntanten?
https://msdn.microsoft.com/en-us/lib...edded.10).aspx
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.633 Beiträge
 
Delphi 12 Athens
 
#10

AW: "Sicheres" Umwandeln von Zeichenkette in Zahl

  Alt 29. Sep 2017, 17:59
Der Code soll natürlich nur als Richtlinie dienen. Natürlich muss man die ganze Sucherei nach den richtigen FormatSettings nicht bei jedem Wert machen. Einmalig am Anfang der Datei genügt. Danach sollte sich das ja nicht mehr ändern. (Hat Stephan ja in einem der Code-Comments schon erwähnt)
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:21 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