C++ Kalenderformel richtig umsetzen, ungültige Daten ausschließen

-Firebat-

Lt. Commander
Registriert
Feb. 2007
Beiträge
1.029
Hallo Community !
Ich versuche mich momentan daran, mir zu einem angegebenen Datum den Wochentag anzeigen zu lassen. Hab mich ja schon ein bisschen eingegoogelt und auch in der Wikipedia gelesen. Dafür gibt's ja mehrere Möglichkeiten. Stichwort Gaußschen Kalendeformel oder Zellers Kongruenz. Ich hab versucht, das ganze (vorläufig) mit der Gaußschen Kalenderformel zu realisieren. Die Berechnung klappt auch ohne Probleme, allerdings rechnet das Programm auch mit ungültigen Daten wie dem 30.02.2008. Und das ist mein jetziges Problem. Wie bekomme ich das Programm dazu, nur mit gültigen Daten zu rechnen? Sollte das "zu viel Aufwand" sein, kann ich auch auf Zellers Kongruenz wechseln, aber da finde ich die Formel ganz schön kompliziert. Ich möchte ja auch verstehen, was ich da mache und nicht einfach Copy&Paste. Hier erstmal mein jetziger Code.

Code:
// Bestimmung des Wochentags durch Eingabe eines Datums inkl. Gueltigkeitspruefung nach der Gaussschen Kalenderformel
#include <iostream>

using namespace std;

int main()
{

	int w_tag=0,tag=0,monat=0,jahr=0;

    cout << "Bestimmung des Wochentags aus dem Datum mit Hilfe der Gaussschen Kalenderformel" << endl << endl;
    cout << "Bitte Tag (xx) eingeben : ";
    cin >> tag;
	cout << "Bitte Monat (xx) eingeben : ";
    cin >> monat;
    cout << "Bitte Jahr (xxxx) eingeben : ";
    cin >> jahr;

    int h = monat, k = jahr;

		if (monat < 3)
           {
				h = monat + 12;
                k = jahr-1;
           }

	w_tag = ((tag+2*h) + ((3*h+3)/5) + k + (k/4) - (k/100) + (k/400) + 1)%7;


    switch (w_tag)
           {
				case 0 : cout << "Sonntag";
                           break;
                case 1 : cout << "Montag";
                           break;
                case 4 : cout << "Donnerstag";
                           break;
                case 2 : cout << "Dienstag";
                           break;
                case 5 : cout << "Freitag";
                           break;
                case 3 : cout << "Mittwoch";
                           break;
                case 6 : cout << "Samstag";
                           break;
                default: cout << "ungueltige Eingabe";
			}


	cin.get();
	cin.get();
	return 0;
}

Ich wäre euch sehr dankbar, wenn da jemand mal drübergucken könnte und mir vielleicht erklären könnte, wie ich das programm dazu kriege, das datum vielleicht vorher auf Gültigkeit hin zu überprüfen. Danke. :)

Gruß Fusseltuch
 
Du solltest nach der Eingabe sowieso noch eine richtige Kontrolle einbauen, ob ein gültiges Datum eingegeben wurde. Momentan würde dein Programm auch den 40.40.4444444 akzeptieren.
Also musst du dich eh um eine Kontrolle kümmern, und dabei kannst du dann auch fix eine Schaltjahrkontrolle einbauen, das ist nicht allzu schwer.
 
Da ich in C++ aber erst einsteige wär es nett, wenn du das ein bisschen genauer erklären könntest. Ich weiß, dass sowas geht, aber weiter als switch/case und Schleifen bin ich leider noch nicht. Also ein wenig Nachsicht bitte ;-)

€dit: Ich brauche also etwas, was beim Tag nur die Zahlen 1 bis 31 akzeptiert, beim Monat nur die Zahlen 1 bis 12 und beim Jahr 1582 bis 3000 (das reicht mir zum ausprobieren). Ich hab jetzt zwar gelesen, wei man ermittelt, ob ein Jahr ein Schaltjahr ist oder nicht, aber ich bin mir noch nicht im klaren darüber, wie ich das ganze so zusammensetze bzw in mein Programm integriere, dass das alles funktioniert :(
 
Zuletzt bearbeitet:
Ich würde von der logischen Struktur her damit anfangen, das Jahr zuerst abzufragen, da hiervon das Schaltjahr abhängt. Oder du lässt die ganze Eingabe nochmal machen, falls das Datum ungültig ist. Danach den Monat eingeben lassen. Davon hängt nämlich ab, wieviele Tage du akzeptieren kannst. Oder du lässt die Reihenfolge so, mit dem Tag vor dem Monat und beschränkst dann die Monate, die dazu passen.
Das könnte man mit einem switch/case machen.
Also z.B. prüfe Tageingabe
>31 --> nur Jan., März, Mai, Juli, Aug, Okt. und Dez.
=30 --> alle bis auf Feb.
=29 --> alle bis auf Feb, wenn kein Schaltjahr (eigene Funktion...)
<29 --> alle

Bei den Jahren prüfst du auf > 1581 und < 3001.
Die Eingabe beschränken kannst du mit while Schleifen. So z.B.
Code:
while (tag <1 || tag > 31) {
        cout << "Bitte Tag (xx) eingeben : ";
        cin >> tag;
        if (tag < 1 || tag > 32)
                cout << "Eingabe ungültig"
}

Auf Schaltjahr prüfen kannst du auf ähnliche Weise, nur müssen hier mehrere Bedingungen beachtet werden.

  • Alle Jahre, die durch 4 ohne Rest teilbar sind, sind Schaltjahre.
  • Alle Jahre, die durch 100 ohne Rest teilbar sind, sind keine Schaltjahre.
  • Alle Jahre, die durch 400 ohne Rest teilbar sind, sind wiederum Schaltjahre
Teilung ohne Rest erreichst du so: Rest = jahr % 400, if rest == 0...
 
Zurück
Oben