Datumalgorithmus



  • Hi,
    ich hab einen Algorithmus geschrieben um zu prüfen ob ein Datum gültig ist, und verbessert wenn es falsch war. Ist etwas unübersichtlich, und ehrlich gesagt ich weiß garnicht ob er richtig funktioniert (hab ein paar Daten getestet hat funktioniert). Könnt ihr mir vielleicht irgendwelche Tipps geben, wie man ihn verbessern könnte (damit es überschaubarer und effizienter wird).

    // Das höchste Datum in einem Monat
          int monthdays_[] = { 31,   // Januar
                         28,   // Februar
                         31,   // März
                         30,   // April
                         31,   // Mai
                         30,   // Juni
                         31,   // Juli
                         31,   // August
                         30,   // September
                         31,   // Oktober
                         30,   // November
                         31 }; // Dezember
    
    void Date::correctDate()
    {
    neustart:
       int result = checkDate(year_, month_, day_);
       switch( result ){
          case 3: // Falscher Tag und Monat
          nochmal:  /* Wird angesprungen, wenn der Tag falsch ist/war und falscher
                       Monat berechnet wurde. */
          case 2: // Falscher Monat
             year_ += int(month_ / 12);
             month_ = (12 + month_ % 12 ) % 12;
             if (result != 3) // Wenn nur Monat
                break;
          case 1: // Falscher Tag
             do{
                int daysDiff = abs(day_); // Differenzen sind positiv
    
                if (daysDiff <= monthdays[month_])
                   break;   // Jetzt ist der Tag richtig
                else {
                   if (day_ > 0){     // Tage werden addiert
                      day_ -= monthdays[month_];
                      ++month_;
                   }else{             // und hier subtrahiert
                      day_ += monthdays[month_];
                      --month_;
                   }
    
                   if ( (month_ < 0) || (month_ > 11) ){
                      result = 3;   // Damit der Tag wieder angepasst werden kann
                      goto nochmal; // Anspringen um den Monat zu korrigieren
                   }
                }
             }while(true);
       }
       if (result != 0)
          goto neustart;
    }
    


  • Bah! Ein goto!!!! 😡
    Pack doch den Teil nach neustart in ne eigene Funktion, dann kannst du dir das häßliche goto sparen.

    mfg
    Glamdring



  • In diesem Fall kann man das Goto lassen, auch wenn es nicht so schön ist.

    Soweit sieht auch alles richtig aus.



  • In diesem Fall sehe ich das goto eher als Fehler im Konzept. Das kann man viel eleganter lösen. Das äußere goto-Konstrukt kann ohne große Änderungen durch eine do/while-Schleife ersetzt werden. Und mit einem goto in ein case zu springen ist mehr als Spaghetti. Das könnte man mit einer Rekursion vermeiden.



  • Sieht wie eine C Funktion aus.

    In C++ würde man das anders lösen.

    etwa so:

    int res;
    while( (res=checkDate(...)) )
    {
      if(res & WRONG_DAY) correctDay();
      if(res & WRONG_MONTH) correctMonth();
    }
    

    und schon hätte man eine schönere Aufteilung. Wahrscheinlich geht es noch schöner - aber dieser Ansatz macht die Sache viel klarer.



  • Danke für die Beiträge, sorry dass ich nicht sofort antworten konnte, war paar Tage nicht zu Hause. Ich werde mich dann heute damit auseinandersetzen. Auf jeden Fall ist mir aufgefallen, dass der (gepostete) Algorithmus keine Schaltjahre beachtet.

    Glamdrink schrieb:

    Ein goto!!!!

    Da sind zwei gotos 😉

    MaSTaH schrieb:

    Und mit einem goto in ein case zu springen ist mehr als Spaghetti. Das könnte man mit einer Rekursion vermeiden.

    Mir ist aufgefallen, dass der Sprung zum Label "nochmal:" garnicht notwendig ist, wenn man

    ...
    if ( (month_ < 0) || (month_ > 11) )
    { 
       break;
    } 
    ...
    

    schreibt. Dann wird zwar checkDate() durchgelaufen aber wenigstens gibt es keine Rekursion.



  • Was ist an Rekursion schlecht? 🙂

    Ich für meinen Teil finde das sehr elegant.



  • Shade Of Mine schrieb:

    Sieht wie eine C Funktion aus.
    In C++ würde man das anders lösen.

    Was ist daran jetzt eigentlich mehr C++?
    Ich denke ein guter C-Programmierer hätte das auch so geschrieben.



  • gelöscht



  • Hem, gibts dafür nicht ne richtige Formel?



  • Mis2com schrieb:

    Was ist an Rekursion schlecht? 🙂

    Ich für meinen Teil finde das sehr elegant.

    Ich habe nicht behauptet dass eine Rekursion schlecht sei. Ist auf jeden Fall besser als break, aber was mir nicht gefällt ist, dass da der (unter Win98) stark begrenzte Heap-Speicher "belastet" wird. Bei dieser Funktion wird es vielleicht selten auftreten, aber die Möglichkeit ist gegeben.



  • bIce schrieb:

    Ich habe nicht behauptet dass eine Rekursion schlecht sei. Ist auf jeden Fall besser als break, aber was mir nicht gefällt ist, dass da der (unter Win98) stark begrenzte Heap-Speicher "belastet" wird.

    Ich finde Walnüsse sind besser als Äpfel!
    break mit Rekursion zu vergleichen ist nicht euer Ernst oder?

    Außerdem wird durch Rekursion nicht der Heap belastet sondern der Stack. Und der sollte für gewöhnlich groß genug sein.

    Aber nichtsdestotrotz ist es meistens sinnvoll nicht-rekursive Lösungen vorzuziehen, wenn sie nicht gerade deutlich komplexer sind.

    MfG Jester


Anmelden zum Antworten