#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int berechne(double, double, char, double *);
void fehlerBehandlung(int);

/*
 *	Funktion zur Berechnung
 *
 *	Eingabe-Parameter:
 *		od_1	1. Operand (Gleitkommazahl)
 *		od_2	2. Operand (Gleitkommazahl)
 *		reop	Rechenoperation als Zeichen
 *		erg		Ergebnisreferenz
 *
 *	Rückgabewert enthält die Fehlernummer:
 *		0	kein Fehler
 *		1	Division durch Null
 *		2	Wurzel nicht difniert
 *		3	unbekannte Rechenoperation
 */
int berechne(double od_1, double od_2, char reop, double * erg) {
	int fehler = 0;

	switch(reop) {

		case '+':	*erg = od_1 + od_2;
					break;

		case '-':	*erg = od_1 - od_2;
					break;

		case '*':	*erg = od_1 * od_2;
					break;

		case '/':	if (od_2 != 0.0)
						*erg = od_1 / od_2;
					else {
						fehler = 1;
						*erg = 0.0;
					}
					break;

		case 'w':	if (od_1 >= 0.0)
						*erg = sqrt(od_1);
					else {
					   fehler = 2;
					   *erg = 0.0;
					}
					break;

		case 's':	*erg = sin(od_1);
					break;

		case 'c':	*erg = cos(od_1);
					break;

		default:	fehler = 3;
					*erg = 0.0;
	}
	return fehler;
}

/*
 *	Funktion zur Fehlerbehandlung
 *
 *	Eingabe-Parameter:
 *		fehler	Fehlernummer
 */
void fehlerBehandlung(int fehler) {
	switch(fehler) {
		case 0: 	return;

		case 1:		printf("Divison durch Null ist nicht definiert.\n");
					break;

		case 2:		printf("Wurzel einer negativen Zahl ist nicht definiert.\n");
					break;

		case 3:		printf("Unbekannte Rechenoperation.\n");
					printf("(Erlaubt: +, -, *, /, w, s oder c)\n");
					break;

		default:	printf("Unerwarteter Fehler.\n");
	}
}

int main(void) {
	double operand_1 = 0.0, operand_2 = 0.0;
	double ergebnis = 0.0;
	char rechenoperation = '+';
	int fehler = 0;
	char ja_nein = 'j';

	/* Endlosschleife für Taschenrechner. */
	do {
		system("@cls||clear");

		/* Einlesen des ersten Operanden. */
		printf("\n1. Operand: ");
		fflush(stdin);
		scanf("%lf", &operand_1);

		/* Endlosschleife zur Eingabe der Rechenoperation. */
		do {
			printf("\nGueltige Rechonoperationen sind (+|-|*|/|w|s|c)");
			printf("\nRechenoperation: ");
			fflush(stdin);
			scanf(" %c", &rechenoperation);
		} while((rechenoperation != '+')
			&& (rechenoperation != '-')
			&& (rechenoperation != '*')
			&& (rechenoperation != '/')
			&& (rechenoperation != 'w')
			&& (rechenoperation != 's')
			&& (rechenoperation != 'c'));

		/* Falls Rechenoperation einen zweiten Operanden benötigt… */
		if ((rechenoperation == '+')
		|| (rechenoperation == '-')
		|| (rechenoperation == '*')
		|| (rechenoperation == '/')) {
			printf("\n 2. Operand: ");
			fflush(stdin);
			scanf("%lf", &operand_2);
		}

		/* Eigentliche mathematische Opration aufrufen. */
		fehler = berechne(operand_1, operand_2, rechenoperation, &ergebnis);

		/* Ergebnis oder Fehler ausgeben. */
		if (!fehler)
			printf("\n\nErgebnis: %lf\n", ergebnis);
		else
			fehlerBehandlung(fehler);

		/*
		 * Prüfen, ob noch eine Berechnung durchgeführt werden soll.
		 * (Hier keine Effizienzsteigerung durch BREAK, da wir sowieso am Ende
		 *  des Schleifenkörpers sind; es folgen also keine Anweisungen mehr.)
		 */	
		printf("\n\n\nNoch einmal? [j/n] ");
		fflush(stdin);
		scanf(" %c", &ja_nein);
	} while (ja_nein != 'n');

	/* Dem Betriebssystem die erfolgreiche Programmausführung zurückmelden. */
	return 0;
}
