while Schleife mit Counter und character Ausgabe



  • .. hoppla, der Server war weg. Daher kommt die Antwort etwas später:

    ThaRealMatix schrieb:

    ich habe die Aufgabenstellung ja am Anfang erwähnt. Ich weiss nicht ob ich objektorientiert arbeiten muss ich habs einfach probiert, weil ich selbst eben kein Crack bin und dachte das ich damit nun sicherer darin werde.

    Mir ist völlig klar, dass dass Programm für diese Aufgabe übertrieben ist.

    Ich kann mich jetzt spontan auch nicht erinnern, schon Vektoren durch genommen zu haben.

    Mir würde es für's erste wirklich genügen, wenn man mir sagt wo ich in meinem Code Dinge - mit den Mitteln die ich eingesetzt habe bzw einsetzen muss - Patzer habe.

    Desweiteren ist mir halt absolut nicht klar wie ich eine cin Eingabe in die "Objekterstellung" ( histogramm histogramm1 ( 5 );) bekommen könnte.

    Hallo Gunnar,

    um noch mal eine Lanze für die Objektorientierung zu brechen ... Es ist auch in diesem Fall völlig ok, es mal zu probieren. An solch' kleinen Beispielen kann man schön üben.
    Wenn man eine Klasse entwirft, sollte man sich (vorher!) darüber klar werden, welchen Zweck so eine Klasse hat. Damit man nicht in die Falle rennt, die CStoll schon erwähnt hat. In diesem Fall wäre der Zweck einfach die Ausgabe des *-Balkens.
    Jetzt muss man noch wissen, wie man das in C++ realisiert. Hier wäre eine friend-Funktion mit überladenem operator<< die übliche Lösung. Also

    class histogramm {
    public:
        friend std::ostream& operator<<( std::ostream& out, const Histogramm& h )
        {
            // und hier jetzt h.zahl mal '*' ausgeben
            return out;
        }
    };
    

    Damit kann man ein Histogramm genauso ausgeben, wie etwa ein int:

    histogramm h ...;
    cout << h << endl;
    

    Die Methode displayMessage ist dann hinfällig. Ein Patzer ist es auch, wenn Du innerhalb von displayMessage die Ausgabe auf cout lenkst. Damit schränkst Du den Anwender in der Wahl des Ausgabe-Mediums ein; in solchen Fällen immer den std::ostream mitgeben - genau wie bei der friend-Funktion oben - damit der Anwender sich das Ziel der Ausgabe aussuchen kann (cout, ofstream oder was anderes).
    Weiter sollte man im Konstruktor immer die Initialisierung-Listen verwenden und mit get- und set-Methoden sparsam umgeben. Ich meine, in diesem Fall brauchst Du keine Get/Set-Methode. Auch beim Einlesen könntest Du notfalls ein Histogramm einfach zuweisen (genau wie ein int), statt ein setZahl zu benutzen.

    histogramm h[5];
    for( int i=0; i<5; ++i )
    {
        int val;
        cin >> val;
        h[i] = Histogramm( val );
    }
    

    Der Unterschied zwischen einem setZahl und einer Zuweisung ist der, dass Du keinerlei interne Strukturen der Klasse Histogramm für den Anwender offen legen musst. Das nennt man Kapselung der Daten. In diesem Fall mag der Vorteil nicht so offensichtlich sein, dazu ist die Anwendung zu klein, aber grundsätzlich hat dies große Vorteile.

    Ja man könnte auch noch einen Schritt weitergehen (nur so als Übung - ich weiß schon: Kanonen & Spatzen ..), indem man Histogramm 'eingebbar' macht. Also das Ziel kann es sein, folgendes zu schreiben:

    Histogramm h[5];
    for( int i=0; i<5; ++i )
    {
        cin >> h[i];
    }
    

    Das geht symmetrisch zur Ausgabe mit einem zusätzlichen operator>>.

    class Histogramm {
    public:
        friend std::istream& operator>>( std::istream& in, Histogramm& h )
        {
            int val;
            if( in >> val )
                h.zahl = val;
            return in;
        }
    };
    

    auch hier wieder nicht von std::cin einlesen - etwa mit einer Methode Histogramm::eingabe() - sondern allgemein von einem std::istream lesen lassen und erst bei der Anwendung (s.o.) wird das Medium (cin) festgelegt.

    Gruß
    Werner



  • Simon2 schrieb:

    ThaRealMatix schrieb:

    ...Wenn dieses Forum nicht dazu gedacht ist Anfängern auch bei belanglosem vielleicht erklärend zur Seite zu stehen, ist das für mich in Ordnung, es wäre nur nett wenn man mir den Anspruch dieses Forums dann mitteilt - ich suche mir dann gerne eines für Anfänger, kein Thema....

    Ho, Ruhig, Brauner - niemand hat Dich hier "angemacht". 😉 :xmas1:

    Aber als Einsteiger wirst Du evtl. auch zu schätzen wissen, wenn Dir hier nicht nur auf dem Weg zu einer korrekten Programmsyntax, sondern auch zu einer angemessenen Programmiertechnik geholfen wird.

    ... und dazu zählt der Hinweis, dass es eine Frage der Problemstellung ist, ob OOP geeigneter ist oder evtl. prozedural. Das bedeutet nicht, dass es in OOP nicht ginge, aber zu demonstrieren, wie und warum prozedural einfacher ist, ist nicht als Vorwurf gemeint.

    Gruß,

    Simon2.

    Der von Dir zitierte Teil war durchaus ernst gemeint. Es gibt eben Foren im Web die eine "fortgeschrittene" (in Bezug auf das Themengebiet) Usergruppe wendet. Nach den ganzen Postings auf mein Thema hab ich mich halt wie der kleine Junge in der Diskussionrunde von Professoren gefühlt, nichts weiter 😉

    Dann möchte ich Werner für seinen Beitrag danken. Ich hoffe Du siehst mir nach wenn ich einiges davon (noch) nicht wirklich verstehe. Die Vorlesung ist in der siebten Woche, von daher sagen mir begriffe wie "friend" ehrlich gesagt noch wenig. Ich werde mir das ganze aber gerne noch einmal durchlesen, wenn ich mit dem Buch von Prinz und dem C++ How to Program von Deitel soweit bin. (An der Stelle vielleicht die Frage, sollte ich beide Bücher nutzen ode ratet ihr mir eher zum Deitel (nutzt der Prof) oder ist doch der Prinz besser?)

    Ich habe zu guter letzt einmal versucht es simpler umzusetzen (werde aber auch das OOP weiterhin versuchen).

    Leider scheine ich bei der Überprüfung der Zahl einen Fehler zu haben.

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	int zahl1;
    	int i;
    	cout << "Bitte geben Sie die erste Zahl ein: ";
    	cin>>zahl1;
    
    	if (zahl1<0 && zahl1>80)
    	{
    		cout << "Bitte geben Sie eine korrekte Zahl ein: ";
    	}
    	else
    	{	
    			for(i=1;i<=zahl1;i++)
    		{
    			cout << "*";
    		}
    	}
    
    	return 0;
    }
    

    Vielen Dank für Eure Mühe

    Gunnar



  • Bei sowas hilft es oft sich die Bedingung mal laut selbst vorzulesen: Wie kann eine Zahl kleiner als Null und größer als 80 zugleich sein? Ich schätze, da würde ein oder besser passen 😉



  • Ja die Logik:

    if (zahl1<0 && zahl1>80)
    

    Hier wolltest Du statt dem UND sicher ein ODER verwenden. (Die Zahl wird nie gleichzeitig kleiner als 0 UND größer als 80 sein.)

    DJohn



  • -.- ok korrigiert.. Kann ich es auch irgendwie hinbekommen, dass er danach nicht abbricht, sondern ich wieder eingeben kann und er es dann wieder versucht, also quqasi am anfang der schleife wieder ansetzt? brauch ich dazu ne andere schleifenform?



  • ThaRealMatix schrieb:

    ...
    Der von Dir zitierte Teil war durchaus ernst gemeint. ...
    Nach den ganzen Postings auf mein Thema hab ich mich halt wie der kleine Junge in der Diskussionrunde von Professoren gefühlt, nichts weiter ;)...

    Das hat man gemerkt. 😃

    Gruß,

    Simon2.



  • ThaRealMatix schrieb:

    -.- ok korrigiert.. Kann ich es auch irgendwie hinbekommen, dass er danach nicht abbricht, sondern ich wieder eingeben kann und er es dann wieder versucht, also quqasi am anfang der schleife wieder ansetzt? brauch ich dazu ne andere schleifenform?

    Ja, du kannst eine beliebige Schleife dafür nehmen (C hat drei zur Auswahl, welche am passendsten ist, hängt vom Problem ab). Als Hilfsmittel gibt es noch die Befehle break; (beendet die Schleife unabhängig von erfüllten Bedingungnen) und continue; (überspringt den Rest des Schleifenkörpers).



  • Hm... krieg ich nicht hin 😕

    Anyway... gibt es vielleicht eine "schönere" Möglichkeit fünf Zahlen einzulesen als diese hier:

    #include <iostream>
    using namespace std;
    
    int main()
    {
    	int zahl1;
    	int i;
    	cout << "Bitte geben Sie die erste Zahl zwischen 0 und 80 ein: ";
    	cin>>zahl1;
    
    	if (zahl1<0 || zahl1>80)
    	{
    		cout << "Die Zahl lag nciht zwischen 0 und 80!!!";
    	}
    	else
    	{	
    			for(i=1;i<=zahl1;i++)
    		{
    			cout << "*";
    		}
    	}
    
    	int zahl2;
    	//int i;
    	cout << "Bitte geben Sie die zweite Zahl zwischen 0 und 80 ein: ";
    	cin>>zahl2;
    
    	if (zahl2<0 || zahl2>80)
    	{
    		cout << "Die Zahl lag nicht zwischen 0 und 80!!!";
    	}
    	else
    	{	
    			for(i=1;i<=zahl2;i++)
    		{
    			cout << "*";
    		}
    	}
    
    	int zahl3;
    	//int i;
    	cout << "Bitte geben Sie die dritte Zahl zwischen 0 und 80 ein: ";
    	cin>>zahl3;
    
    	if (zahl3<0 || zahl3>80)
    	{
    		cout << "Die Zahl lag nicht zwischen 0 und 80!!!";
    	}
    	else
    	{	
    			for(i=1;i<=zahl3;i++)
    		{
    			cout << "*";
    		}
    	}
    
    	int zahl4;
    	//int i;
    	cout << "Bitte geben Sie die vierte Zahl zwischen 0 und 80 ein: ";
    	cin>>zahl4;
    
    	if (zahl4<0 || zahl4>80)
    	{
    		cout << "Die Zahl lag nicht zwischen 0 und 80!!!";
    	}
    	else
    	{	
    			for(i=1;i<=zahl4;i++)
    		{
    			cout << "*";
    		}
    	}
    
    	int zahl5;
    	//int i;
    	cout << "Bitte geben Sie die letze Zahl zwischen 0 und 80 ein: ";
    	cin>>zahl5;
    
    	if (zahl5<0 || zahl5>80)
    	{
    		cout << "Die Zahl lag nicht zwischen 0 und 80!!!";
    	}
    	else
    	{	
    			for(i=1;i<=zahl5;i++)
    		{
    			cout << "*";
    		}
    	}
    
    	return 0;
    }
    


  • Ja, mit Arrays und einer Schleife - irgendwo da oben habe ich schonmal angedeutet, wie das aussehen könnte. (btw, die Tatsache, daß du fünfmal fast den selben Code schreiben mußtest, deutet auf Design-Fehler hin ;))


Anmelden zum Antworten