[gelöst] Im Editfeld eingabe: 34.56 -> absturz
-
- Beiträge: 6910
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Im Editfeld eingabe: 34.56 -> absturz
Wen du s meinst, das sind nicht einzelne Zeichen im String, sondern die Nummer des Stringes. s ist eine Array.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
Re: Im Editfeld eingabe: 34.56 -> absturz
Mathias hat geschrieben:Wen du s meinst, das sind nicht einzelne Zeichen im String, sondern die Nummer des Stringes. s ist eine Array.
Es ist schon richtig.
Dein Fehler: Man nennt ein Array of String nicht "s". Das ist verwirrend. Man nennt auch ein "double" nicht i.
Bei "StrArr" wäre das Missverständnis von m.fuchs nicht aufgetreten
- m.fuchs
- Lazarusforum e. V.
- Beiträge: 2808
- Registriert: Fr 22. Sep 2006, 19:32
- OS, Lazarus, FPC: Winux (Lazarus 2.0.10, FPC 3.2.0)
- CPU-Target: x86, x64, arm
- Wohnort: Berlin
- Kontaktdaten:
Re: Im Editfeld eingabe: 34.56 -> absturz
Ah, da bitte ich um Entschuldigung, das habe ich wirklich übersehen bzw. nicht mit einem Array namens s gerechnet. Mea culpa.
Na schön, sehen wir uns dein Programm noch einmal an. Ich habe es mal ein wenig angepasst (so dass nicht immer das Array-Element selber überschrieben wird:
Es gewinnt: KommaInPunkt.
Nun ist leider das Ausgangstestmaterial nicht besonders gut. Es gibt nämlich kein Komma. Also wird auch nichts geändert.
Ändern wir mal die Erzeugung des Arrays ab:
Es gewinnt: StringReplace.
Na schön, sehen wir uns dein Programm noch einmal an. Ich habe es mal ein wenig angepasst (so dass nicht immer das Array-Element selber überschrieben wird:
Code: Alles auswählen
program SpeedTest;
{$mode objfpc}{$H+}
uses
Classes, SysUtils, Windows, StrUtils;
const
max = 10000000;
function KommaInPunkt(var AString:string):string;
var
i,l :integer;
begin
l:=Length(AString);
if l>0 then for i:=1 to l do if AString[i]=',' then AString[i]:='.';
Result:=AString;
end;
var
i: integer;
start,ende:cardinal;
s: string;
strArray:array[0..max]of string;
begin
for i := 0 to max do begin
strArray[i] := FloatToStr(Random * 1000000);
end;
WriteLn('Array filled.');
start := GetTickCount;
for i := 0 to max do begin
s := Stringreplace(strArray[i],'.',',',[rfReplaceAll]);
end;
ende := GetTickCount;
Writeln('Zeit StringReplace:', Ende-Start);
start := GetTickCount;
for i := 0 to max do begin
s := KommaInPunkt(strArray[i]);
end;
ende := GetTickCount;
Writeln('Zeit Komma in Punkt:', Ende-Start);
readln;
end.
Nun ist leider das Ausgangstestmaterial nicht besonders gut. Es gibt nämlich kein Komma. Also wird auch nichts geändert.
Ändern wir mal die Erzeugung des Arrays ab:
Code: Alles auswählen
for i := 0 to max do begin
strArray[i] := FloatToStr(Random * 1000000) + ',' + FloatToStr(Random * 1000000);
end;
Software, Bibliotheken, Vorträge und mehr: https://www.ypa-software.de
-
- Beiträge: 2013
- Registriert: Do 16. Okt 2008, 10:22
- OS, Lazarus, FPC: Linux,Windows,FreeBSD,(MSEide+MSEgui 4.6,git master FPC 3.0.4,fixes_3_0)
- CPU-Target: x86,x64,ARM
Re: Im Editfeld eingabe: 34.56 -> absturz
Solche Dinge machen doch immer wieder Spass! 
KommaInPunkt() verändert auch den Ursprungsstring was StringReplace() nicht macht. Dafür ist beim Aufruf von StringReplace() glaube ich ',' und '.' vertauscht, so dass es nicht viel zu tun gibt. MSEgui hat auch entsprechende Funktionen. Ich habe sie neu für Free Pascal optimiert, vorher waren sie für Delphi optimal. replacechar() bringt eine Kopie, replacechar1() arbeitet "in place". Der angepasste Test:

KommaInPunkt() verändert auch den Ursprungsstring was StringReplace() nicht macht. Dafür ist beim Aufruf von StringReplace() glaube ich ',' und '.' vertauscht, so dass es nicht viel zu tun gibt. MSEgui hat auch entsprechende Funktionen. Ich habe sie neu für Free Pascal optimiert, vorher waren sie für Delphi optimal. replacechar() bringt eine Kopie, replacechar1() arbeitet "in place". Der angepasste Test:
Code: Alles auswählen
program stringreplacetest;
{$ifdef FPC}{$mode objfpc}{$h+}{$endif}
{$ifdef mswindows}{$apptype console}{$endif}
uses
{$ifdef FPC}{$ifdef unix}cthreads,cwstring,{$endif}{$endif}
sysutils,strutils,msesysutils,mseformatstr,msenoise,msestrings;
const
max = 10000000;
function KommaInPunkt(AString:string):string;
var
i,l :integer;
begin
Result:= AString;
l:=Length(result);
if l>0 then for i:=1 to l do if result[i]=',' then result[i]:='.';
end;
var
start,ende: longword;
procedure printresult(const caption: string);
begin
writeln('Zeit '+caption+': '+ formatfloatmse((ende-start)/1000000,'0.0000 s'));
end;
var
i: integer;
s: string;
strArray:array[0..max]of string;
begin
for i := 0 to max do begin
strArray[i]:= inttostr(mwcnoise() div 32)+','+
inttostr(mwcnoise() div 32);
end;
WriteLn('Array filled.');
start := timestamp(); //micro seconds
for i := 0 to max do begin
s := Stringreplace(strArray[i],',','.',[rfReplaceAll]);
end;
ende := timestamp();
printresult('StringReplace');
start := timestamp();
for i := 0 to max do begin
s := KommaInPunkt(strArray[i]);
end;
ende := timestamp();
printresult('Komma in Punkt');
start := timestamp();
for i := 0 to max do begin
s := replacechar(strArray[i],',','.');
end;
ende := timestamp();
printresult('replacechar()');
start := timestamp();
for i := 0 to max do begin
replacechar1(strArray[i],',','.');
end;
ende := timestamp();
printresult('replacechar1()');
readln;
end.
Code: Alles auswählen
Array filled.
Zeit StringReplace: 11.1018 s
Zeit Komma in Punkt: 3.1805 s
Zeit replacechar(): 2.4412 s
Zeit replacechar1(): 0.7440 s
Array filled.
Zeit StringReplace: 11.0746 s
Zeit Komma in Punkt: 3.1850 s
Zeit replacechar(): 2.4376 s
Zeit replacechar1(): 0.7394 s
Array filled.
Zeit StringReplace: 11.1084 s
Zeit Komma in Punkt: 3.1870 s
Zeit replacechar(): 2.4370 s
Zeit replacechar1(): 0.7396 s
-
- Beiträge: 340
- Registriert: Di 12. Sep 2006, 08:57
- OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
- CPU-Target: xxBit
- Kontaktdaten:
Re: Im Editfeld eingabe: 34.56 -> absturz
Code: Alles auswählen
for i := 0 to max do begin
s := Stringreplace(strArray[i],'.',',',[rfReplaceAll]);
end;
Code: Alles auswählen
s := Stringreplace(strArray,'.',',',[rfReplaceAll]);
Grüße, Antrepolit
care only if your os is really burning
care only if your os is really burning
Re: Im Editfeld eingabe: 34.56 -> absturz
Dieser Thread driftet komplett ab.
Hab schon gar keine Lust mehr, zu den einzelnen Quatschbeiträgen Stellung zu nehmen.
Der letzte Beitrag von TE kromer war jedenfalls vorgestern um 14:21.
Hab schon gar keine Lust mehr, zu den einzelnen Quatschbeiträgen Stellung zu nehmen.
Der letzte Beitrag von TE kromer war jedenfalls vorgestern um 14:21.

-
- Beiträge: 323
- Registriert: Di 12. Apr 2011, 13:21
- OS, Lazarus, FPC: WinXP + VMWare Player mit Fedora14, L 1.1, FPC 2.7.1
- CPU-Target: 1core 1,8GHz 32Bit
- Wohnort: Fürth
- Kontaktdaten:
Re: Im Editfeld eingabe: 34.56 -> absturz
StringReplace ist ein sehr praktischer Einzeiler. Da braucht es keine Schleife mehr.
-
- Beiträge: 6910
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Im Editfeld eingabe: 34.56 -> absturz
Es wurde noch was wichtiges übersehen wen die Umwandlung in DE und in CH funktionieren soll muss man zuerst den Decimalseperator prüfen.Gibt es eine Möglichkeit, dass das Programm bei keiner Variante abstürzt, also weder bei einer Kommazahl noch bei einer durch Punkt getrennten Zahl?
Code: Alles auswählen
function GetDeci(const s: string): string;
begin
Result := s;
if DecimalSeparator = '.' then begin
Result := StringReplace(Result, ',', '.', [rfReplaceAll]);
end else if DecimalSeparator = ',' then begin
Result := StringReplace(Result, '.', ',', [rfReplaceAll]);
end;
end;
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
Re: Im Editfeld eingabe: 34.56 -> absturz
Am besten, ohne StringReplace etc., mit den FormatSettings; allerdings darf der String keine Tausendertrennzeichen enthalten, die bei uns Punkte sind und sonst Kommas, also dem Dezimaltrennzeichen in die Quere kommen:Gibt es eine Möglichkeit, dass das Programm bei keiner Variante abstürzt, also weder bei einer Kommazahl noch bei einer durch Punkt getrennten Zahl?
Code: Alles auswählen
function ConvertStrToNumber(const AString: String; out Number: Double; out Msg: String): boolean;
var
fs: TFormatSettings;
begin
Msg := '';
Result := true;
// Konvertierungsversuch mit aktuellen Einstellungen
if TryStrToFloat(AString, Number) then
exit;
// Konvertierungsversuch mit geänderten Einstellungen (Punkt und Komma vertauscht)
fs := DefaultFormatSettings;
if fs.DecimalSeparator := '.' then fs.DecimalSeparator := ',' else fs.Decimal.Separator := '.';
if TryStrToFloat(AString, Number, fs) then
exit;
Result := false;
Msg := 'Der String "' + AString +'" ist keine gültige Zahl.';
end;
-
- Beiträge: 6910
- Registriert: Do 2. Jan 2014, 17:21
- OS, Lazarus, FPC: Linux (die neusten Trunk)
- CPU-Target: 64Bit
- Wohnort: Schweiz
Re: Im Editfeld eingabe: 34.56 -> absturz
Code: Alles auswählen
allerdings darf der String keine Tausendertrennzeichen enthalten, die bei uns Punkte sind und sonst Kommas, also dem Dezimaltrennzeichen in die Quere kommen:
Warscheinlich kommt das Ganze aus dem Office-Bereich.
Zum Glück ist wenigstens bei den Programmiersprachen der Dezimalseperator einheitlich.
Ich habe auch erst kürzlich erfahren, das die Deutschen die Dezimaltrennung mit einem ',' machen.
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot
Mit Java und C/C++ sehe ich rot
-
- Beiträge: 340
- Registriert: Di 12. Sep 2006, 08:57
- OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
- CPU-Target: xxBit
- Kontaktdaten:
Re: Im Editfeld eingabe: 34.56 -> absturz
Doch. Mann muss nur die korrekten Eingabeelemente wie z.B. TFlostSpinEdit verwenden.Mathias hat geschrieben:(...)
Irgendwie finde ich dies recht mühsam, warum hat man dafür nicht eine internationale Lösung ?
Es gibt fertige Lösungen. Doch irgendwie scheint jeder lieber seinen eigenen Spaghetti-Bastelcode ins Netz stellen zu wollen, der nicht fehlerfrei ist und auch nur Teile des problems löst, statt die fertige, korrekte Lösung verwenden zu wollen. Von daher hat Theo recht, dieser Thread driftet komplett ab.Mathias hat geschrieben: Warscheinlich kommt das Ganze aus dem Office-Bereich.
(...)
Grüße, Antrepolit
care only if your os is really burning
care only if your os is really burning
Re: Im Editfeld eingabe: 34.56 -> absturz
Wenn aber die Frage ist, wie man Punkt UND Komma als gültige Dezimaltrennzeichen ermöglichen kann (siehe erstes Posting --> kein Abdriften!), dann kann TFloatSpinEdit auch nicht helfen.Mann muss nur die korrekten Eingabeelemente wie z.B. TFlostSpinEdit verwenden.
-
- Beiträge: 340
- Registriert: Di 12. Sep 2006, 08:57
- OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
- CPU-Target: xxBit
- Kontaktdaten:
Re: Im Editfeld eingabe: 34.56 -> absturz
Das war nicht die Frage.wp_xyz hat geschrieben:(...)Wenn aber die Frage ist, wie man Punkt UND Komma als gültige Dezimaltrennzeichen ermöglichen kann (siehe erstes Posting --> kein Abdriften!), dann kann TFloatSpinEdit auch nicht helfen.
Die Frage war nach einer Variante, bei der das Programm nicht abstürzt. Und da solche Fehlermeldungen definitiv unnötig sind, da das Dezimalformat dem Benutzer ohnehin klar ist, schränkt man zugunsten der Usability direkt die Eingabe ein und erspart sich die (für den Bneutzer unnötige) Fehlermeldung. Dies mal TFloatSpinEdit, denn genau dafür wurde der Entwickelt. Den Rest könnt ihr nun verdrehen, durchdiskutieren und Spaghetti-Code-posten, wie ihr mögt. Fehlerfrei das, was hier an Code gepostet wurde ohnehin nicht, deshlab kann man sich das sparen.kromer hat geschrieben:Hallo,
bei der Eingabe einer Zahl mit einem Punkt als Dezimaltrennzeichen (z.B. 34.56) im Editfeld stürzt mein Programm ab.
Im Forum habe ich den DecimalSeperator gefunden und mit der Codezeile:kann man jetzt zwar 34.56 eingeben, dafür stürzt das Programm bei 34,56 ab.Code: Alles auswählen
DecimalSeparator := '.';
Gibt es eine Möglichkeit, dass das Programm bei keiner Variante abstürzt, also weder bei einer Kommazahl noch bei einer durch Punkt getrennten Zahl?
Wichtig: Ich will nur den Absturz verhindern, es soll bei 34.56 eine Fehlermeldung zeigen und bei 34,56 einfach normal rechnen. Es muss also nicht beide Varianten rechnen können.
Grüße, Antrepolit
care only if your os is really burning
care only if your os is really burning
Re: Im Editfeld eingabe: 34.56 -> absturz
Stimmt, hab vergessen das Thema auf gelöst zu setzen...theo hat geschrieben:Dieser Thread driftet komplett ab.
Hab schon gar keine Lust mehr, zu den einzelnen Quatschbeiträgen Stellung zu nehmen.
Der letzte Beitrag von TE kromer war jedenfalls vorgestern um 14:21.
