Obligatorisches "3 Zahlen ordnen"



  • Hallo allesamt.
    Ich bin Neuling beim C++ Programmieren und arbeite gerade Bjarne Stroustrups "Einführung in die Programmierung mit C++" durch. (Bin noch recht am Anfang)

    Eine der Aufgaben forderte, ein Programm zu schreiben, dass 3 Zahlen einliest
    und sie ordnet.
    Wollte ich jede Zahl einzeln einlesen, wäre das ganze kein Problem, aber ich dachte, ich lasse den Benutzer mehrere Zahlen aufeinmal eingeben via Whileschleife.

    int main()
    {
        int counter = 0;
        int input = -1;
        int input1 = -1;
        int input2 = -1;
        int input3 = -1;
        while (counter != 4){
    
            while(counter != 3 && cin>>input){
                    if(counter==0){
                    input1 = input;
                    ++counter;
                }
                    else if(counter==1){
                    input2 = input;
                    ++counter;
                }
                    else if(counter==2){
                    input3 = input;
                    ++counter;
    
                }
            }
            if(input1>=input2 && input1>=input3){
    
                    if(input2>=input3){
                    cout << input3 << " " << input2 << " " << input1;
                    }
                    else cout << input2 << " " << input3 << " " << input1;
                    }
    
            else if(input2>=input1 && input2>=input3){
    
                    if(input1>=input3){
                    cout << input3 << " " << input1 << " " << input2;
                    }
                    else cout << input1 << " " << input3 << " " << input2;
    
                }
            else cout << input1 << " " << input2 << " " << input3;
    
            counter = 0;
            cout << "\n";
            cin.clear();
        }
    
    }
    

    Mein Problem ist, dass wenn man mehr als 3 Zahlen eingibt, die übrigen Zahlen immernoch im cinbuffer (heißt das so? Ich hoffe ihr wisst was ich meine) gespeichert sind um beim erneuten durchgehen auch vom Programm benutzt werden.
    Ich würde also am liebsten den cinspeicher "leeren", wenn das denn irgendwie möglich ist. Wie funktioniert das?

    Kann man so ein Programm mit den einfachen Mitteln if, else und while Schleife auch einfacher gestallten? Brauche keinen Code aber wenn jemand mir einen Denkanstoß geben könnte wäre ich verbunden!

    Vielen Dank im voraus,
    mit freundlichen Grüßen,
    Thez



  • Den cin-Buffer leeren kannst du so:

    // Ignore to the end of file
    cin.ignore(std::numeric_limits<std::streamsize>::max())
    
    // Ignore to the end of line
    cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
    

    Bitte nicht vom Namen "clear" auf das Leeren schließen, das macht nämlich etwas ganz anderes.

    Zur Aufgabe selbst: Du könntest die Zahlen auch in ein Array oder einen std::vector einlesen. Dann müsstest du keine ifs beim Einlesen benutzen, sondern könntest die Zahlen einfach über den aktuellen Index ins Array schreiben oder mit push in den vector.
    Das Sortieren wäre dann auch einfacher, z.B. mittels std::sort.



  • oenone schrieb:

    Das Sortieren wäre dann auch einfacher, z.B. mittels std::sort.

    Der Sinn der Aufgabe ist es programmieren zu lernen, nicht std::sort aufzurufen.



  • hustbaer schrieb:

    oenone schrieb:

    Das Sortieren wäre dann auch einfacher, z.B. mittels std::sort.

    Der Sinn der Aufgabe ist es programmieren zu lernen, nicht std::sort aufzurufen.

    Da könnte man aber argumentieren, dass std::sort aufrufen programmieren lernen ist. Zumal die meisten (wie hier) lieber if/else/while nehmen statt es richtig zu machen.



  • Thez schrieb:

    Wollte ich jede Zahl einzeln einlesen, wäre das ganze kein Problem, aber ich dachte, ich lasse den Benutzer mehrere Zahlen aufeinmal eingeben via Whileschleife.

    Was könnte einfacher sein als cin >> zahl1 >> zahl2 >> zahl3; ?

    while(counter != 3 && cin>>input){
                    if(counter==0){
                    input1 = input;
                    ++counter;
                }
                    else if(counter==1){
                    input2 = input;
                    ++counter;
                }
                    else if(counter==2){
                    input3 = input;
                    ++counter;
    
                }
            }
    

    Das ist eine Variante des For-Case-Antipatterns. Unbedingt abgewöhnen 🙂
    http://thedailywtf.com/Articles/The_FOR-CASE_paradigm.aspx



  • Danke für die Antworten. Dass man cin >> zahl1 >> zahl2 usw. machen kann, hätte ich mir ja denken können, kam aber garnicht drauf. Sehr klasse, danke! Werde es ausprobieren sobald ich wieder am Heim-Rechner bin. Das mit den Arrays habe ich mir auch schon gedacht, aber in dem Kaptiel wurden Arrays eigentlich noch garnicht behandelt. Werde aber wohl auch diese Variante probieren, der Übung halber.

    Danke sehr für die Hilfe 🙂



  • nwp3 schrieb:

    hustbaer schrieb:

    oenone schrieb:

    Das Sortieren wäre dann auch einfacher, z.B. mittels std::sort.

    Der Sinn der Aufgabe ist es programmieren zu lernen, nicht std::sort aufzurufen.

    Da könnte man aber argumentieren, dass std::sort aufrufen programmieren lernen ist. Zumal die meisten (wie hier) lieber if/else/while nehmen statt es richtig zu machen.

    Ja, könnte man argumentieren.
    MMn. sollte man es aber erstmal schaffen die drei zahlen ohne std::sort zu sortieren.
    Wer das nicht zusammenbringt, der kann nicht programmieren.
    Wer es geschafft hat, der sollte dann in Zukunft std::sort verwendet.

    Idealerweise kommt das dann auch in der Reihenfolge im Unterricht.

    ps: Die Frage ist also: was soll bei dieser Aufgabe alles gelernt/geübt werden? Umgang mit iostreams? Umgang mit Arrays/Containern? Einfache Logik mit Schleifen/ifs/... abbilden?
    Und wenn letzteres dabei ist, was ich vermute, dann ist std::sort eben nicht das Mittel der Wahl.


  • Mod

    MMn. sollte man es aber erstmal schaffen die drei zahlen ohne std::sort zu sortieren.

    Hier ist das Sortiernetzwerk:

    X  o  o
       |  |
    X  |  o  o
       |     |
    X  o     o
    

    Und hier ein wenig Testcode:

    #include <algorithm>
    
    template <typename T, std::size_t N>
    bool test_sort_function( void f(T(&)[N]) )
    {
    	std::uintmax_t counter = 0;
    
    	do
    	{
    		T arr[N];
    		for( std::size_t i = 0; i != N; ++i )
    			arr[i] = counter & (T(1) << i);
    
    		f( arr );
    
    		if( !std::is_sorted(std::begin(arr), std::end(arr)) )
    			return false;
    	}
    	while( ++counter != (T(1) << N) );
    
    	return true;
    }
    
    void sort3( int (&arr)[3] )
    {
    	// swap if greater
    	// vertauscht die Werte der Arrayelemente an Positionen i bzw. j falls das Element an Position i größer ist als das an j
    	#define sig(i, j) if( arr[i] > arr[j] ) std::swap(arr[i], arr[j]);
    
    	// Diese Zeilen entsprechen den Operationen im Sortiernetzwerk oben in entsprechender Reihenfolge
    	sig( 0, 2 )
    	sig( 1, 2 )
    	sig( 0, 1 )
    }
    
    #include <iostream>
    
    int main()
    {
    	std::cout << (test_sort_function(sort3)? "passed!" : "failed!");
    }
    

    So kann man ein wenig Sortiernetzwerke üben.

    Edit: Habe die Test-Funktion verbessert, sodass sie nun das Zero-One-Prinzip verwendet.


Anmelden zum Antworten