gültigkeit der fuktionen.



  • Ich glaube er meint es eher so

    int funtion()
    {
        if(/*Bedingung*/)
        {
            tu_etwas();
            return 1;
        }
        else
            return -1;
    }
    
    int main()
    {
        int var = funktion();
        if(var == -1)
            return 0;
    }
    


  • Dravere schrieb:

    @samsonitex,
    Versteh ich dich dich richtig, dass bei folgendem Code bei dir eine 0 auf der Konsole ausgegeben wird?

    So wie ich ihn verstanden habe, gibt er den Rückgabewert von einer seiner Funktionen aus. Und die Funktion soll main() nichts zurückgeben, sondern direkt beenden...

    samsonitex schrieb:

    hab das jetzt mal so gemacht, aber:

    Vielleicht noch Argumente übergeben, zum Beispiel eine 0. 😉


  • Administrator

    samsonitex schrieb:

    was nun?

    Auf den Link klicken, welcher dir Nexus gegeben hat. Ich schreibe ihn mal ausgeschrieben hin:
    http://www.cplusplus.com/reference/clibrary/cstdlib/exit.html

    Jetzt Augen aufmachen und den Text dort lesen. Dann hast du gute Chancen, dein Problem in den Griff zu bekommen.

    Eine Antwort auf meinen Post wäre aber auch nicht schlecht 🙂

    Grüssli



  • Dravere schrieb:

    @samsonitex,
    Versteh ich dich dich richtig, dass bei folgendem Code bei dir eine 0 auf der Konsole ausgegeben wird?

    int main()
    {
      return 0;
    }
    

    Dann kannst du ziemlich wenig von C++ her machen, da dies eine Sache des Betriebsystem ist, welches den Exitcode des Programmes nach dessen Ausführung auf der Konsole ausgibt. Habe allerdings noch nie davon gehört, dass ein OS sowas macht ...

    Grüssli

    hallo.

    nein.

    nicht wenn das programm ganz normal beendet wird. nur wenn ich es vorzeitig durch return 0; beende. bsw. in einer if - else anweisung. wenn ich zum beispiel sage:

    "möchten sie forfahren"
    [ja] oder [nein]
    
    if (ja)
       {fortfahren}
    
    else 
       { return 0;}
    

    mal vereinfacht dargestellt


  • Administrator

    @samsonitex,
    Kannst du mal einen vollständig lauffähigen Beispielcode zeigen, welcher dieses Verhalten auslöst? Ich finde das irgendwie sehr seltsam und denke das Problem liegt womöglich eher woanders.

    Der Beispielcode sollte kurz, knapp und klein sein, aber kompilierbar 😉

    Grüssli



  • klein halten kann ich ihn leider nicht, da ich mich wie gesagt nicht sehr gut mit c++ auskenne und nicht weiß, ob es am system oder am code liegt.
    außerdem habe ich verschiede stellen im code an denen das programm vorzeitig beendet werden soll, falls eine bedingung nicht zutrifft. also wenns nichts ausmacht, poste ich hier mal den gesamten code.

    ist bloß ein relativ kleines programm.
    einfaches rechenprogramm:

    ich poste es einfach mal.
    aber vorab nochmal: ich bin anfänger. ihr hättet das sicher viiiieeeel besser gelöst als ich. es war eine übung für mich. es befinden sich alle von mir bis jetzt erlernten dinge von c++.

    also nicht lachen. 😉

    Ihr könnt das programm auch gleich mal n bißchen testen und mid feedback geben. würd mich freuen.

    Zuerst einmal der selbstgeschriebene Header:

    #ifndef _STDCALC_H__
    #define _STDCALC_H__
    
    double add (double a, double b)
    {
    	return a + b;
    }
    
    double sub (double a, double b)
    {
    	return a - b;
    }
    
    double multi (double a, double b)
    {
    	return a * b;
    }
    
    double div (double a, double b)
    {
    	return a / b;
    }
    
    #endif
    

    jetzt der code:

    #include <iostream>
    #include <string>
    #include "stdcalc.h"
    
    using namespace std;
    int error ();
    
    double repeat (double& erste, double& zweite)
    {
    	cout << endl << endl;
    	cout << "[" << erste << "] und [" << zweite << "] miteinander" << endl;
    	cout << endl << endl;
    	cout << "<A>ddieren" << endl;
    	cout << "<S>ubtrahieren" << endl;
    	cout << "<M>ultiplizieren" << endl;
    	cout << "<D>ividieren" << endl;
    	char c;
    	cin >> c;
    	switch (c)
    	{
    	case 'a' : cout << endl << endl << "[" << erste << "] + [" << zweite << "] = " << add (erste, zweite); break;
    		cout << endl;
    	case 's' : cout << endl << endl << "[" << erste << "] - [" << zweite << "] = " << sub (erste, zweite); break;
    		cout << endl;
    	case 'm' : cout << endl << endl << "[" << erste << "] * [" << zweite << "] = " << multi (erste, zweite); break;
    		cout << endl;
    	case 'd' : cout << endl << endl << "[" << erste << "] / [" << zweite << "] = " << div (erste, zweite); break;
    		cout << endl << endl;;
    	default : cout << endl <<"Sie haben sich vertippt." << endl;
    		cout << "M\x94" << "chten Sie es erneut versuchen, oder das Programm beenden?" << endl;
    		cout << endl <<"<F>ortfahren oder <B>eenden  ";
    		char d;
    		cin >> d;
    		switch (d)
    		{
    	case 'f' : cout << repeat (erste, zweite); break;
    	case 'b' : return 0;
    	default : cout << error ();
    		}
    	}
    	cin.get();
    	return 0 ;
    }
    int neben ();
    
    int error ()
    {
    	cout << "Sie haben sich vertippt" << endl;
    			cout << "M\x94" << "chten Sie es erneut versuchen, oder das Programm beenden?" << endl;
    			cout << endl <<"<F>ortfahren oder <B>eenden  ";
    			char e;
    		cin >> e;
    		switch (e)
    		{
    	case 'f' : cout << neben (); break;
    	case 'b' : return 0;
    	default : cout << error ();
    		}
    		return 0;
    }
    int error2()
    {
    	cout << endl << endl << "M\x94" << "chten Sie eine weiter Rechnung durchf\x81hren?" << endl;
    	cout << "<Ja> oder <Nein> :  ";
    	string ans;
    	cin >> ans;
    	if (ans == "ja")
    	{
    		cout << neben ();
    	}else
    	{
    		if (ans == "nein")
    		{
    			return 0;
    		}else
    		{
    			cout << "Sie haben sich vertippt" << endl;
    			cout << "M\x94" << "chten Sie es erneut versuchen, oder das Programm beenden?" << endl;
    			cout << endl <<"<F>ortfahren oder <B>eenden  ";
    			char e;
    		cin >> e;
    		switch (e)
    		{
    	case 'f' : cout << neben (); break;
    	case 'b' : return 0;
    	default : cout << error ();
    		}
    		}
    	}
    		cin.get();
    		cin.get();
    		return 0;
    }
    int neben ()
    {
    	cout << endl << endl;
    	cout << "Geben Sie bitte die erste Zahl ein: ";
    	double erste, zweite;
    	cin >> erste;
    	cout << "Geben Sie bitte die zweite Zahl ein: ";
    	cin >> zweite;
    	cout << endl << endl << endl;
    	cout << "[" << erste << "] und [" << zweite << "] miteinander" << endl;
    	cout << endl << endl;
    	cout << "<A>ddieren" << endl;
    	cout << "<S>ubtrahieren" << endl;
    	cout << "<M>ultiplizieren" << endl;
    	cout << "<D>ividieren" << endl;
    	char c;
    	cin >> c;
    	switch (c)
    	{
    	case 'a' : cout << endl << endl << "[" << erste << "] + [" << zweite << "] = " << add (erste, zweite); break;
    		cout << endl;
    	case 's' : cout << endl << endl << "[" << erste << "] - [" << zweite << "] = " << sub (erste, zweite); break;
    		cout << endl;
    	case 'm' : cout << endl << endl << "[" << erste << "] * [" << zweite << "] = " << multi (erste, zweite); break;
    		cout << endl;
    	case 'd' : cout << endl << endl << "[" << erste << "] / [" << zweite << "] = " << div (erste, zweite); break;
    		cout << endl;
    	default : cout << endl << "Sie haben sich vertippt." << endl;
    		cout << "M\x94" << "chten Sie es erneut versuchen, oder das Programm beenden?" << endl;
    		cout << endl <<"<F>ortfahren oder <B>eenden  ";
    		char d;
    		cin >> d;
    		switch (d)
    		{
    	case 'f' : cout << repeat (erste, zweite); break;
    	case 'b' : return 0;
    	default : cout << error ();
    		}
    
    	}
    	cout << error2 ();
    		cin.get();
    		cin.get();
    		return 0;
    
    }
    
    int main()
    {
    	cout << "Hallo, dies ist ein einfaches Rechenprogamm." << endl;
    	cout << endl << "Es lassen sich Standardrechnungen wie" << endl;
    	cout << "Addition, Subtraktion, Multiplikation und Division durchf\x81hren" << endl;
    	cout << endl << endl;
    	cout << "Geben Sie bitte die erste Zahl ein: ";
    	double erste, zweite;
    	cin >> erste;
    	cout << "Geben Sie bitte die zweite Zahl ein: ";
    	cin >> zweite;
    	cout << endl << endl << endl;
    	cout << "[" << erste << "] und [" << zweite << "] miteinander" << endl;
    	cout << endl << endl;
    	cout << "<A>ddieren" << endl;
    	cout << "<S>ubtrahieren" << endl;
    	cout << "<M>ultiplizieren" << endl;
    	cout << "<D>ividieren" << endl;
    	char c;
    	cin >> c;
    	switch (c)
    	{
    	case 'a' : cout << endl << endl << "[" << erste << "] + [" << zweite << "] = " << add (erste, zweite); break;
    		cout << endl;
    	case 's' : cout << endl << endl << "[" << erste << "] - [" << zweite << "] = " << sub (erste, zweite); break;
    		cout << endl;
    	case 'm' : cout << endl << endl << "[" << erste << "] * [" << zweite << "] = " << multi (erste, zweite); break;
    		cout << endl;
    	case 'd' : cout << endl << endl << "[" << erste << "] / [" << zweite << "] = " << div (erste, zweite); break;
    		cout << endl;
    	default : cout << endl << "Sie haben sich vertippt." << endl;
    		cout << "M\x94" << "chten Sie es erneut versuchen, oder das Programm beenden?" << endl;
    		cout << endl <<"<F>ortfahren oder <B>eenden  ";
    		char d;
    		cin >> d;
    		switch (d)
    		{
    	case 'f' : cout << repeat (erste, zweite); break;
    	case 'b' : return 0;
    	default : cout << error ();
    		}
    	}
    	cout << error2 ();
    		cin.get();
    		cin.get();
    		return 0;
    }
    

    Wie gesagt, hab ich jetzt return 0; durch exit(0); ersetzt. jetzt funktioniert es.

    Achja, was mir auch aufgefallen ist:

    wie ihr seht, habe ich hin und wieder 2 mal hintereinander cin.get(); geschreiben. denn wenn ich es nur einmal geschrieben habe, hat es nicht funktioniert. weiß jemand warum??

    cin.get(); wartet doch normalerweise auf die eingabe des users. das hat er aber nur gemacht, wenn ich es 2 mal geschreiben habe!



  • @samsonitex:
    Du liest mit cin >> c ein char aus cin .
    cin ist nun aber a) zeilenbasiert und b) gepuffert.
    a) bedeutet dass du von cin nichts bekommst, solange der User nicht [enter] getippt hat.

    Nun gibt der User z.B. b[enter] ein. Dann liest du mit cin >> c ein einzelnes char aus dem Stream, in dem Fall bekommst du ein b . Im Puffer steht nun aber noch ein [enter] .

    Wenn du nun danach 1x cin.get() aufrufst, wird sofort dieses [enter] zurückgeliefert, da es ja noch nicht "gelesen" wurde.

    Aber Achtung! cin.get() liest auch nur ein einzelnes Zeichen! Wenn der User also beenden[enter] eintippt, dann helfen auch deine zwei cin.get() nichts.

    Besser ist es meist eine ganze Zeile mit getline einzulesen:

    int main()
    {
    	std::string str;
    	std::getline(std::cin, str); // liest eine ganze Zeile - äusserst praktisch :)
    
    	std::cout << "you entered '" << str << "'\n";
    
    	std::cin.get();
    	return 0;
    }
    

    Wenn du das in einem Text-Menu wie in deinem Programm verwenden willst, geht das z.B. so:

    int main()
    {
    	std::string option;
    	std::getline(std::cin, option);
    
    	if (option == "a")
    		std::cout << "option a selected\n";
    	else if (option == "b")	
    		std::cout << "option b selected\n";
    	else
    		std::cout << "invalid option\n";
    
    	std::cin.get();
    	return 0;
    }
    

    Du könntest aber auch mal nachsehen, ob deine IDE nicht eine Option hat, damit das Konsolenfenster beim Debuggen nicht sofort verschwindet. Ist IMO praktischer als das olle cin.get() . Vor allem muss man das cin.get() dann nicht entfernen, wenn man das Programm mal rausgeben will, weil es von vornherein gleich garnicht da war. Das nervt nämlich eigentlich nur, wenn man nicht gerade entwickelt, sondern ein Programm einfach nur verwenden will.



  • hustbaer schrieb:

    @samsonitex:
    Du liest mit cin >> c ein char aus cin .
    cin ist nun aber a) zeilenbasiert und b) gepuffert.
    a) bedeutet dass du von cin nichts bekommst, solange der User nicht [enter] getippt hat.

    Nun gibt der User z.B. b[enter] ein. Dann liest du mit cin >> c ein einzelnes char aus dem Stream, in dem Fall bekommst du ein b . Im Puffer steht nun aber noch ein [enter] .

    Wenn du nun danach 1x cin.get() aufrufst, wird sofort dieses [enter] zurückgeliefert, da es ja noch nicht "gelesen" wurde.

    Aber Achtung! cin.get() liest auch nur ein einzelnes Zeichen! Wenn der User also beenden[enter] eintippt, dann helfen auch deine zwei cin.get() nichts.

    Besser ist es meist eine ganze Zeile mit getline einzulesen:

    int main()
    {
    	std::string str;
    	std::getline(std::cin, str); // liest eine ganze Zeile - äusserst praktisch :)
    
    	std::cout << "you entered '" << str << "'\n";
    
    	std::cin.get();
    	return 0;
    }
    

    Wenn du das in einem Text-Menu wie in deinem Programm verwenden willst, geht das z.B. so:

    int main()
    {
    	std::string option;
    	std::getline(std::cin, option);
    
    	if (option == "a")
    		std::cout << "option a selected\n";
    	else if (option == "b")	
    		std::cout << "option b selected\n";
    	else
    		std::cout << "invalid option\n";
    		
    	std::cin.get();
    	return 0;
    }
    

    Du könntest aber auch mal nachsehen, ob deine IDE nicht eine Option hat, damit das Konsolenfenster beim Debuggen nicht sofort verschwindet. Ist IMO praktischer als das olle cin.get() . Vor allem muss man das cin.get() dann nicht entfernen, wenn man das Programm mal rausgeben will, weil es von vornherein gleich garnicht da war. Das nervt nämlich eigentlich nur, wenn man nicht gerade entwickelt, sondern ein Programm einfach nur verwenden will.

    Danke,
    aber das habe ich jetzt nicht vestanden. 😕

    ich bin noch nicht soweit. ich beschäftige mich seit etwa est 2 wochen intensiv mit c++.

    kannst du ds bitte nochmal für dumme erklären, was dieses "getline" genau macht??

    Wie findest du den code sonst?
    ist das ok, wenn man bedenkt, das ich erst 2 wochen damit zutun habe?



  • ...


  • Administrator

    Ich habe mal deinen Code analysiert, auseinandergenommen und neu zusammengesetzt. Dabei aber probiert auf deinem Wissensstand zu bleiben. Du hast in deinem Code extrem viel Code Duplikationen. Lagere sowas in Funktionen aus, dann musst du es nicht immer neu schreiben und kannst es zentral ändern. Das erleichtert einem die Aufgabe.
    Zudem hast du ein völlig rekursives Programm. Desto länger jemand mit deinem Rechner rechnet, umso Wahrscheinlicher wird ein Stackoverflow. Irgendwann muss es einfach krachen. Deshalb wären ein paar Schleifen nicht schlecht.

    Zudem ist es fraglich, ob der User wirklich überall direkt aus dem Programm rauskommen muss. Es reicht dies oft im "Hauptmenu" zu machen. Wenn er eine Berechnung machen soll, dann soll er diese jetzt noch zu einem Ende führen. Auch bist du zum Teil recht brutal, was Fehleingaben angeht. Da muss der User plötzlich sogar die Zahlen neu eingeben, nur weil er zweimal die falsche Eingabe gemacht hat, bei der Auswahl einer Operation.

    Das Problem mit deinen mehrfachen std::cin.get() , hat ja schon hustbaer probiert zu erklären. Ich versuche es auch nochmals:
    Sagen wir du hast ein cin.get() im Code und die Ausführung kommt an diesen Punkt. Das Programm wartet auf eine Eingabe. Der User tippt ein:

    hallo bli bla blub
    

    Und er drückt auf <Enter> . cin.get() gibt dir nun ein 'h' zurück. Es bleibt im Puffer zurück "allo bli bla blub\r\n" , auf Linux wäre es wohl nur ein \n statt eines \r\n . Aber wie du siehst, bleibt da eine Menge übrig. Sogar wenn du nur einen Buchstaben eingibst, bleibt mindestens noch ein Linefeed im Puffer. Wenn du das nächste Mal cin.get() aufrufst, wird halt dieser Linefeed zurückgegeben und da noch Zeichen im Puffer waren, wird keine Eingabeaufforderung getätigt.
    Deshalb habe ich in meinem Code eine Funktion flush geschrieben, welche den Eingabpuffer leert.

    Calculation.hpp

    //////////////////////////////////////////////////////////////////////////
    // Calculation : Header file
    
    // Man sollte doppelte und einfache Unterstriche
    // vor dem Bezeichner meiden. Der Standard reserviert diese
    // für die Kompilerhersteller. Es gibt zwar Ausnahmen,
    // welche im Standard genau vermerkt sind, aber es ist immer noch
    // das beste, einfach pauschal darauf zu verzichten.
    
    #ifndef CALCULATION_HEADER_GUARD_3256234243134__
    #define CALCULATION_HEADER_GUARD_3256234243134__
    
    // Nur die Deklarationen kommen normalerweise in den Header.
    // Wenn man auch die Definition reinnehmen möchte, dann
    // muss man ein inline vor die Funktion schreiben, da
    // es sonst zu mehrfach definitionen kommen kann.
    // Wenn man kein inline hinschreiben würde, würde die Funktion
    // in jeder Übersetzungseinheit implementiert, was eben zu einer
    // Mehrfachdefinition führt.
    
    // Aber hier machen wir es wegen der Übung nun so,
    // dass die Definition in einer eigenen Übersetzungseinheit steht.
    
    double add(double lhs, double rhs);
    double sub(double lhs, double rhs);
    double mult(double lhs, double rhs);
    double div(double lhs, double rhs);
    
    #endif // CALCULATION_HEADER_GUARD_3256234243134__
    

    Calculation.cpp

    //////////////////////////////////////////////////////////////////////////
    // Calculation : Implementation file
    
    // Das ist nun die eigene Übersetzungseinheit für unsere Funktionen.
    // Wir brauchen hier aber die Deklarationen, deshalb holen wir
    // den Header.
    
    #include "Calculation.hpp"
    
    // Nun definieren wir die Funktionen.
    
    double add(double lhs, double rhs)
    {
    	return lhs + rhs;
    }
    
    /************************************************************************/
    
    double sub(double lhs, double rhs)
    {
    	return lhs - rhs;
    }
    
    /************************************************************************/
    
    double mult(double lhs, double rhs)
    {
    	return lhs * rhs;
    }
    
    /************************************************************************/
    
    double div(double lhs, double rhs)
    {
    	return lhs / rhs;
    }
    
    // Ich glaube dies sollte klar sein.
    // Das Objectfile, welches durch Calculation.cpp entsteht,
    // muss dann bei der Kompilierung von main.cpp gelinkt werden.
    // Eine gute IDE macht dies automatisch.
    

    main.hpp

    //////////////////////////////////////////////////////////////////////////
    // main : Header file
    
    // Ich erstelle noch einen Header für die main Übersetzungseinheit.
    // Dies geschieht in erster Linie aus Bequemlichkeit, so dass alle
    // benötigten Funktionen in der main.cpp bereits deklariert sind.
    // So muss ich nicht mehr darauf achten, in welcher Reihenfolge
    // ich die Funktionen definieren muss.
    // Auch sind alle Deklarationen schon gekapselt und folgen nicht
    // irgendwo in der Übersetzungseinheit, zwischen zwei Definitionen.
    
    #ifndef MAIN_HEADER_GUARD_23462343662234__
    #define MAIN_HEADER_GUARD_23462343662234__
    
    // Dir wird womöglich bei Calculation.hpp diese zusätzliche Zahl
    // schon aufgefallen sein. Diese dient nur dazu, dass es ganz sicher
    // kein zweites Makro mit dem selben gibt. Es ist also eine rein
    // zufällige Zahl, welche von mir eingetippt wurde.
    
    #include <istream>
    
    bool shallRepeat();
    void flush(std::istream& in);
    double readDouble(char const* text);
    void performCalc(double lhs, double rhs);
    void outputCalcResult(double lhs, double rhs, double result, char op);
    
    // lhs == left-hand side / rhs == right-hand side
    
    #endif // MAIN_HEADER_GUARD_23462343662234__
    

    main.cpp

    //////////////////////////////////////////////////////////////////////////
    // main : Implementation file
    
    // Hier sind wir also in der zentralen Übersetzungseinheit,
    // wo auch der Einstiegspunkt des Programmes liegt.
    
    // Wir brauchen hier die Deklarationen unseren Funktionen.
    // Holen wir sie mit einem include rein.
    #include "Calculation.hpp"
    
    // Die Definition wird dann über das Objectfile und dem Linker
    // nachgeliefert. In einer IDE passiert dies, wie schon gesagt,
    // automatisch.
    
    // Ich habe, wie schon gesagt, die Deklarationen der hier
    // verwendeten Funktionen in einen eigenen Header ausgelagert.
    // So muss ich hier nicht mehr darauf achten, wo ich die
    // Funktionen definiere, bzw. in welcher Reihenfolge dies geschieht.
    #include "main.hpp"
    
    // Zusätzliche Standardheader, welche wir benötigen.
    #include <string>
    #include <iostream>
    
    // Ich persönlich verzichte auf using namespace std;
    // Man sollte damit sehr vorsichtig umgehen, da man
    // den Zweck des namespace damit aushebelt. Auf gar keinen Fall darf ein
    // using namespace std; in einen Header rein! Wenn du das machst,
    // dann kann man den Namensraum gleich wegwerfen, da er überall
    // global verfügbar wird, wo der entsprechende Header eingefügt wird.
    // Über kurz oder lang führt das dann ganz sicher zu einem
    // Namenskonflikt.
    // Wenn man ein using namespace macht, dann höchstens in einem Scope.
    // Ich werde es auch so anwenden. So ist der Namensraum nur im Scope
    // ausgehebelt und nirgends sonst. Normalerweise verwende ich aber die
    // vollständige Schreibeweise.
    
    int main()
    {
    	double lhs, rhs;
    
    	do
    	{
    		// Wir lesen zwei Werte ein:
    		lhs = readDouble("Enter lhs double value: ");
    		rhs = readDouble("Enter rhs double value: ");
    
    		// Führen eine Berechnung damit aus:
    		performCalc(lhs, rhs);
    
    		// Und fragen nach, ob noch eine weitere Berechnung
    		// durchgeführt werden soll.
    	}
    	while(shallRepeat());
    
    	return 0;
    }
    
    /************************************************************************/
    
    bool shallRepeat()
    {
    	// Eine allgemeine Fehlermeldung für diese Funktion,
    	// damit wir sie nicht immer neu hinschreiben müssen.
    	// Der Zeiger ist static, besteht also über die Funktionsgrenzen
    	// hinweg. Er zeigt auf konstanten Speicher und ist selber
    	// konstant, damit er nicht verändert werden kann.
    	static char const* const errMsg = "Invalid input. Retry!";
    
    	// Wir brauch ein paar Hilfsvariablen.
    	std::string line;
    
    	bool repeat;
    	bool invalidInput;
    
    	do
    	{
    		invalidInput = false;
    
    		// Frage.
    		std::cout << "\n<C>ontinue or <E>xit?" << std::endl;
    
    		// Sicherstellen, dass nichts mehr im Inputpuffer ist.
    		flush(std::cin);
    
    		// Eine Zeile einlesen.
    		std::getline(std::cin, line);
    
    		// Prüfen ob auch etwas eingelesen wurde.
    		if(line.empty())
    		{
    			// Wenn nicht, dann die Fehlermeldung ausgeben
    			// und von vorne starten.
    			std::cout << errMsg << std::endl;
    			continue;
    		}
    
    		// Den ersten Buchstaben der Zeile betrachten.
    		switch(line[0])
    		{
    		case 'c' :
    		case 'C' :
    			{
    				// C für continue,
    				// also soll nochmals eine Berechnung durchgeführt werden.
    				repeat = true;
    			}
    			break;
    		case 'e' :
    		case 'E' :
    			{
    				// E für exit,
    				// also soll das Programm beendet werden.
    				repeat = false;
    			}
    			break;
    		default:
    			{
    				// Der User war wieder zu dumm,
    				// die richtige Eingabe zu tätigen.
    				invalidInput = true;
    				std::cout << errMsg << std::endl;
    			}
    		}
    	}
    	while(invalidInput);
    
    	// Resultat der Nachfrage zurückgeben.
    	return repeat;
    }
    
    /************************************************************************/
    
    void flush(std::istream& in)
    {
    	// Wir löschen alle Fehler, welche im istream gesetzt sind.
    	in.clear();
    
    	// Und wir ignorieren alle noch verfügbaren Zeichen im Puffer.
    	in.ignore(in.rdbuf()->in_avail());
    }
    
    /************************************************************************/
    
    double readDouble(char const* text)
    {
    	// Hilfsvariablen.
    	double result;
    
    	// Textausgeben und sicherstellen, dass der Text
    	// auch auf der Konsole erscheint (flush).
    	std::cout << text;
    	std::cout.flush();
    
    	// Wir lesen ein und prüfen, ob die Eingabe keinen Fehler
    	// verursacht hat.
    	while(!(std::cin >> result))
    	{
    		// Der User war wohl zu dumm eine Zahl einzugeben.
    		// Wir weisen ihn darauf hin und verlangen
    		// erneut eine Eingabe.
    		std::cout << "Invalid input. Retry!\n"
    				  << text;
    
    		// Wieder sicherstellen, dass der Text auch auf der Konsole
    		// erscheint, bevor wir die nächste Abfrage machen.
    		std::cout.flush();
    
    		// Zudem leeren wir den Eingabepuffer.
    		flush(std::cin);
    	}
    
    	// Den eingelesenen Wert zurückgeben.
    	return result;
    }
    
    /************************************************************************/
    
    void performCalc(double lhs, double rhs)
    {
    	// In dieser Funktion will ich wie versprochen noch das
    	// using namespace std; in einem Scope aufzeigen.
    	// Ich hätte normalerweise diese Anweisung allerdings weggelassen.
    	using namespace std;
    
    	// Aber hier sind somit alle Klassen und Funktionen aus
    	// dem Namensraum std bekannt, ohne dass man diesen explizit
    	// angeben muss. Dies gilt allerdings nur bis ans Ende der Funktion,
    	// da wir hier im Scope der Funktion sind.
    
    	// Ein paar Hilfsvariablen. Man beachte,
    	// es reicht hier string zu schreiben statt std::string.
    	char op;
    	string line;
    	double result;
    	bool calculationPerformed;
    
    	do
    	{
    		calculationPerformed = true;
    
    		// Auswahlmöglichkeiten angeben.
    		cout << "\nChoose an operation:\n"
    			 << "<A>ddition\n"
    			 << "<S>ubtraction\n"
    			 << "<M>ultiplication\n"
    			 << "<D>ivision\n"
    			 << '\n';
    
    		cout << "Choice: ";
    		cout.flush();
    
    		// Wir wollen wieder sicherstellen, dass die Ausgabe
    		// auf der Konsole erscheint, bevor eine Eingabe geschieht.
    
    		// Den Eingabepuffer leeren und eine Zeile lesen.
    		flush(cin);
    		getline(cin, line);
    
    		// Prüfen, ob die Zeile auch etwas enthält.
    		if(line.empty())
    		{
    			// Anscheinend hat der User Entscheidungsschwierigkeiten.
    			cout << "You need to make a choice!" << endl;
    
    			// Also nochmals von vorne.
    			continue;
    		}
    
    		// Den ersten Buchstaben der Zeile analysieren.
    		switch(line[0])
    		{
    		case 'a' :
    		case 'A' :
    			{
    				op = '+';
    				result = add(lhs, rhs);
    			}
    			break;
    		case 's' :
    		case 'S' :
    			{
    				op = '-';
    				result = sub(lhs, rhs);
    			}
    			break;
    		case 'm' :
    		case 'M' :
    			{
    				op = '*';
    				result = mult(lhs, rhs);
    			}
    			break;
    		case 'd' :
    		case 'D' :
    			{
    				op = '/';
    				result = div(lhs, rhs);
    			}
    			break;
    		default:
    			{
    				// Der User hat mal wieder was falsches eingegeben.
    				cout << "Unknown operation." << endl;
    				calculationPerformed = false;
    			}
    		}
    
    		// Prüfen ob die Berechnung ausgeführt wurde.
    		if(calculationPerformed)
    		{
    			// Wenn dem so ist, das Ergebnis ausgeben.
    			outputCalcResult(lhs, rhs, result, op);
    		}
    	}
    	while(!calculationPerformed);
    
    	// Die Schleife wird so lange wiederholt, bis der User die Berechnung
    	// ausgeführt hat. Wenn er raus will, dann muss er halt die Berechnung
    	// auch durchführen. Aber das sollte kein Problem sein.
    
    	// Der Namensraum std wird ab sofort nicht mehr automatisch
    	// verwendet.
    }
    
    // Hier könnten wir nicht mehr zum Beispiel string verwenden,
    // der Kompiler würde die Klasse nicht finden. Es muss wieder
    // explizit std::string angegeben werden.
    
    /************************************************************************/
    
    void outputCalcResult(double lhs, double rhs, double result, char op)
    {
    	// Dürfte leicht verständlich sein:
    
    	std::cout << '[' << lhs << ']'
    			  << ' ' << op  << ' '
    			  << '[' << rhs << ']'
    			  << ' ' << '=' << ' '
    			  << result << std::endl;
    }
    

    Ich hoffe der Code nützt etwas.

    Grüssli



  • puuhhh. ich verstehe nur bahnhof.

    aber ich werd mir das mal in ruhe alles anschauen.

    danke.

    eine sache die mir aufgefallen ist, raff ich mal so gar nicht.

    #ifndef CALCULATION_HEADER_GUARD_3256234243134__
    #define CALCULATION_HEADER_GUARD_3256234243134__
    
    double add(double lhs, double rhs);
    double sub(double lhs, double rhs);
    double mult(double lhs, double rhs);
    double div(double lhs, double rhs);
    
    #endif // CALCULATION_HEADER_GUARD_3256234243134__
    

    wozu hast du das gechrieben, wenn du in der .cpp das hier geschrieben hast.

    #include "Calculation.hpp"
    
    // Nun definieren wir die Funktionen.
    
    double add(double lhs, double rhs)
    {
        return lhs + rhs;
    }
    
    /************************************************************************/
    
    double sub(double lhs, double rhs)
    {
        return lhs - rhs;
    }
    
    /************************************************************************/
    
    double mult(double lhs, double rhs)
    {
        return lhs * rhs;
    }
    
    /************************************************************************/
    
    double div(double lhs, double rhs)
    {
        return lhs / rhs;
    }
    

    Ich versteh das nicht. wozu muss man den header überhaupt noch mit einbinden?
    ich hab doch alles was ich brauche in der .ccp.

    den rest, werd ich mir mal in aller ruhe anschauen.

    danke erstmal.



  • samsonitex schrieb:

    Ich versteh das nicht. wozu muss man den header überhaupt noch mit einbinden?
    ich hab doch alles was ich brauche in der .ccp.

    Das ist modulare Programmierung. Du hast mehrere .cpp-Dateien, die einzeln kompiliert werden können. Die Funktionen sind dort implementiert, der Header dient nur als Schnittstelle, um die Funktionen bekannt zu machen.

    Eine Darstellung der Dateien zur Veranschaulichung (beide .cpp-Dateien inkludieren den Header, durch Linien verdeutlicht):

    [b]Calculation.h[/b]
                   Deklaration der Funktionen
                      /                \
                    /                    \
                  /                        \
                /                            \
           [b]Main.cpp[/b]                       [b]Calculation.cpp[/b]
    Benutzung der Funktionen         Definition der Funktionen
    


  • ich hab das immernoch nicht verstanden.

    es ist doch besser, wenn ich die funktion bereits im header definiere oder nicht?

    wenn nicht, warum?
    ich verstehe den unterschied nicht. wenn ich sie bereits im header definiere und sie in verschiedene .cpp dateien einbinde, kann ich sie doch auch einzeln kompelieren.



  • samsonitex schrieb:

    es ist doch besser, wenn ich die funktion bereits im header definiere oder nicht?

    wenn nicht, warum?

    Nein. Erstens, weil du damit die Implementierung offen legst. Headerdateien sollten aber primär ein Interface anbieten. Aber schlimmer ist zweitens, du musst dann nämlich sämtliche Dateien, die den Header einbinden, neu kompilieren, wenn du etwas an der Funktion änderst. Drittens kann inline auch langsamer sein und führt zu mehr Code (Optimierungen jetzt mal ausser Acht gelassen).

    samsonitex schrieb:

    ich verstehe den unterschied nicht. wenn ich sie bereits im header definiere und sie in verschiedene .cpp dateien einbinde, kann ich sie doch auch einzeln kompelieren.

    Nein, jedes Modul (.cpp-Datei) wird für sich kompiliert. Die Funktion darf aber in allen Modulen total nur einmal definiert sein. Es handelt sich schliesslich um die gleiche Funktion, was würde es bringen, zur Laufzeit mehrere davon zu haben?

    Im Weiteren empfehle ich dir, dich zum Beispiel in einem Buch ausführlicher mit der Thematik zu befassen.



  • Nexus schrieb:

    Im Weiteren empfehle ich dir, dich zum Beispiel in einem Buch ausführlicher mit der Thematik zu befassen.

    lol.
    bücher habe ich genug.
    ich sag doch, das ich erst seit zwei wochen dran bin.



  • samsonitex schrieb:

    lol.
    bücher habe ich genug.
    ich sag doch, das ich erst seit zwei wochen dran bin.

    Hast du den anderen Teil meines Posts auch gelesen und vor allem verstanden?

    Ich hab das im Übrigen nur gut gemeint. Vielleicht ist es zum jetzigen Zeitpunkt aber auch noch ein wenig zu früh für modulare Programmierung...



  • nein, verstanden habe ich das immernoch nicht. ich werd das mal ausprobieren müssen um mir ein bild machen zu können, da ich die problematik nicht sehe.(noch nich).

    Wie gesagt, ich beschäftige mich erst seit 2 wochen damit.

    ich habe in meinem programm nur das gemacht, was ich bis jetzt durch habe.
    es wird halt noch ne weile dauern, bis ich wirklich mitreden kann.
    naja, dann werd ich noch n bißchen lesen. 😉

    danke erstmal


  • Administrator

    samsonitex schrieb:

    Ich versteh das nicht. wozu muss man den header überhaupt noch mit einbinden?
    ich hab doch alles was ich brauche in der .ccp.

    Hat ein bisschen technischer Hintergrund. Ich habe gerade einen ellenlangen Text geschrieben und ihn dann wieder gelöscht. Ich weiss nicht, ob das so gut ist, wenn du mit 2 Wochen Erfahrung dies lesen würdest. Wahrscheinlich würde es dich nur noch mehr verwirren 🙂

    Was für Bücher hast du denn? Wenn du ein gutes C++ Buch erwischt hast, wird dich dieses bestimmt auch in diese Thematik einführen. Ich denke es ist besser, wenn wir das dem Buch überlassen, sofern es eben ein gutes ist. Es gibt nämlich verdammt viele, die sehr schlecht sind.

    Grüssli



  • das sind meine bücher:

    Markt und Technik - Magnum C++
    Pearson Studium - Intensivkurs C++
    Markt und Technik - Jetzt lerne ich C++
    Markt und Technik - C++ der leichte Einstieg
    Pearson Studium - C++ Programmierung im klartext.

    was könnt ihr mir sonst für bücher empfehlen?
    Leicht zu lesen und verständlich sollten sie sein. und vor allem, für anfänger. 😉

    Danke




Anmelden zum Antworten