#include<iostream>
using namespace std;

bool istSchaltjahr(int jahreszahl)
// Aufbau der Kopfzeile einer Funktion ist immer wie folgt:
// <Datentyp des Rückgabewerts> <Name der Funktion>(<Variablenliste>)
// Datentyp bool kann die Werte true und false annehmen
{
	if (jahreszahl % 4 == 0)
	{
		if (jahreszahl % 100 == 0)
		{
			if (jahreszahl % 400 == 0)
			{
				return true; // an dieser Stelle wird die Funktion
				// istSchaltjahr beendet und das Programm springt an die
				// Stelle zurück, an der istSchaltjahr aufgerufen wurde.
				// An der Stelle wird quasi der Aufruf istSchaltjahr(...)
				// durch den Wert ersetzt, der hier mittels return
				// zurückgegeben wird.
			}
			else
			{
				return false;
			}
		}
		else
		{
			return true;
		}
	}
	else // jahreszahl %4 != 0
	{
		return false;
	}
} // Ende istSchaltjahr


bool tageszahlOK(int tage, int tageImMonat)
// gibt true zurück wenn der Parameter tage zwischen 1 und tageImMonat liegt
{
	if (1 <= tage && tage <= tageImMonat)
	{
		return true;
	}
	else
	{
		return false;
	}
}

// Forward declaration - vorweggenommene/vorwärts Deklaration
// diese gibt dem Compiler an, dass es Funktion gibt,
// die den Namen xyz hat und die Parameter abc und def erwartet
int tageImMonat(int, int);
// bei Vorwärtsdeklarationen von Funktionen können wir die Variablennamen
// weglassen (diese werden vom Compiler (an dieser Stelle) ignoriert)
// Wenn dadurch an dieser Stelle der Sinn der Funktion verschleiert wird,
// sollten Sie die Variablennamen jedoch unbedingt angeben
// konkret: in diesem Beispiel hätte man die Variablennamen besser angeben sollen

bool datumIstGueltig(int tag, int monat, int jahr)
{
	if (1 <= monat && monat <= 12) // && verknüpft zwei boolsche Werte
		// in diesem Fall das Ergebnis des Vergleichs 1 <= monat und
		// das Ergebnis des Vergleichs monat <= 12
		// das Ergebnis ist wahr, wenn beide Vergleich sich zu wahr auswerten
	{
		if (tageszahlOK(tag,tageImMonat(monat,jahr)))
		{
			return true;
		}
		else
		{
			return false;
		}
	} // Monat liegt zwischen 1 und 12
	else
	{
		return false;
	}
}


int tageImMonat(int monat, int jahr)
// Eingabe: eine Monatszahl, eine Jahreszahl
// Ausgabe: 28/29/30/31 bei gültigen Kombinationen, 31 sonst
{
	if (monat == 2)
	{
		if (istSchaltjahr(jahr))
		{
			return 29;
		}
		else
		{
			return 28;
		}
	} // Ende Februar
	else if (monat == 4 || monat == 6 || monat == 9 || monat == 11)
		// das || ist eine logische ODER-Verknüpfung
		// wertet sich zu wahr aus, wenn wenigstens ein Operand wahr ist
	{
		return 30;
	}
	else // es ist ein Monat mit 31 Tagen
	{
		return 31;
	}
}

void ausgabeDatumIstGueltig(void)
// nur als Beispiel für eine Funktion ohne Parameter und ohne Rückgabewert
{
	cout << "Das Datum ist gueltig!" << endl;
}

void ausgabeDatumIstNichtGueltig(void)
// nur als Beispiel für eine Funktion ohne Parameter und ohne Rückgabewert
{
	cout << "Das Datum ist nicht gueltig!" << endl;
}

int anzahlDerTageSeitJahresanfang(int tag, int monat, int jahr)
{
	// die Prüfung, ob das Datum tag.monat.jahr gültig ist, wird hier nicht überprüft
	// Rückgabewert: bei gültigem Datum die Anzahl der Tage seit dem 1.1.jahr
	// bei unklarer Sachlage, immer angeben, was genau passiert, hier z.B.
	// Rückgabewert beim 1.1.jahr = 1
	int mm;
	int anzDerTage = 0;
	for (mm = 1; mm < monat; mm = mm + 1)
	// zur Erinnerung: for (Initialisierung; Abbruchbedg.; Inkrement)
	// Beachte: ist die Bedingung schon zu Beginn verletzt, wird die Schleife
	// garnicht betreten, sondern gleich bei der zugehörigen "}" fortgesetzt
	{
		anzDerTage = anzDerTage + tageImMonat(mm, jahr);
	}
	anzDerTage = anzDerTage + tag;
	return anzDerTage;
	// Argumente für/wider for (int xyz= ...) oder int xyz; for (xyz= ...)
	// - im ersten Fall gilt das xyz nur bis zum Ende der for-Schleife
	// - im zweiten Fall auch danach
	// Problematik: so sollte es sein, aber nicht alle Compiler halten sich dran
	// deshalb: keine Variablendeklaration im Initailisierungsteil der for-Schleife
}

int anzahlDerTageZwischenAundB(int tagA, int monatA, int jahrA, int tagB, int monatB, int jahrB)
// liefert für zwei Datumsangaben A und B die Anzahl der Tage zwischen A (exkl.) und B (inkl.)
{
	int anzDerTage = 0;
	if (jahrA == jahrB)
	{
		anzDerTage = anzahlDerTageSeitJahresanfang(tagB,monatB,jahrB)
			       - anzahlDerTageSeitJahresanfang(tagA,monatA,jahrA);
		return anzDerTage;
	}
	else if (jahrA < jahrB)
	{
		int jj;
		if (istSchaltjahr(jahrA))
		{
			anzDerTage = 366 - anzahlDerTageSeitJahresanfang(tagA,monatA,jahrA);
		}
		else
		{
			anzDerTage = 365 - anzahlDerTageSeitJahresanfang(tagA,monatA,jahrA);
		}
		for (jj = jahrA + 1; jj <= jahrB - 1; jj = jj + 1)
		{
			if (istSchaltjahr(jj))
			{
				anzDerTage = anzDerTage + 366;
			}
			else
			{
				anzDerTage = anzDerTage + 365;
			}
		}
		anzDerTage = anzDerTage + anzahlDerTageSeitJahresanfang(tagB,monatB,jahrB);
		return anzDerTage;
		// noch selbst einfügen, was passiert, wenn die Monate/Tage voreinander liegen
	}
	else // jahrA > jahrB
	{
		// return 0; // nur, weil's jetzt schnell geht, nicht, weil es hübsch ist
		return - anzahlDerTageZwischenAundB(tagB,monatB,jahrB,tagA,monatA,jahrA);
		// eine Möglichkeit
	}
}

int wochentagAmDatum(int tag, int monat, int jahr)
// 15.10.1582, Freitag, war Beginn des Gregorianischen Kalenders
// Ausgabe soll sein: 1 für Montag, 2 für Dienstag, ..., 7 für Sonntag
{
	int abFreitagGerechnet = anzahlDerTageZwischenAundB(15,10,1582,tag,monat,jahr)%7;
	return ((abFreitagGerechnet+4)%7)+1;
}

void ausgabeWochentag(int wotag)
// gibt bei wotag==1 Montag aus, bei 2 Dienstag, etc. bei außerhalb 1-7 undefiniert
{
	if (wotag == 1)
	{
		cout << "Montag";
	}
	else if (wotag == 2)
	{
		cout << "Dienstag";
	}
	else if (wotag == 3)
	{
		cout << "Mittwoch";
	}
	else if (wotag == 4)
	{
		cout << "Donnerstag";
	}
	else if (wotag == 5)
	{
		cout << "Freitag";
	}
	else if (wotag == 6)
	{
		cout << "Samstag";
	}
	else // sollte (wotag == 7)
	{
		cout << "Sonntag";
	}
}



int main(void)
{
	int tag, monat, jahr; //, tagB, monatB, jahrB;

    //Aufgabe: die Eingabe des Datums soll solange 
	//wiederholt werden, bis ein gültiges Datum eingegeben wurde

//	do
//	{
//		cout << "Gib bitte einen Tag Monat und Jahr ein: ";
//		cin >> tag >> monat >> jahr;
//	} while (!(datumIstGueltig(tag,monat,jahr)));
	// !(<Ausdruck>) ist dieser Ausdruck wahr, wenn <Ausdruck> falsch ist, und umgekehrt
	// Die Struktur einer bedingten Schleife (fußgesteuert) ist immer(!)
	// do
	// {
	//		<Anweisung 1>
	//		<Anweisung 2>
	//		...
	// } while (<Boolscher Ausdruck>);
	// Wenn eine Schleife wiederholt werden soll, bis etwas gilt, lautet die letzte Zeile
	// } while (!(<Boolscher Ausdruck));

//	cout << "Gib bitte einen Tag Monat und Jahr ein: ";
//	cin >> tag >> monat >> jahr;
//  while (!(datumIstGueltig(tag,monat,jahr)))
//	{
//		cout << "Das war kein gueltiges Datum!" << endl
//			 << "Gib bitte nochmal einen Tag Monat und Jahr ein: ";
//		cin >> tag >> monat >> jahr;
//	}
	// wird die Bedingung wie hier zu Beginn abgefragt, spricht man von kopfgesteuerten Schleifen
    // while (<Boolscher Ausdruck>)
	// {
	//		<Anweisung 1>
	//		<Anweisung 2>
	//		...
	// }

	// geht das auch mit for-Schleifen?
	// zur Erinnerung: for (<Initialisierung>;<Abbruch>;<Inkrement>) { <Anweisung> }
	// for-Schleife ist lediglich eine Abkürzung:
	// {
	//		<Initialisierung>
	//		while (<Abbruch>)
	//		{
	//			<Anweisung>
	//			<Inkrement>
	//		}
	// }
//	for( ;(!(datumIstGueltig(tag,monat,jahr))); )
//	{
//		cout << "Das war kein gueltiges Datum!" << endl
//			 << "Gib bitte nochmal einen Tag Monat und Jahr ein: ";
//		cin >> tag >> monat >> jahr;
//	}
// ist das sinnvoll?
	// es tut, aber:
	// for-Schleifen sind Zählschleifen, bei denen man i.A. vorher wissen sollte,
	// wie oft diese durchlaufen werden!
	// Idee: es gibt verschiedene Arten von Schleifen, weil in der Praxis verschiedene
	// Arten benötigt werden
	// deshalb (zur Lesbarkeit): for-Schleifen immer zum Zählen
	// bedingte Schleifen (while / do..while), wenn die Anzahl der Durchläufe vorher unbekannt ist

//Fazit: sinnvollste Variante oben ist: do...while (außer, wenn man beim ersten Mal einen
	// anderen Text haben möchte -> man will ... also doch eher ... while(..) ...

	//cout << "Gib bitte noch einen Tag Monat und Jahr ein: ";
	//cin >> tagB >> monatB >> jahrB;

	//if (datumIstGueltig(tag,monat,jahr))
	//{
	//	ausgabeDatumIstGueltig();
	//}
	//else
	//{
	//	ausgabeDatumIstNichtGueltig();
	//}

	//cout << "Tage seit dem " << tag << "." << monat << "." << jahr
	//	 << " = " << anzahlDerTageSeitJahresanfang(tag,monat,jahr) << endl;

    //cout << "Tage zwischen dem " << tag << "." << monat << "." << jahr
	//	 << " und dem " << tagB << "." << monatB << "." << jahrB << " sind "
	//	 << anzahlDerTageZwischenAundB(tag,monat,jahr,tagB,monatB,jahrB) << endl;

//	cout << "Der "  << tag << "." << monat << "." << jahr << " ist ein ";
//	ausgabeWochentag(wochentagAmDatum(tag,monat,jahr));
//	cout << endl;

	int zahl;
	cout << "Gib eine Zahl ein: ";
	cin >> zahl;

// unten geht's weiter

//	do
//	{
//		cout << "Die vorherige Stelle ist eine " << zahl%2 << endl;
//		zahl = zahl / 2; // der evtl. auftretende Nachkommaanteil entfällt automatisch,
//		// bei Ganzzahldivision wird in C/C++ IMMER abgerundet
//	} while (zahl>=1);
//	while (zahl>=1)
//	{
//		cout << "Die vorherige Stelle ist eine " << zahl%2 << endl;
//		zahl = zahl / 2;
//	}
	// Fazit bis hierhin: beides tut, welche Variante ist richtig?
	// Dies führt uns auf die Frage: was sind hier sinnvolle Testfälle
	// -> 42
	// -> 64
	// -> 63
	// -> 0
// Fazit: do .. while ist richtig, das stellt man entweder fest durch vorausschauende Planung
	// oder durch Eingebung
	// oder Talent
	// oder durch Erfahrung
    // oder durch Testen

	// Aufgabe (Einführung von Arrays)
	// Idee: speichere die Ziffern zunächst alle ab und gebe diese dann in umgekehrter Reihenfolge aus#
	// es wird eine Struktur benötigt, die mehrere Ziffern abspeichern kann!

	int zahlen[10]; // so etwas deklariert ein Array Zahlen, das aus 10 int-Variablen besteht
	// der Zugriff geschieht durch zahlen[<Index>], wobei Index zwischen 0 und 9 liegt

	int index = 0; // Index zeigt jeweils auf das als nächstes zu füllende Element im Array
	do
	{
		zahlen[index] = zahl%2;
		index = index +1;
		zahl = zahl / 2; // der evtl. auftretende Nachkommaanteil entfällt automatisch,
		// bei Ganzzahldivision wird in C/C++ IMMER abgerundet
	} while (zahl>0);
    // an dieser Stelle ist nun das Array (zu deutsch: Feld) von Index 0 bis (index-1) gefüllt
	// diese Ziffern sollen nun in umgekehrter Reihenfolge wieder ausgegeben werden
	// welche Schleifenart? und warum? for, weil die Anzahl der Durchläufe jetzt bekannt ist
	int i;
	for (i = index-1; i>=0 ; i = i-1)
	{
		cout << "Die naechste Ziffer ist die " << zahlen[i] << endl;
	}

	return 0;
}