if Schleife



  • Hallo zusammen,

    ich bin gerade dabei einen kleinen Taschenrechner zu programmieren. Leider habe ich ein Fehler in meiner if Schleife.

    Wenn ich a für Addition auswähle zeigt er mir nicht das Ergebnis an sondern geht in die else Anweisung.

    Wenn ich s für Subtraktion auswähle führt das Programme den richtigen Ablauf aus.

    Kann mir jemand helfen meinen Fehler zu finden und zu verstehen?

    Gruß

    Christian

    #include <iostream> 
    #include <cmath>  
    
    using namespace std;
    
    int main()
    {
    	float zahl1;
    	float zahl2;
    	float ergebnis;
    	string rechenzeichen;
    	string again;
    	bool run = true;
    	system ("color f1");
    	
    	
    	cout<< endl;
    	cout<< ">--------------------------------------------<" <<endl;
    	cout<< "Text der das Porgramm und der Ablaufbeschreibt"<<endl;
    	cout<< ">--------------------------------------------<" <<endl;
    	cout<< endl;
    	cout<< endl;
    	cout<< endl;
    	system("PAUSE");
    	cout<< endl;
    	cout<< endl;
    	cout<< endl;
    	
    	while(run == true)
    	{
    		
    		
    		while(run == true)
    		{
    			cout<< " Bitte waehlen Sie ein Kuerzel fuer die Rechenoperation aus: "<<endl;
    			cout<<endl;
    			cout<< " Fuer Addition ein       [a] eingeben" <<endl; 
    			cout<< " Fuer Subtraktion ein    [s] eingeben" <<endl; 
    			cout<< " Fuer Multiplikation ein [m] eingeben" <<endl; 
    			cout<< " Fuer Division ein       [d] eingeben" <<endl;
    			cout<< " Füer Potenzen ein       [p] eingeben" <<endl;
    			cout<<endl;
    			cout<<endl;
    			cout<< "Operator "; 
    			cin >>                rechenzeichen;
    			cout<<endl;
    			
    			if(rechenzeichen == "a")
    			{
    				cout<<"Bitte geben Sie Summand 1 ein"<< endl;
    				cout<<endl;
    				cout<< "Summand 1 = "; 
    				cin>>zahl1; 
    				cout<<endl; 
    				cout<<"Bitte geben Sie Summand 2 ein"<< endl;
    				cout<<endl;
    				cout<< "Summand 2 = "; 
    				cin>>zahl2;
    				cout<<endl;
    				cout<<endl;
    				cout<<endl; 
    				ergebnis = zahl1 + zahl2;
    			}
    			if(rechenzeichen == "s")
    			{
    				cout<<"Bitte geben Sie Minuend ein"<< endl;
    				cout<<endl;
    				cout<< "Minuend  = "; 
    				cin>>zahl1; 
    				cout<<endl; 
    				cout<<"Bitte geben Sie Subtrahend ein"<< endl;
    				cout<<endl;
    				cout<< "Subtrahend = "; 
    				cin>>zahl2;
    				cout<<endl;
    				cout<<endl;
    				cout<<endl; 
    				ergebnis = zahl1 - zahl2;
    			}
    			else
    			{
    				cout<<"Die Eingabe Ihres Operators entspricht nicht den Vorgaben:"<<endl;
    				cout<<endl;
    				cout<<"[a] [s] [m] [d] [p]"<<endl;
    				cout<<endl;
    				run=false;
    				break;
    			}
    			
    			cout<< "Das Ergebnis der Berechnung betraegt."<< endl;
    			cout<<endl;
    			cout<< "Ergebnis = ";
    			cout<< ergebnis<< endl;
    			cout<<endl;
    			cout<<endl;
    			cout<<endl;
    			
    			run=false;
    			
    			
    				
    		
    		}
    	
    	cout<<"Eine neue Rechnung beginnen oder das Programme beenden? (j/n)"<<endl;
    	cin >> again;
    	if(again == "j")
    		{
    			run = true;
    		}
    		else
    		{
    			run = false;
    		}			
    			
    			
    		
    		
    		
    		
    	}
    	
    			
    			
    			
    }

  • Gesperrt

    @Becksprinz sagte in if Schleife:

    if Schleife.

    OT:
    Ich wollte schon motzen, dass es sowas nicht gibt. Doch siehe: https://www.ibm.com/support/knowledgecenter/en/SSSHRK_4.2.0/ref/reference/ref_stifloop.html 😲



  • Nee, gibt keine if Schleifen. Folglich hast du auch kein Problem.



  • @Becksprinz wenn du "a" eingibst, geht das Programm durch das "a"-if und durch den else-Zweig vom "s"-if, da es ja kein "s" ist.

    Du brauchst eine if-else-if-Kette



  • Genau @DirkB hat es richtig gesagt. Dein Programm macht gerade folgendes:

    Wenn a dann addiere
    Wenn s dann subtrahiere ansonsten "Die Eingabe Ihres Operators entspricht nicht den Vorgaben:"

    Dein else bezieht sich nur auf den zweites if. Er macht also eigentlich den addieren Teil. Dann kommt die Abfrage "wenn s dann subtrahieren" (was in den Fall ja falsch ist) und springt daher ins else zur Fehlermeldung. Machst du statt if, if, else ein if, else if, else draus müsste es gehen (habs nur überflogen)



  • Ich habe es mit if else if else probiert. Hat aber leider nicht funktioniert. Vorher lief das Programm bei s wie es sollte und bei a nicht. Jetzt läuft es bei a und s nicht korrekt.

    Meint ihr vielleicht es wäre besser mit switch case zu probieren? Ich habe leider noch nicht so viel Erfahrung deshalb würde ich mich über eure Meinung dau freuen 🙂

    Gruß

    Christian



  • @Becksprinz Es funktioniert mit if-else-if.
    Demnach hast du etwas falsch gemacht.

    Wenn du etwas lernen möchtest, zeig deinen aktuellen Code.



  • @Becksprinz wie schon richtig angemerkt wurde, ist die Bezeichnung "if-Schleife" nicht korrekt. Das kannst du ja schon ganz einfach daran erkennen, dass eine Schleife Dinge wiederholt - was bei if nicht der Fall ist.
    Besser ist z.B. die Bezeichnung if-Verzweigung.

    Ein großes Problem, das mir bei deinem Code auffällt, ist, dass er ziemlich unleserlich ist.
    Die Einrückungen sind eigentlich ziemlich gut, abgesehen vllt. von den Zeilen 105-107, die anscheinend einen Tab zu wenig eingerückt sind.
    Du hast allerdings ziemlich viele Ausgabebefehle immer hintereinander, die auch noch immer das gleiche machen. So etwas deutet schon meistens darauf hin, dass es besser ginge. In deinem Fall würde ich dir ganz einfach empfehlen, alle Ausgaben in einem std::cout Aufruf zusammenzufassen. Zeilenumbrüche sind da trotzdem möglich, um das nicht in eine lange Zeile quetschen zu müssen.
    Du kannst z.B. die Zeilen 35-44 folgendermaßen lesbarer machen:

    std::cout << " Bitte waehlen Sie ein Kuerzel fuer die Rechenoperation aus:\n\n"
    	  << " Fuer Addition ein       [a] eingeben\n" 
    	  << " Fuer Subtraktion ein    [s] eingeben\n" 
    	  << " Fuer Multiplikation ein [m] eingeben\n"
    	  << " Fuer Division ein       [d] eingeben\n"
    	  << " Füer Potenzen ein       [p] eingeben\n\n\n"
    	  << "Operator ";
    

    Oder sogar noch besser die Zeilen 17-27:

    std::cout << "\n>--------------------------------------------<\n"
    	  << "Text der das Porgramm und der Ablaufbeschreibt\n"
    	  << ">--------------------------------------------<\n\n\n" << std::endl;
    std::cin.get();	// siehe unten; Warum aber danach eigentlich noch einmal drei Leerzeilen ausgeben?
    std::cout << "\n\n\n";
    

    Weitere Tipps für die allgemeine bessere Lesbarkeit:

    • nutze Leerzeichen um Operatoren; z.B. a = b + c; ist besser lesbar als a=b+c. Gleiches gilt für std::cout << std::endl;
    • lass == true weg; du vergleichst damit, ob ein bool wahr ist - und wenn das so ist, wird wahr zurückgegeben (-> also der gleiche Wert, der sowieso schon im bool gespeichert ist) lieber: while(run){...}. != true lässt sich dann mit while(!run){...} ausdrücken.
    • überflüssige Leerzeilen sind unschön, wenn sie nicht der Strukturierung von Code dienen (Z. 115-125)
    • deklariere Variablen immer so nah am Nutzungsort wie möglich; alles andere erschwert nur unnötig das Lesen und ist bei längerem Code sehr umständlich.
    • Funktionen könnten dir bereits beim Strukturieren helfen (sofern du sie schon gelernt hast)

    Anderes:

    • vermeide system("PAUSE");. Das ist plattformabhängig und ein dazu noch ein unnötiger Systemaufruf. Wenn du ein Bestätigen durch den Nutzer willst, dann nimm lieber std::cin.get(); aus der Standard-Lib (dann muss der Nutzer durch <Enter> bestätigen) - oder, wenn du unbedingt willst, dass jede beliebige Taste bestätigt, das Windows-spezifische getch(); (benötigt #include <conio.h> (oder so ähnlich)).
    • deine innere Schleife erscheint mir komisch. Am Ende setzt du run doch sowieso immer auf false?
    • nutze std::endl nicht so oft; std::endl leer nämlich zusätzlich zu einer neuen Zeile auch noch den Ausgabebuffer, was unnötige zusätzliche Arbeit ist, die du bei dir nicht brauchst - erst recht nicht so oft hintereinander. Gib lieber '\n' aus.
    • nutze lieber nicht using namespace std; so allgemein. Damit hebelst du den ganzen Daseinszweck von namespaces aus. Schreib lieber immer std:: dazu. Das ist nicht viel Schreibarbeit, man gewöhnt sich daran und man weiß immer, wo man eine Funktion einordnen kann. (persönliche Meinung)

    Zu deinem eigentlichen Problem:
    Folgendermaßen sieht eine vollständige if-Verzweigung aus:

    if(condition1) { ... }
    else if(condition2) { ... }
    else if(condition3) { ... }
    /* beliebig viele weitere else ifs */
    else { ... }    // else ist optional
    

    Dabei wird jede Verzweigung durch das if keyword eingeleitet. Dabei wird zunächst condition1 überprüft.
    Wenn das wahr ist, wird der Block dahinter ausgeführt und anschließend hinter die schließende Klammer des Blockes von else gesprungen (hier: hinter Z. 5).
    Wenn das falsch ist, wird anschließend condition2 überprüft. Bei wahr wird der entsprechende Block hinter condition2 ausgeführt und hinter das else gesprungen. Bei falsch wird condition3 überprüft.
    usw.
    Wenn alle conditions falsch ergaben, wird else ausgeführt.
    Dein Problem ist, dass du zwei Verzweigungen hast - eine mit else und eine ohne else.
    Das heißt, dass, wenn deine erste Bedingung (== "a") wahr ist, wird die Verzweigung ausgeführt und anschließend ans Ende der gesamten Verzweigung (in diesem Fall nur das eine if) gesprungen. Anschließend wird die nächste Verzweigung ausgewertet (== "b"). Dies ergibt falsch, weshalb das else ausgeführt wird.
    Ein Fix ist - wie angesprochen - dass du das if(rechenzeichen == "b") in ein else-if umwandelst.

    Ich hoffe, ich habe nichts übersehen.



  • @Unterfliege sagte in if Schleife:

    Du kannst z.B. die Zeilen 35-44 folgendermaßen lesbarer machen:

    std::cout << " Bitte waehlen Sie ein Kuerzel fuer die Rechenoperation aus:\n\n"
    	  << " Fuer Addition ein       [a] eingeben\n" 
    	  << " Fuer Subtraktion ein    [s] eingeben\n" 
    	  << " Fuer Multiplikation ein [m] eingeben\n"
    	  << " Fuer Division ein       [d] eingeben\n"
    	  << " Füer Potenzen ein       [p] eingeben\n\n\n"
    	  << "Operator ";
    

    Anzumerken ist noch das das obige das selbe ist wie:

    std::cout << " Bitte waehlen Sie ein Kuerzel fuer die Rechenoperation aus:\n\n";
    std::cout << " Fuer Addition ein       [a] eingeben\n" ;
    std::cout << " Fuer Subtraktion ein    [s] eingeben\n"; 
    std::cout << " Fuer Multiplikation ein [m] eingeben\n";
    std::cout << " Fuer Division ein       [d] eingeben\n";
    std::cout << " Füer Potenzen ein       [p] eingeben\n\n\n";
    std::cout << "Operator ";
    

    Es wird 7 mal eine schreiboperation aufgerufen (Genauer: der operator<<() )
    Das ist nicht gut. In C++ werden aneinandergereihte Zeichenketten zur Compilerzeit zu einer Zeichenkette zusammengefügt.

    Besser ist daher:

    std::cout << " Bitte waehlen Sie ein Kuerzel fuer die Rechenoperation aus:\n\n"
    	     " Fuer Addition ein       [a] eingeben\n" 
    	     " Fuer Subtraktion ein    [s] eingeben\n" 
    	     " Fuer Multiplikation ein [m] eingeben\n"
    	     " Fuer Division ein       [d] eingeben\n"
    	     " Füer Potenzen ein       [p] eingeben\n\n\n"
    	     "Operator ";
    

    Jetzt wird der cout.operator<<() nur ein mal aufgerufen.



  • @dirkski Und da jede Ausgabeoperation viel langsamer ist als ein Funktionsaufruf ist es schnurz piep sch**ß egal.



  • Hey Leute ich arbeite immer noch am mein Taschenrechner. Deshalb wollte ich mal Fragen ob es eine Möglichkeit gibt, wenn der User eine Zahl eingibt wie z.B. in Zeile 53 , diese dann zu prüfen ob es eine Zahl ist oder vielleicht ein Buchstabe?



  • cin >> zahl;
    if( !cin )
    {
       // Keine Zahl
    }
    


  • @out sagte in if Schleife:

    // Keine Zahl

    Nicht vergessen: danach den Fehlerstatus des Streams wieder löschen (https://en.cppreference.com/w/cpp/io/basic_ios/clear) und den Stream leeren (https://en.cppreference.com/w/cpp/io/basic_istream/ignore).



  • Dieser Link fehlt noch: if-schleife ;- )



  • guck mal weiter oben, von ibm persönlich.😄



  • @Wade1234 das ist weder C noch C++.



  • @Swordfish
    aber das gleiche konzept der bedingten ausführung.



  • @Wade1234 IBM auf den Blödsinn aufmerksam gemacht.


Anmelden zum Antworten