Stringreplace

Für Fragen von Einsteigern und Programmieranfängern...
Antworten
Adenos
Beiträge: 67
Registriert: So 17. Okt 2021, 17:18
OS, Lazarus, FPC: Windows 7
CPU-Target: X86
Wohnort: Allgäu

Stringreplace

Beitrag von Adenos »

in meinem Programm lese ich Kurswerte von verschiedenen Internetseiten ein. Auf vielen internationalen Seiten sind die Werte mit einem Punkt als Dezimaltrenner angegeben, auf deutschen Seiten dagegen mit einem Komma. Um mit den Kursen rechnen zu können, ersetze ich alle Punkte mit Stringreplace in Kommas. Das funktioniert auch auf meinem Rechner wunderbar, aber ich frage mich, was passiert eigentlich, wenn das Programm irgendwann mal auf einem amerikanischen Computer installiert wird? Gibt es dann nicht eine Fehlermeldung?

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Stringreplace

Beitrag von theo »

Was das System vorgibt, findet man in DefaultFormatSettings.
Man kann dort auch die Werte verändern:
DefaultFormatSettings.DecimalSeparator:='!';
Caption:=FloatToStr(12.5);

So hast du ein Ausrufezeichen als Dezimaltrenner.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Stringreplace

Beitrag von wp_xyz »

Und man sollte vielleicht noch erwähnen, dass DefaultFormatSettings (oder kürzer: FormatSettings - das ist dasselbe) die Standard-Einstellung für Zahlen-/Datums-/Zeit-Formate der Anwendung enthalten. Wenn du in Deutschland lebst, wo der Dezimaltrenner ein Komma ist, du aber partout einen Dezimalpunkt willst, dann kannst du einfach DefaultFormatSettings.DecimalSeparator auf '.' setzen, und künftig werden alle Dezimalzahlenstrings mit '.' ausgewertet.

Aber das System ist noch flexibler. Die Konvertierungsfunktionen StrToFloat und FloatToStr (aber auch DateToStr, TimeToStr, ...) kann man mit optionalen FormatSettings aufrufen. Wenn du also als Deutscher eine amerikanische Datei einlesen willst, kannst du dir einen Formatsettings-Record mit DecimalSeparator '.' erstellen und diesen als letzten Parameter in StrToFloat angeben. Dann werden die Dezimalzahlenstrings als Werte mit Punkt interpretiert, ohne dass du deine Anwendung generell auf DecimalSeparator '.' umstellen musst. Du kannst sogar in derselben Routine zwischen beiden Varianten testweise hin-und-her schalten. Und damit wäre ich bei meiner eigenen Konvertierungsroutine, die ich gerne verwende, wenn ein Programm sowohl Dezimalkomma als auch Dezimalpunkt können soll:

Code: Alles auswählen

function StrToFloatEx(s: String): Double;
const
  PUNKt = '.';
  KOMMA = ',';
var
  fs: TFormatSettings;
begin
  if not TryStrToFloat(s, Result) then
  begin
    fs := FormatSettings;
    if fs.decimalSeparator = PUNKT then fs.DecimalSeparator := KOMMA else fs.DecimalSeparator := PUNKT;
    Result := StrToFloat(s, fs);
  end;
end;

Adenos
Beiträge: 67
Registriert: So 17. Okt 2021, 17:18
OS, Lazarus, FPC: Windows 7
CPU-Target: X86
Wohnort: Allgäu

Re: Stringreplace

Beitrag von Adenos »

vielen Dank, aber meine Frage war eher so gemeint, was passiert, wenn ich mein Programm mit einem Dezimaltrenner Komma auf einem Rechner laufen lasse, der einen Dezimaltrenner Punkt hat? Funktioniert es dann noch einwandfrei?

Benutzeravatar
theo
Beiträge: 10467
Registriert: Mo 11. Sep 2006, 19:01

Re: Stringreplace

Beitrag von theo »

Adenos hat geschrieben:
Do 16. Dez 2021, 19:39
vielen Dank, aber meine Frage war eher so gemeint, was passiert, wenn ich mein Programm mit einem Dezimaltrenner Komma auf einem Rechner laufen lasse, der einen Dezimaltrenner Punkt hat? Funktioniert es dann noch einwandfrei?
Diese Frage wurde eigentlich beantwortet.
Die Formatsettings enthalten die Werte des aktuellen Systems.
Wenn du Punkt brauchst und das System Komma vorgibt, kannst du darauf reagieren.

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Stringreplace

Beitrag von wp_xyz »

So wie du's beschrieben hast, wird es nicht funktionieren...

Du musst, um bei dem StringReplace zu bleiben, prüfen ob der "andere" Dezimaltrenner im String enthalten ist und durch den "richtigen" ersetzen. Ob Punkt oder Komma "richtig" sind, steht in dem FormatSettings. Die folgende Routine sollte immer funktionieren, solange der Dezimaltrenner nur Punkt oder Komma sein kann, und solange natürlich keine Tausendertrenner vorhanden sind.

Code: Alles auswählen

function StrToFloatEx(s: String): Double;
const
  KOMMA = ',';
  PUNKT = '.';
begin
  if (FormatSettings.DecimalSeparator = KOMMA) and (Pos(PUNKT, s) > 0) then
      s := StringReplace(s, PUNKT, COMMA)
  else
  if (FormatSettings.DecimalSeparot = PUNKT) and (Pos(KOMMA, s) > 0 then
      s := Stringreplace(s, COMMA, PUINKT);
   Result := StrToFloat(s);
end;

Benutzeravatar
corpsman
Lazarusforum e. V.
Beiträge: 1496
Registriert: Sa 28. Feb 2009, 08:54
OS, Lazarus, FPC: Linux Mint Mate, Lazarus GIT Head, FPC 3.0
CPU-Target: 64Bit
Wohnort: Stuttgart
Kontaktdaten:

Re: Stringreplace

Beitrag von corpsman »

du kannst in der Regel auch bei all den konvertierungsroutienen als zusätzlichen Parameter die Formatsettings selbst übergeben. So mache ich das immer, intern wandle ich alles um in Punkt und wenn es Richtung user geht nehme ich dann die System variante ohne die Formatsettings, dadurch sieht der User es immer in den Einstellungen die er selbst definiert hat und du hast intern keinen Stress.
--
Just try it

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6198
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Re: Stringreplace

Beitrag von af0815 »

Alle Regeln kannst du zB. mit Chinesen vergessen. Da gibt es englische Systeme mit deutschen Sprachschemen. Mandarin Systeme mit englisch oder deutschen oder französischen Sprachschema. Oder deutsche Rechner mit englischen oder Mandarin Sprachschema.

Mandarin kann durch vereinfachte Chinesische Zeine ersetzt werden.

Da hilft wirklich nur nur mehr die Ratelogik wie von wp_xyz. Bin echt froh nicht mehr Software für China machen zu müssen. Für die Chinesen ist das alles kein Problem, in welcher Sprache das Userinterface ist. Die lernen sowieso nach Symbolen, damit ist die Sprache komplett egal. Und was die für Silben im Kopf haben, da kommt es auf ein paar Muster mehr oder weniger nicht mehr an. (Mein Eindruck)
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

Benutzeravatar
Niesi
Lazarusforum e. V.
Beiträge: 331
Registriert: So 26. Jun 2016, 19:44
OS, Lazarus, FPC: Linux Mint Cinnamon (Windows wenn notwendig), Lazarus 3.0 FPC 3.3.1

Re: Stringreplace

Beitrag von Niesi »

Adenos hat geschrieben:
Do 16. Dez 2021, 18:48
in meinem Programm lese ich Kurswerte von verschiedenen Internetseiten ein. Auf vielen internationalen Seiten sind die Werte mit einem Punkt als Dezimaltrenner angegeben, auf deutschen Seiten dagegen mit einem Komma. Um mit den Kursen rechnen zu können, ersetze ich alle Punkte mit Stringreplace in Kommas. Das funktioniert auch auf meinem Rechner wunderbar, aber ich frage mich, was passiert eigentlich, wenn das Programm irgendwann mal auf einem amerikanischen Computer installiert wird? Gibt es dann nicht eine Fehlermeldung?
Ich hatte aehnliche Probleme - Du solltest pruefen, ob es Dir passieren kann, dass Du Punkte, die als Tausendertrenner dienen, versehentlich in Kommas umwandelst. Ansonsten wandelst Du ja Strings in Floats um, das macht das System nach meiner Erfahrung immer richtig mit den regionalen Vorgaben ...
Wissen ist das einzige Gut, das sich vermehrt, wenn es geteilt wird ...

Benutzeravatar
Winni
Beiträge: 1577
Registriert: Mo 2. Mär 2009, 16:45
OS, Lazarus, FPC: Laz2.2.2, fpc 3.2.2
CPU-Target: 64Bit
Wohnort: Fast Dänemark

Re: Stringreplace

Beitrag von Winni »

Hi!

Die regionalen Einstellungen haben mehr Konfusion als Vorteil gebracht.

Lieber auf die gute alte Art:

* Alle Kommas durch Punkte ersetzen
* Statt StrToFloat das gute alte val benutzen

Fertig

Winni

wp_xyz
Beiträge: 4869
Registriert: Fr 8. Apr 2011, 09:01

Re: Stringreplace

Beitrag von wp_xyz »

Wenn ich als Deutscher das Ergebnis der Rechnung 1/2 mitteilen muss, dann sage ich "null-komma-fünf" und nicht "null-punkt-fünf" , und das wirst du nicht aus den Köpfen der Leute rauskriegen, zumindest nicht bei denen, die älter als ca 10 Jahre sind (oder in welcher Klasse kamen die Dezimalzahlen dran?)

Das einzig vernünftige Vorgehen ist, es bei den Vorgaben des Betriebssystems zu belassen, und nur bei Bedarf, wenn etwa Dateien mit anderem Dezimaltrenner zu lesen sind, sich flexible Konvertierungsroutinen zu schreiben.

Adenos
Beiträge: 67
Registriert: So 17. Okt 2021, 17:18
OS, Lazarus, FPC: Windows 7
CPU-Target: X86
Wohnort: Allgäu

Re: Stringreplace

Beitrag von Adenos »

Winni hat geschrieben:
Sa 18. Dez 2021, 10:22
* Alle Kommas durch Punkte ersetzen
* Statt StrToFloat das gute alte val benutzen
ja danke, so werde ich das auch machen,

Antworten