Entwickler-Ecke

Sonstiges (Delphi) - String in Zahl umwandeln - OHNE Exception?


tempuss13 - Mi 24.02.10 22:45
Titel: String in Zahl umwandeln - OHNE Exception?
Hallo Delphi-Freunde!

Hab so einiges versucht, hänge hier fest.

Ich lese aus einer Datei div. Zeilen ein, hier sind Text und Datum(in Stringformat) abgelegt.
Wenn ich den 2-stelligen String in die entspr. Tageszahl umwandle, knallt mir immer eine Exception auf den Bildschirm.

In ca. 5 Fäleen von knapp 100 Zeilen steht, wo das Tages-Datum stehen sollte, z.B. <li>, wie auch immer das in die Datei gelangt.

Ich will solche Fehler abfangen, aber WIE???

Mit try und except klappt das nicht! Müsste ich noch einen Compilerschalter nutzen? Z.B. {$V-}?


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
procedure TForm1.Button1Click(Sender: TObject);
var
  done: boolean;
  i: integer;
  Dummy: string;
begin
repeat
      done := true;
      try
      for i := 0 to 780 do
          if strToInt(day[i]) > strToInt(day[i+1]) then
             begin
             Dummy := day[i];
             day[i] := day[i+1];
             day[i+1] := Dummy;
             done := false;
             end;
      except
      showmessage('KEINE Zahl!');
      end;
      until done;
end;

Alles klappt bestens, bis der Tag mit <li> kommt(bei ca. 300. Zeile).

Unter TP hab ich solche Probs nicht so in Erinnerung.
Für den richtigen Tip/Trick wäre ich wirklich dankbar!

Gruß Uli


der organist - Mi 24.02.10 22:51

versuch mal was mit StrToIntDef, da kannst du noch nen Parameter angeben, der zurückgegeben wird, wenns nen Fehler gibt. Wenn du da z.B -1 nimmst und dann auf -1 abfragst, weisst du, ob es gelaufen is oder nich. Zum andern gibts da imho noch Funktionen wie StrToInfExecpt, schlag mich nich, iwas gabs da, schau mal im Forum...........................................................


Delete - Mi 24.02.10 22:55

user profile icontempuss13 hat folgendes geschrieben Zum zitierten Posting springen:
Mit try und except klappt das nicht!

Wahnsinns Fehlerbeschreibung.


tempuss13 - Mi 24.02.10 23:15

Danke Dir erstmal!
Zwar erhalte ich mit mit StrToIntDef keine Fehlermeldung, dafür kommen astronomische Zahlen raus..
Ich versuche es eben weiter.

...
Was soll ich zu dem Fehler schreiben?
Es kommt eine Box mit 'Exception'.

Habe einen Screenshot davon als Datei angehängt.


Delete - Mi 24.02.10 23:24

Dann starte die Exe mal nicht aus der IDE.

Und hättest du das gleich gesagt, dann hätte man dich gleich darauf hinweisen können.


Xentar - Mi 24.02.10 23:25

Hast du mal in den Eingangswerten geschaut, ob da nicht doch li drin steht?
Ansonsten: Das ist nur eine Delphi Exception, start das Programm mal aus dem Explorer, dann taucht die nicht auf.


Chemiker - Mi 24.02.10 23:32

Hallo tempuss13,


ich habe Deine Frage nicht so ganz verstanden, aber vielleicht funktioniert Dein Vorhaben mit:


Delphi-Quelltext
1:
2:
TryStrToFloat(Text, Zahl)
 TryStrToDate(Text,Datum)

Bis bald Chemiker


tempuss13 - Mi 24.02.10 23:32

Hallo Luckie!

Ich denke wohl nicht so weit, um gleich alle interressanten Fakten aufzulisten.

Habe eben in der Exceptionenbox einen Haken gesetzt, unter:
"Diesen Fehler ignorieren"

Nun klappt es zwar, kein Absturz und der Exceptionblock wird abgearbeitet.
Aber das ist doch sicher keine saubere Lösung, oder?

In meinem Delphi-Buch steht ausdrücklich drin, dass bei Fehlern der Except-Block abgearbeitet wird.
Doch der wird garnicht erreicht.

Danke Dir!!!


Delete - Mi 24.02.10 23:47

user profile icontempuss13 hat folgendes geschrieben Zum zitierten Posting springen:
Nun klappt es zwar, kein Absturz und der Exceptionblock wird abgearbeitet.


Zitat:
Doch der wird garnicht erreicht.

Du widersprichst dir.


tempuss13 - Mi 24.02.10 23:54

Hallo Chemiker!

Was es alles für Befehle gibt!?
Habe 3 Delphi Bücher, in KEINEM steht sowas drin- traurig!
Auf jeden Fall versuche ich es damit auch noch.
Kann dabei ja nur lernen.

Alte TP-Bücher zeigen alle Befehle in Listenform oder ähnlich an.

Warum gibt es sowas nicht für Delphi??

Die Delphi-Bücher zeigen eher Beispiele auf,
doch fehlt so was wie eine Legende, ein Buch mit allen Delphi-Befehlen.
Vielleicht stelle ich mir das zu einfach vor.

Gruß Uli

---Moderiert von user profile iconNarses: Beiträge zusammengefasst---

Luckie BITTE!

Der Block wurde nicht erreicht, als ich den Ignorieren-Haken in der Exception-Meldung noch nicht gesetzt hatte!
Jetzt ist der Haken GESETZT!
Und jetzt wird der except-Block ABGEARBEITET!


Xentar - Do 25.02.10 00:02

Der Except Block wurde vorher auch abgearbeitet.. aber wenn man sein Programm aus Delphi heraus ausführt, hält Delphi trotzdem an.


tempuss13 - Do 25.02.10 00:05

Das ist auf jeden Fall ein wertvoller Hinweis!!!
Warum steht das in meinem Buch nicht drin??

DANKE Dir!


platzwart - Do 25.02.10 00:06

ALLE Delphi-Befehle??? Dann könntest du dir einen ganzen Aktenschrank anschaffen, nur um eine Auflistung unter zu bekommen.

Und die Exeption, die du gesehen hast, wird lediglich von der IDE ausgelöst bzw. dort angezeigt, um dir als Entwickler einen Hinweis zu geben. Du sollst nicht das Häkchen setzen, sondern die EXE aus dem Explorer heraus starten...


jfheins - Do 25.02.10 00:08

Kein Ahnung, was hast du denn für ein Buch?
Ich hatte "Jetzt lerne ich Delphi" (http://www.amazon.de/Jetzt-lerne-Delphi-Thomas-Binzinger/dp/3827267633/ref=sr_1_1?ie=UTF8&s=books&qid=1267049225&sr=8-1) - das hat mir eigentlich ganz gut geholfen :)

P.S.: Damit der except-Block abgearbeitet wird, muss man glaube ich auch Fortsetzen klicken - wenn du auf Anhalten klickt macht er natürlich genau das. Er hält an ;)


tempuss13 - Do 25.02.10 00:21

Nacheinander:

Wie ich schon schrieb: stelle mir das wohl zu einfach vor.

Und dass nur die IDE den Fehler zeigt, für den Programmierer und als Exe nicht, das wusste ich nicht.
In TP habe ich wirklich Erfahrung sammeln können.
Doch über Delphi muss ich ich noch viel lernen!

Das Buch, dass ich habe heißt: "Delphi 6 in Team"

DANKE Euch allen!


Gammatester - Do 25.02.10 00:24

user profile iconXentar hat folgendes geschrieben Zum zitierten Posting springen:
Der Except Block wurde vorher auch abgearbeitet..

Bei Floatingpoint-Exceptions wäre ich vorsichtig mit solchen Behauptungen, wenn ich das nicht selbst gesehen habe. Manche FPU-Exeptions werden, erst beim nächsten FPU-Befehl ausgelöst, und das kann uU meilenweit außerhalb des try except sein.

@tempuss13: wenn's mit TP geklappt, kannst Du ja auch unter Delphi Val(S; var V; var Code: Integer); benutzen und Code auswerten (hat allerdings den Nachteil, daß das Dezimaldings immer ein '.' ist).

Moderiert von user profile iconNarses: Überflüssige Zeilenumbrüche/Leerzeilen entfernt.


Xentar - Do 25.02.10 10:27

user profile iconGammatester hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconXentar hat folgendes geschrieben Zum zitierten Posting springen:
Der Except Block wurde vorher auch abgearbeitet..

Bei Floatingpoint-Exceptions wäre ich vorsichtig mit solchen Behauptungen, wenn ich das nicht selbst gesehen habe. Manche FPU-Exeptions werden, erst beim nächsten FPU-Befehl ausgelöst, und das kann uU meilenweit außerhalb des try except sein.

Ist mir bisher nicht (bewusst) untergekommen.
Über ein Beispiel würde ich mich freuen.


Gammatester - Do 25.02.10 14:44

user profile iconXentar hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconGammatester hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconXentar hat folgendes geschrieben Zum zitierten Posting springen:
Der Except Block wurde vorher auch abgearbeitet..

Bei Floatingpoint-Exceptions wäre ich vorsichtig mit solchen Behauptungen, wenn ich das nicht selbst gesehen habe. Manche FPU-Exeptions werden, erst beim nächsten FPU-Befehl ausgelöst, und das kann uU meilenweit außerhalb des try except sein.

Ist mir bisher nicht (bewusst) untergekommen.
Über ein Beispiel würde ich mich freuen.

Ein Beispiel, zwar nicht inhaltlich besonders interessant aber reproduzierbar für Delphi 5-7, Win98 und/oder XP:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Math;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

{$ifdef VER130}
const
  Nan = 0/0;  //Für Delphi 5
{$endif}


procedure TForm1.Button2Click(Sender: TObject);
begin
  Button2.Caption := FloatToStr(random);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  x: extended;
begin
  x := Nan;
  try
    if x<>x then Button1.Caption := 'x<>x';
  except
    Button1.Caption := 'Except';
  end;
end;

end.

Die Applikation ist ein Form mit 2 Buttons. Drückt man Button1 einmal, scheint sich nichts zu ändern, drückt man dann Button2 gibts eine "Invalid Floating point exception". Drückt man Button1 zweimal ändert sich Button1.caption zu 'Except'. Allgemein (aber nicht immer): Drückt man Button1 ein ungerade Zahl, dann Button2 gibts die Exception, bei gerader Anzahl nicht und Button2.caption zeigt eine neue Zufallszahl.


trm - Do 25.02.10 17:35

Hallo tempuss13,

wenn Du wirklich eine exeptionfreie Alternative suchst, rate ich Dir (weil ich das Problem kenne), den String, der zu überprüfen ist, Char für Char durchgehst und das Zeichen auf eine ziffer testest. Somit brauchst Du noch nicht einmal einen Try..Except - Block :)

Wer ASM gut kann, der könnte ja mal ein ASM-Beispiel mit Registern (?) posten. Würde mich auch interessieren.


Hier die NORMALE Vorgehensweise, welche in der IDE eine Schutzverletzung erzeugt, wenn es sich nicht um eine reine Zahlenfolge im String handelt:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
function Test_Integer(Dummy: string): Boolean;
begin

{ Testen, ob ein String komplett aus Ziffern besteht }
  Result := False;
  if Length(Dummy) < 1 then
    Exit;
  try
    StrToInt(Dummy);
  except
    Exit;
  end;
  Result:=True;
{ Testen, ob ein String komplett aus Ziffern besteht }

end;



Hier die Version, welche Char für Char prüft und bei INTEGER-Werten 100% keine Exeption auslöst:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
function TForm1.Test_Integer2(Dummy: string): Boolean;
var
  x: Integer;
begin

{ Testen, ob ein String komplett aus Ziffern besteht }
  Result := False;
  if Length(Dummy) < 1 then
    Exit;

  for x := 1 to Length(Dummy) do
    if not (ORD(Dummy[x]) in [48..57]) then
      Exit;

  Result := True;
{ Testen, ob ein String komplett aus Ziffern besteht }
end;




Gruß
~Mathias


Edit: Syntaxfehler bei for x := 1 to Length(Dummy) do (war for x:=0 vorher)


SvenAbeln - Do 25.02.10 18:00

user profile icontrm hat folgendes geschrieben Zum zitierten Posting springen:

wenn Du wirklich eine exeptionfreie Alternative suchst, rate ich Dir (weil ich das Problem kenne), den String, der zu überprüfen ist, Char für Char durchgehst und das Zeichen auf eine ziffer testest. Somit brauchst Du noch nicht einmal einen Try..Except - Block :)


Oder man verwendet einfach TryStrToInt


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TForm1.Button1Click(Sender: TObject);
var
  Zahl: integer;
begin
  if TryStrToInt(Edit1.Text, Zahl) then
  begin
  //  Hier dann Zahl verwenden
  end
  else
    showmessage('Error: Bitte eine Zahl eingeben');
end;


Chemiker - Do 25.02.10 20:31

Hallo,

hier ein Beispiel:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
unit DEMO_String_umwandeln;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TfrmDemoStringUmwandeln = class(TForm)
    edStringEingabe: TEdit;
    btStringUmwandeln: TButton;
    edStringAusgabe: TEdit;
    procedure btStringUmwandelnClick(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  frmDemoStringUmwandeln: TfrmDemoStringUmwandeln;

implementation

{$R *.dfm}

procedure TfrmDemoStringUmwandeln.btStringUmwandelnClick(Sender: TObject);
var
  strString: String;
  intZahl: integer;
  dbZahl: double;
  dtDatum: TDateTime;
begin
  strString:= edStringEingabe.Text;
  if TryStrToInt(strString, intZahl) then
  begin
    intZahl:= intZahl+2// Integer-Zahl wird um 2 erhöht
    edStringAusgabe.Text:= inttostr(intZahl);
  end
  else
  begin
    if TryStrToFloat(strString, dbZahl) then
    begin
      dbZahl:= dbZahl+ 44.01// Float-Zahl wird um 44.01 erhöht
      edStringAusgabe.Text:= floattostr(dbZahl);
    end
    else
    begin
      if TryStrToDate(strString, dtDatum) then
    begin
      dtDatum:= dtDatum - 1// Vom Datum wird ein Tag abgezogen
      edStringAusgabe.Text:= Datetostr(dtDatum);
    end
    else
    begin
      edStringAusgabe.Text:= strString; // sonst wird ein Text zurückgeben
    end;
  end;
 end;
end;

end.


Eingabe Ausgabe
10-> 12
12,1-> 56,11
30.12.2009-> 29.12.2009

Bei allen andern Eingaben wird der eingegeben String wieder zurückgegeben.

Bis bald Chemiker