while Schleife mit Counter und character Ausgabe



  • ThaRealMatix schrieb:

    void histogramm::displayMessage()
    {
    	counter = i++;
    	while(counter <zahl)
    		{ cout << "*";}
    

    Bei deiner while schleife wird nichts erhöht um die schleife irgendwann einmal zu beenden.

    probiers mal hiermit:

    int counter = 0;
    while(counter < zahl)
    {
    cout <<"*";
    counter++;
    }
    


  • megaweber schrieb:

    [...]

    Bei deiner while schleife wird nichts erhöht um die schleife irgendwann einmal zu beenden.

    [...]

    Stimmt natürlich, aber imvho fehlen der realen Matrix einfach ein paar grundlegendste Grundlagen... Der gesamte Ansatz ist Käse. 🙄

    Greetz, Swordfish



  • Jo 8 - 10 Zeilen Code hätten's auch getan



  • megaweber schrieb:

    Jo 8 - 10 Zeilen Code hätten's auch getan

    naja,

    #include <iostream>
    
    using namespace std;
    
    const size_t num_values = 5;
    
    int main( ) {
    
        int values[ num_values ];
    
        for( size_t i = 0; i < num_values; ++i ) {
    
            cout << i <<". Wert: ";
            cin >> values[ i ];
        }
    
        cout << endl << "Histogram:" << endl << endl;
    
        for( size_t i = 0; i < num_values; ++i ) {
    
            for( int n = 0; n < values[ i ]; ++n )
    
                cout << '*';
    
            cout << endl;
        }
    
        cout << endl;
    }
    

    ist wohl das geringste, was jemand bei dieser Aufgabenstellung durchgehen lässt.

    Greetz, Swordfish



  • megaweber schrieb:

    Jo 8 - 10 Zeilen Code hätten's auch getan

    Jo, stimmt! Ist aber dann kein Anfänger-Variante mehr.

    #include <iostream>
    #include <algorithm>    // std::fill_n
    #include <iterator>     // std::ostream_iterator
    #include <iomanip>      // std::setw
    
    std::ostream& bar( std::ostream& out )
    {
        std::fill_n( std::ostream_iterator< char >( out ), out.width( 0 ), '*' );
        return out;
    }
    
    int main()
    {
        using namespace std;
        for( int i=0; i<5; ++i )
        {
            int zahl;
            if( cin >> zahl && zahl < 80 )
                cout << setw( zahl ) << bar << endl;
        }
        return 0;
    }
    

    Gruß
    Werner



  • Warum denn so umständlich?

    #include <iostream>
    #include <iomanip>      // std::setw
    
    int main()
    {
        using namespace std;
        for( int i=0; i<5; ++i )
        {
            int zahl;
            if( cin >> zahl && zahl < 80 )
                cout << setw( zahl ) << setfill('*')<< '*' << endl;
        }
        return 0;
    }
    

    PS: Wird das jetzt ein Wettbewerb ala "wer schafft die Aufgabe mit dem schönsten STL-Trick?"



  • CStoll schrieb:

    Warum denn so umständlich?

    ... weil das auch mein erster Gedanke war und ich diese Lösung wieder verworfen habe, da das setfill('*') wieder zurückgesetzt werden sollte. Und mit boost.io_state_saver wollte ich nicht auch noch anrücken.

    CStoll schrieb:

    PS: Wird das jetzt ein Wettbewerb ala "wer schafft die Aufgabe mit dem schönsten STL-Trick?"

    Ja, macht doch Spaß - oder? :xmas1:

    Gruß
    Werner



  • Werner Salomon schrieb:

    CStoll schrieb:

    Warum denn so umständlich?

    ... weil das auch mein erster Gedanke war und ich diese Lösung wieder verworfen habe, da das setfill('*') wieder zurückgesetzt werden sollte. Und mit boost.io_state_saver wollte ich nicht auch noch anrücken.

    Ja, aber das dürfte auch nicht das Problem darstellen? Ein char f=cout.fill(); am Anfang und cout<<setfill(f); am Ende ist wesentlich einfacher zu verstehen als dein Manipulator-Gebastel (sorry, wenn "Gebastel" abwertend klingt).



  • CStoll schrieb:

    (sorry, wenn "Gebastel" abwertend klingt).

    Ja, es klingt abwertend. Du hättest das 'Gebastel' ja auch ohne Informationsverlust weglassen können.

    Aber ich wünsche Dir trotzdem eine schöne Vor-Weihnachtszeit, auf das sich Deine Laune bessern möge. :xmas1:

    Gruß
    Werner



  • Hm...

    also um mal hier zu erklären, wieso ich auf diese Weise heran gegangen bin.
    Wir hatten in der Vorlesung davor nun einmal Klassen durchgenommen. Ich habe hier wieder OOP genommen, weil ich einfach annehme, das unser Prof sich erhofft, das wir

    a) damit arbeiten um darin sicherer zu werden
    b) das Programm recht schnell erweitern können sollen um x Eingegebene Zahlen

    Er erwartet ja in der Aufgabenstellung 5 Zahlen und ich hab halt gedacht, das es einfacher wäre eine Funktion zu definieren und diese dann per Objekt immer wieder neu aufzurufen.

    Es ist ja schön, hier zu erfahren, dass ich anscheinend der letzte Idiot bin, eigentlich hatte ich gedacht, dass meine Lösung, so man Sie mit OOP realisieren muss zumindest nicht sau mieß wäre, zumal ich mir wirklich Mühe gegeben hatte mit dem in der Vorlesung gelernten zu arbeiten - und ich dachte ich übersehe nur etwas.

    Ich hatte mir mit diesem Posting erhofft zu hören, wo mein Denkfehler oder Ansatzfehler ist. Ich hätte mich sicherlich darüber gefreut, wenn man mir anhand meines Codes aufzeigt wo ich Fehler vermeiden könnte oder ich schlechte Ansätze habe, Komplett Programme von Leuten die viel mehr drauf haben als ich helfen mir da absolut nicht weiter. Das einzige was mir hier wohl weiterhilft, ist die Aussage das ich mich nochmal mit Input Output beschäftigen sollte, den ich dankend (ja wirklich und ohen Ironie) annehme.

    Es tut mir leid, dass ich Euren hohen Coding Ansprüchen nicht genüge. Es tut mir weiterhin leid das ich nach 7 Wochen nicht so weit bin wie ich vielleicht sollte , ich werde mich bemühen meine Anstrengungen in anderen Vorlesungen und meinem Nebenjob zu reduzieren um mich völligst aufs Programmieren konzentrieren zu können. Bis dahin werde ich Euch den gefallen tun, und Euer Forum nicht weiter mit meiner Unwissenheit und Müllcode zu behelligen

    Herzlichst

    Gunnar



  • Nur weil man in C++ objektorientiert programmieren kann, muß man noch lange nicht alles als Objekt darstellen. (und meistens führt es nur zu unnötigen Verwirrungen, wenn man es versucht)

    Wenn du der Meinung bist, das ursprüngliche Programm erweitern zu wollen, könntest du als erstes das Array durch einen vector<> ersetzen (schon bist du in der Lage, beliebig viele Werte einzulesen und darzustellen).

    @Werner: Ich hab' mich ja entschuldigt :xmas2:



  • Hm...

    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.

    Ich bin ja bemüht mir c++ anzueignen und lese das Script sowie ein Buch - leider muss ich auf das Buc h das der Prof verwendet aber noch warten - und bin bemüht nicht bei jeder Kleinigkeit hier sofort anzufragen, aber irgendwann brauch ich halt Hilfe. 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.

    Grüße

    Gunnar

    P.S ich werde natürlich gerne auch nocheinmal probieren, eine einfachere Lösung zu Programmieren



  • ThaRealMatix schrieb:

    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.

    Der auffälligste Patzer wurde ja schon erwähnt - du hast die displayMessage() falsch aufgebaut und erzeugst dadurch eine Endlosschleife.

    (außerdem ist es unnötig, die Variablen counter und i in der Klasse anzulegen - die werden nur von displayMessage() benötigt, können also auch lokal in der Methode angelegt werden)

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

    Im einfachsten Fall so:

    int val;
    histogramm data[5];//Array für fünf histogramm'e
    for(int i=0;i<5;++i)
    {
      cin>>val;
      data[i].setZahl(val);
    }
    

    (als Erweiterung würde ich der Klasse noch einen op>> übergeben)



  • Hm... sehe ich das richtig das das nun in die setZahl käme? Wenn ich aber das nun so wie du mache, muss ich dann noch 5 objekte erzeugen? Mich verwirrt dieses

    histogramm data[5];
    

    heisst das das er ohnehin fünf Werte nacheinander eingegeben haben will?

    Tut mir leid für die doofe Frage aber ich hab bis jetzt erst einmal nen Array benutzt und das war als ich Sekunden als Worte ausgeben lassen wollte - und das ist lange her.



  • ThaRealMatix schrieb:

    Hm... sehe ich das richtig das das nun in die setZahl käme? Wenn ich aber das nun so wie du mache, muss ich dann noch 5 objekte erzeugen? Mich verwirrt dieses

    histogramm data[5];
    

    Das erzeugt ganz einfach ein Array mit fünf Elementen (die du über ihren Index als 'data[0]' bis 'data[4]' ansprechen kannst. (alternativ müsstest du fünf einzelne Objekte anlegen und dann alle Befehle fünfmal hintereinander schreiben - das sieht scheußlich aus, ist nicht erweiterbar und saumäßig zu warten)



  • ThaRealMatix schrieb:

    ... sehe ich das richtig das das nun in die setZahl käme?

    Ja. Dazu hast Du ja die (selbst geschriebene) Methode setZahl.

    ThaRealMatix schrieb:

    ... heisst das das er ohnehin fünf Werte nacheinander eingegeben haben will?

    Nein er erstellt nur fünf Objekte. Befüllt werden sie über die for-Schleife

    for (int i = 0; i < 5; ++i)
    {
        // ...
    

    Hoffe das hilft Dir weiter...

    Viele Grüße und viel Erfolg
    Knecht



  • 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.



  • .. 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 😉


Anmelden zum Antworten