Test auf float-Werte mit try...catch - ist das ok?



  • In einem StringGrid stehen float-Werte, die der Benutzer eingegeben hat.
    Ob es auch wirklich float-Werte sind, teste ich so:

    for (int i = 0; i < z; i++)
    		for (int j = 0; j < s; j++)
    		{
    			try
    			{
    				StrToFloat(Form1->StringGrid1->Cells[j+1][i+1]);
    			}
    			catch (...)
    			{
    				Application->MessageBox("Fehlerhafter Wert in der Tabelle. ...);
    				goto ende;
    			}
    		}
        //kein Fehler, also weiter
        ...
        //Label für Fehler
        ende:
    

    Gibts daran etwas auszusetzen, oder ist das eine gute Vorgehensweise?



  • ich bin zwar keien borländerin, aber das goto stört mich ziemlich 😉



  • Du hast Recht. Man kann es auch mit return false/true machen.
    Aber der Test mit try...catch, ist der gesund oder ungesund?



  • Hallo,

    try & catch zu verwenden ist vollkommen richtig ... Anstatt dem goto würde ich aber auch eher das return Statement verwenden 🙂

    Gruß Skay


  • Mod

    Hallo

    warum machst du es denn nicht so:

    als Eingabe nur Zahlen,Punkt,Komma zulassen (Punkt und Komma deswegen, weil viele entweder oder eingeben)

    damit koenntest du dir diese Abpruefung sparen

    Ob das was du da machst richtig ist musst du wissen (zB. 3 -> Fehler ?)
    MfG
    Klaus



  • KlausB, aber was ist, wenn jemand eine Zelle leer lässt, oder aus Boshaftigkeit Buchstaben eingibt?
    Oder meintest du, schon während der Eingabe zu überprüfen, was der User in welcher Zelle eintippt? Das wäre doch ein wenig aufwändig, oder.



  • ich würde mich KlausB anschließen: eine try catch um eine eingabeprüfung ist etwas viel.
    warum nicht selber auf richtigkeit prüfen? (aber ich lasse mich gerne eines besseren belehren...)



  • Und wie unterbinde ich die Möglichkeit, in einem StringGrid die Eingabe von Buchstaben etc. zuzulassen, so dass nur . , 0..9 erlaubt sind?



  • Hm, eine Prüfung zur Laufzeit, ob ein Floatwert eingegeben wurde ist extrem aufwändig. Und funktioniert im Regelfall schon nicht mehr, wenn der böse, böse User etwas über die Zwischenablage einfügt (oder wird noch aufwändiger, wenn man das im Source berücksichtigt).
    Das try catch ist schon prima geeignet. Aber goto sollte man nicht verwenden.


  • Mod

    Hallo

    @Joe_m

    eine Prüfung zur Laufzeit, ob ein Floatwert eingegeben wurde ist extrem aufwändig

    extrem -> ein 4 Zeiler
    zwei if-Abfrage - mehr nicht
    (wegen Eingabe . und , um das ganze fuer alle Anwender bedienbar zu machen)

    (dazu gehoert natuerlich auch noch in OnExit die Anpassung der Anzeige 3 ->3.00 wenn ueberhaupt noetig)

    MfG
    Klaus



  • Marc++us' Sekretär schrieb:

    Und wie unterbinde ich die Möglichkeit, in einem StringGrid die Eingabe von Buchstaben etc. zuzulassen, so dass nur . , 0..9 erlaubt sind?

    Ich rate davon dringed ab. Nur eines ist nerviger für den Benutzer als die Eingabe auf bestimmte Tasten zu beschränken: Formatprüfung während der Eingabe.

    Wie bereits erwähnt, klemmst du damit wahrscheinlich auch die Zwischenablage ab. Zudem musst du noch - und e/E zulassen. Oder willst du dem Benutzer zumuten, 1e100 ausschreiben zu müssen?

    Außerdem bringt es einfach nichts. Die Beschränkung auf bestimmte Zeichen garantiert dir keine richtig formatierte Zahl. Beispiel: .2,.5-3,8ee-

    Jetzt könnte man darauf kommen, schon bei der Eingabe das Format der Zahl zu prüfen. Aber das finde ich, wie gesagt, noch schlimmer. Angenommen, ich will das Komma bei einer eingegebenen Zahl verschieben. Dann würde mich das Programm dazu zwingen, zuerst das alte Komma zu entfernen, bevor ich das neue setzen kann. Das nervt gewaltig.

    Bleib bei der Prüfung nach der Eingabe. Und bleib bei der fertigen Funktion.



  • @all:
    Danke, ich belasse es also erst einmal dabei, mit try...catch das gesamte Grid nach erfolgter Eingabe auf gültige floats zu testen.



  • Mit einem 4-Zeiler? Den möchte ich sehen... 😉

    Den brauch ich ja schon fast um das Dezimaltrennzeichen aus den Windows-Einstellungen zu lesen. 😉
    Ansonsten muß man auf - (eventuell auch +) an erster Stelle des 'Textes' prüfen, dann, je nach Dezimaltrennzeichen alle (überflüssigen) Punkte oder Kommas ingnorieren, prüfen, ob das Dezimaltrennzeichen nur einmal vokommt und ob der Rest nur aus Zahlen besteht. Das Ganze kann dann nur noch in der OnChange des Edits (oder was auch immer) gemacht werden, da sonst wieder das Einfügen der Zwischenablage nicht überprüft werden kann. Aber hier ist es dann nicht mehr so einfach ein Zeichen zu 'verwerfen'.

    EDIT: Ups, ich sollte mir beim posten wohl nicht so viel Zeit lassen, der letzte Beitrag, den ich gelesen hatte, war der von KlausB...



  • Also ich hab' mal so einen Test gemacht:

    void __fastcall TForm1::ParamCheck(TObject *Sender)               //Testet, ob Eingabewert gueltig ist
    {
      static Checking=false;
      AnsiString AS;
      double Value;
      TEdit *Edit;
      Edit=(TEdit*)Sender;                                            //zu testendes Edit
      if (!Checking)                                                  //keine Rekursionen!!!
      {
        Checking=true;
        try
        {
          AS=Edit->Text;                                              //String fuer Debugger
          Value=Edit->Text.ToDouble();                                //Wert aus Eingabe
          Edit->ClearUndo();                                          //Rueckgaengig aus!
          Checking=false;
        }
        catch(EConvertError &e)                                       //bei Konvertierungsfehler - falsche Zeichen
        {
          Edit->Undo();                                               //Rueckgaengig
          Checking=false;
        }
      }
      else
        Edit->ClearUndo();                                            //Rueckgaengig aus!
    }
    

    Diese Funktion rufe ich in jedem TEdit bei OnChange auf!

    Bei Fehleingaben wird sofort!!! korrigierend eingegriffen!
    Das kann noch mit nem Peep oder ner Message erweitert werden.



  • DerAltenburger schrieb:

    Diese Funktion rufe ich in jedem TEdit bei OnChange auf!

    Bei Fehleingaben wird sofort!!! korrigierend eingegriffen!

    Das meinte ich. Bei einem Programm, das mich derart bevormundet, suche ich innerhalb kürzester Zeit nach einem Button mit der Aufschrift "ICH WAR NOCH NICHT FERTIG!". Warum muss, wenn ich den Inhalt eines Eingabefeldes ändere, jeder einzelne Zwischenschritt der Änderung ein gültiges Format haben?

    Das kann noch mit nem Peep oder ner Message erweitert werden.

    Das setzt dem Ganzen noch eins drauf. Was würdest du von einer Entwicklungsumgebung halten, die bei jeder Änderung im Quelltext eine Syntaxprüfung macht und dich mit einer MessageBox auf Fehler hinweist?



  • Sehe ich genauso. Wenn überhaubt, dann würde ich die Eingabe auf 0..9 "," "." "e" "E" beschränken und eine endgültige Gültigkeitsprüfung am ende machen. Alles andere ist nur nervig.



  • Nun ja, ich bin der Meinung, dass die Vorgehensweise vom Umfeld abhängt. Grundsätzlich stimme ich MFK zu: Keine Überprüfung in der OnChange() (es sei denn um den Button zum Verlassen des Forms zu deaktivieren...).

    Wenn auf dem Form grundsätzlich in allen Feldern nur Zahleneingaben gemacht werden dürfen, macht es vielleicht noch Sinn, die Eingabe zu beschränken. Wenn es aber auch reine Textfelder gibt, mache ich überhaupt keine Einschränkung. Dann kann der User, wenn er sich im Feld vertan hat noch mit Cut and Paste arbeiten. Ich mache das normalerweise ohne irgendeine Beschränkung bei der Eingabe und prüfe in der OnExit(), ob ein gültiger Wert eingeben wurde. Ich habe allerdings auch Eingabemasken, da wird erst bei dem Versuch das Formular zu verlassen (oder was mit den Daten zu machen) eine Prüfung für alle Werte durchgeführt. Dies macht zum Beispiel Sinn, wenn sich Eingaben gegenseitig ausschließen, man aber nicht für jede Änderung in einem Feld alle abhängingen Komponenten (egal ob Edit oder ListBox usw) neu initialisieren möchte oder kann.



  • MFK schrieb:

    DerAltenburger schrieb:

    Diese Funktion rufe ich in jedem TEdit bei OnChange auf!

    Bei Fehleingaben wird sofort!!! korrigierend eingegriffen!

    Das meinte ich. Bei einem Programm, das mich derart bevormundet, suche ich innerhalb kürzester Zeit nach einem Button mit der Aufschrift "ICH WAR NOCH NICHT FERTIG!"...

    Das hat doch mit "Bevormunden" nichts zu tun! Das vermeidet doch nur Fehleingaben - OHNE dass sich der User darum kümmern muss!

    PS:
    Diese Kontrollroutine nutze ich natürlich nur bei TEdits fuer Dezimalzahleingabe!
    Für allgemeine Eingaben ist das VÖLLIG unbrauchbar. Aber um Zahleneingaben ging es ja wohl in dem Thread.



  • DerAltenburger schrieb:

    Das hat doch mit "Bevormunden" nichts zu tun! Das vermeidet doch nur Fehleingaben - OHNE dass sich der User darum kümmern muss!

    Wirft ToDouble() bei einem String wie "1.000000.0" (also mit zwei Dezimaltrennzeichen) eine Exception? Falls ja, folgendes Beispiel:

    Ich habe in einem TEdit die Zahl 1000000.0 stehen und möchte daraus 1.0000000 machen. Ich würde das so machen, dass ich zuerst die Einfügemarke hinter die 1 setze, einen Punkt eingebe, dann mit der Ende-Taste nach hinten springe, ein Zeichen nach links gehe, und mit der Entfernen-Taste den hinteren Punkt lösche. Deine Fehleingabenvermeidungsfunktion lässt das aber nicht zu. Sie zwingt mich dazu, zuerst den Punkt hinten zu entfernen, bevor ich Punkt vorne eingeben kann.

    Das ist für mich Bevormundung des Benutzers, und auf jeden Fall ein Grund, diese Software nicht zu benutzen.

    Worauf ich hinaus will: Du kannst in OnChange nicht wissen, ob der Benutzer mit der Eingabe fertig ist. Und solange solltest du IMHO die Eingabe auch nicht auswerten.



  • MFK hat absolut recht. der Richtige Ort für so eine Routine ist OnExit...

    -junix


Log in to reply