Vorgehensweise bei falschen Parametern



  • Nukularfüsiker schrieb:

    Du brauchst keinen Fehlerindikator.

    if(a > 0)
        throw(AZuGrossException("A zu groß!"));
    

    Möchte aber das Programm danach nicht unterbrechen sondern dem Nutzer eine Möglichkeit geben es zu beheben, durch eingabe eines neuen Wertes oder zumindest durch einen Bericht wo was schiefgelaufen ist.



  • bool ok = false;
    do
    {
        try
        {
            eingabe_die_evtl_exception_wirft();
            ok = true;
        }
        catch(AZuGrossException& fehler)
        {
           ok = false;
        }
    } while(!ok)
    


  • Nukularfüsiker schrieb:

    Du brauchst keinen Fehlerindikator.

    if(a > 0) throw(AZuGrossException("A zu groß!"));
    

    Hab mich kurz durch exceptions durchgelesen... damit müsste es gehen, weil ich die Exception in der übergeordneten Schleife abfangen kann. Oder liege ich falsch?



  • Nukularfüsiker schrieb:

    bool ok = false;
    do
    {
        try
        {
            eingabe_die_evtl_exception_wirft();
            ok = true;
        }
        catch(AZuGrossException& fehler)
        {
           ok = false;
        }
    } while(!ok)
    

    Dankeschön!
    Hat mich super weitergebracht.



  • Wenn die Werte vom Benutzer eingegeben werden, dann solltest du diese Eingaben überprüfen, bevor du versuchst, ein Objekt mir sinnfreien Werten zu initialisieren. Es ist vermutlich nicht Aufgabe der Klasse A, Benutzereingaben zu überprüfen, sondern du benutzt die Klasse zu einem anderen Zweck, oder?



  • pumuckl schrieb:

    Wenn die Werte vom Benutzer eingegeben werden, dann solltest du diese Eingaben überprüfen, bevor du versuchst, ein Objekt mir sinnfreien Werten zu initialisieren. Es ist vermutlich nicht Aufgabe der Klasse A, Benutzereingaben zu überprüfen, sondern du benutzt die Klasse zu einem anderen Zweck, oder?

    Die Werte werden in diesem Teil aus einer Datei gelesen.
    Da diese auch manuell im klartext erstellt werden kann, möchte ich die fehler möglichst einfach abfangen.



  • waldfee schrieb:

    Die Werte werden in diesem Teil aus einer Datei gelesen.
    Da diese auch manuell im klartext erstellt werden kann, möchte ich die fehler möglichst einfach abfangen.

    Ob der Benutzer einen Wert in die Kommandozeile oder eine GUI oder eine Textdatei eingibt, die dann ausgelesen wird, ist egal. Nur sollte die Überprüfung der Richtigeit der Werte im Normalfall nicht von der Klasse ausgeführt werden, die mit den Werten arbeitet, sondern von der Klasse, die die Werte einliest (aus der Datei, der Konsole oder der GUI).

    Siehe auch "separation of concerns" und "single responsibility principle"



  • pumuckl schrieb:

    Ob der Benutzer einen Wert in die Kommandozeile oder eine GUI oder eine Textdatei eingibt, die dann ausgelesen wird, ist egal. Nur sollte die Überprüfung der Richtigeit der Werte im Normalfall nicht von der Klasse ausgeführt werden, die mit den Werten arbeitet, sondern von der Klasse, die die Werte einliest (aus der Datei, der Konsole oder der GUI).

    Siehe auch "separation of concerns" und "single responsibility principle"

    Ich habe es jetzt von der praktischen Seite gesehen. Diese Klasse wird in einigen Programmen verwendet und einfach dazugebunden. Dann müssten (die anderen) Basisprogramme ihr eigenes Süppchen bei der Parameterübergabe kochen.

    Ich glaube dass ich besser dran bin wenn ich dafür funktionen anbiete. Habe auch einen low-level Modus der keine Abfragen macht, falls es mal benötigt wird.



  • Wenn du derartiges Verhalten öfter brauchst, schlage ich eine Funktionsvorlage vor. In etwa

    #include <iostream>
    #include <sstream>
    #include <string>
    #include <tr1/functional>
    
    template<typename T> bool always_true(T const &) { return true; }
    
    template<typename T>
    T read_retry(std::string                         const &prompt    = "",
                 std::tr1::function<bool(T const &)> const &predicate = always_true<T>,
                 std::istream                              &in        = std::cin,
                 std::ostream                              &out       = std::cout)
    {
      std::istringstream parser;
      std::string line;
      T result;
    
      do {
        out << prompt;
        std::getline(in, line);
    
        parser.clear();
        parser.str(line);
        parser >> result;
      } while(!parser || !predicate(result));
    
      return result;
    }
    
    bool greater_than_zero(unsigned x) { return x > 0; }
    
    int main() {
      unsigned x = read_retry<unsigned>("Zahl > 0 eingeben: ", greater_than_zero);
      unsigned y = read_retry<unsigned>("Zahl eingeben: ");
    
      std::cout << x + y << std::endl;
    }
    
    // Ausgabe (Beispiel):
    //
    // Zahl > 0 eingeben: abc
    // Zahl > 0 eingeben: 0
    // Zahl > 0 eingeben: 2
    // Zahl eingeben: foo
    // Zahl eingeben: 3
    // 5
    


  • @ waldfee:
    Bitte nie Programmierfehler mit Exceptions behandeln. Damit sind Logikfehler gemeint, die bei einer korrekten Implementierung des Codes nicht vorkommen. Also Dinge wie

    strlen(NULL);
    

    Nimm assert in den Setter und du wirst sofort auf das Problem aufmerksam. Das kostet im Release-Modus auch keine Performance.

    Wenn dein Fehler hingegen ein Laufzeitfehler ist, der auch bei korrektem Code vorkommen kann (z.B. Datei konnte nicht geöffnet werden), nimm Exceptions. Auf so einen Fehler muss auch ein Release-Kompilat reagieren können. Aber hier denke ich wie pumuckl, dass die Benutzereingabe an anderer Stelle zuerst geprüft werden sollte.


Anmelden zum Antworten