array mit Zahlen füttern und sortieren



  • Hallo,

    ich bin neu hier im Forum und auch noch in den Anfängen von C++.

    Folgendes Problem:
    Ich möchte gerne ein array mit Zahlen füttern die vom User eingegeben werden und diese mit BubbleSort der Größe nach sortieren.
    Als erstes Frage ich ab wie viele Zahlen sortiert werden sollen und dann welche Zahlen sortiert werden sollen.
    Wie kann ich dem array die eingegeben Zahlen zuweisen?

    Hier mein bisheriger der Code:

    int main()
    {
    	int n;
    
    	cout << "Wieviele Zahlen wollen Sie nach der groesse sortieren? \n \n";
    	cin >> n;
    
    	int zahlenlist[n] = {};
    	int i;
    
    
    	cout << "\n Geben Sie jetzt Ihre " << n << " Zahlen ein, die Sie nach groesse sortieren wollen! \n";
    
    	while (i <=n)
    	{
    
    	}
    	cin >> ;
    
    	cout << zahlenliste[n];
    	
    	// BubbleSort
    	/*for ()
    	{
    		for ()
    		{
    
    		}
    	}
    

    Vielen Dank für eure Hilfe im voraus und entschuldigt die Fehler, da ich wirklich erst vor kurzem angefangen habe mit C++.

    BG,
    Guetta



  • Du scheinst schlechtes Lernmaterial zu benutzen. Besorge dir ein gutes Buch.

    Die Größe eines Arrays wird in C++ zur Compilezeit festgelegt. Wenn dein Compiler den gezeigten Code übersetzt, ist das eine nicht standardkonforme Erweiterung. Benutze std::vector.

    std::vector<int> zahlen;
    for(int i=1; i<=n; ++i){
      int z;
      std::cin >> z;
      zahlen.push_back(z);
    }
    

  • Gesperrt

    Hier ist ein Bubblesort für int-Arrays: https://www.geeksforgeeks.org/cpp-program-for-bubble-sort/

    Hinweis: Ich selbst hab's weder geschrieben noch getestet.



  • hast du mal was von dynamischer speicherverwaltung gehört, stichwort new und delete?

    wenn du das hinbekommen ist, musst du in zeile 14 - 17 statt einer while-schleife eine for-schleife für i=0 bis i<n verwenden, die zahlenlist[i] den eingabewert zuweist und bubblesort funktioniert unabhängig von rbs2s lösung (habs mir halt nicht angeguckt) etwa so:

    bool sorted = true;
    
    do
    {
         for(int i = 0; i < n - 1; i++)
         {
               if(zahlenlist[i] > zahlenlist[i+1])
              {
                   int temp = zahlenlist[i];
                   zahlenlist[i] = zahlenlist[i+1];
                   zahlenlist[i+1] = temp;
                  sorted = false;
              }
         }
    }while(!sorted);
    
    


  • @Wade1234 sagte in array mit Zahlen füttern und sortieren:

    stichwort new und delete?

    Gaaah, bitte hör auf mit so ner Kacke.



  • was? wieso? wenn ich im studium (wo professoren c++03 unterrichten, weil die wirtschaft das so will) eine bestimmte menge an daten einlesen will, fordere ich den speicher dynamisch an, oder nicht?



  • @Wade1234 sagte in array mit Zahlen füttern und sortieren:

    fordere ich den speicher dynamisch an, oder nicht?

    Nein. Ja. Jein. Nicht händisch.

    #include <cstdlib>
    #include <vector>
    #include <iostream>
    #include <algorithm>  // von mir aus kannst du dir dein swap auch selbst schreiben
    
    template<typename ForwardIt>
    void bubble_sort(ForwardIt first, ForwardIt last)
    {
    	for (ForwardIt i = first; i != last; ++i)
    		for (ForwardIt k = first; k < i; ++k)
    			if (*i < *k)
    				std::swap(*i, *k);
    }
    
    int main()
    {
    	std::size_t num_values;
    	std::cin >> num_values;
    	
    	std::vector<int> values;
    	int value;
    	for (std::size_t i = 0; i < num_values && (std::cin >> value); ++i)
    		values.push_back(value);
    
    	if (values.size() != num_values) {
    		std::cerr << "Du bist zu doof " << num_values << " integer einzugeben.\nbye.\n\n";
    		return EXIT_FAILURE;
    	}
    
    	bubble_sort(values.begin(), values.end());
    	
    	for (std::size_t i = 0; i < values.size(); ++i)
    		std::cout << values[i] << '\n';
    }
    

    ... und wenn Du Bubblesort einmal verstanden hast dann darfst Du ihn bitte wieder gaaaaanz schnell vergessen.

    // edit: Angepasst auf C++03. (Kalender heuer schon gesehen?)

    in akutellem C++:

    #include <cstdlib>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    
    template<typename ForwardIt>
    void bubble_sort(ForwardIt first, ForwardIt last)
    {
    	for (auto i{ first }; i != last; ++i)
    		for (auto k{ first }; k < i; ++k)
    			if (*i < *k)
    				std::iter_swap(i, k);
    }
    
    int main()
    {
    	std::size_t num_values;
    	std::cin >> num_values;
    
    	std::vector<int> values;
    	
    	decltype(values)::value_type value;
    	for (decltype(num_values) i{}; i < num_values && (std::cin >> value); ++i)
    		values.push_back(value);
    
    	if (values.size() != num_values) {
    		std::cerr << "Du bist zu doof " << num_values << " integer einzugeben.\nbye.\n\n";
    		return EXIT_FAILURE;
    	}
    
    	bubble_sort(values.begin(), values.end());
    
    	for(auto const &v : values)
    		std::cout << v << '\n';
    }
    
    

    // edit: ich schimpfe ja sonst immer über one-letter-identifiers ... also will ich es auch nicht vormachen. n ~> num_values.

    @Wade1234 sagte in array mit Zahlen füttern und sortieren:

    fordere ich den speicher dynamisch an, oder nicht?

    und überhaupt, in so einem Fall bei dem es nur um PODs wie ints geht: std::malloc(), std::realloc() ... wenn man schon zu Fuß will.



  • @Wade1234 sagte in array mit Zahlen füttern und sortieren:

    was? wieso? wenn ich im studium (wo professoren c++03 unterrichten, weil die wirtschaft das so will) eine bestimmte menge an daten einlesen will, fordere ich den speicher dynamisch an, oder nicht?

    std:::vector gibt es schon in C++ 98



  • @manni66 sagte in array mit Zahlen füttern und sortieren:

    std:::vector gibt es schon in C++ 98

    und vorher schon in der STL.Also spätestens 1994.



  • @Wade1234 sagte in array mit Zahlen füttern und sortieren:

    was? wieso? wenn ich im studium (wo professoren c++03 unterrichten, weil die wirtschaft das so will) eine bestimmte menge an daten einlesen will, fordere ich den speicher dynamisch an, oder nicht?

    Du forderst den Speicher im Idealfall gar nicht an, weil du vergessen könntest ihn wieder freizugeben. Das lässt du am besten einen der zuverlässigen STL-Container erledigen. Die vergessen das nämlich nicht.
    Welcher Container das ist, lässt sich so ermitteln: https://stackoverflow.com/questions/471432/in-which-scenario-do-i-use-a-particular-stl-container



  • also wenn ich bspw. prison architect spiele, verlangsamt sich das spiel ab einer gewissen größe sehr stark. wenn ich dann speichere und neu lade, läuft es wieder flüssig. vermutung: man knallt alles in einen container und gibt da auch nichts frei.



  • @It0101

    Welcher Container das ist, lässt sich so ermitteln: https://stackoverflow.com/questions/471432/in-which-scenario-do-i-use-a-particular-stl-container

    Wobei das Sheet, wie in den Kommentaren bei SO erwähnt, heute nicht mehr so richtig passt. std::vector ist meistens ein guter Anfang und oft vorzuziehen; std::list dagegen ist in den wenigsten Fällen von Vorteil.

    // edit:
    Und für Neulinge: std::vector, std::vector, std::vector



  • @Wade1234 sagte in array mit Zahlen füttern und sortieren:

    vermutung: man knallt alles in einen container und gibt da auch nichts frei.

    Da es ja keine andere Möglichkeit gibt muss es so sein.

    Ach, Moment - könnte natürlich auch so jemand wie du gewesen sein, der Speicher anfordert aber nicht wieder freigibt.



  • @It0101 sagte in array mit Zahlen füttern und sortieren:

    weil du vergessen könntest ihn wieder freizugeben.

    und selbst das wäre ja kein wirkliches Argument, weil Du, @Wade1234, natürlich hoch und heilig sofort versprechen wirst, soetwas nie nicht zu vergessen. Davon will ich auch gerne ausgehen. Aber dann kommt eine phöse Exception dahergeflogen und Du hast nur einen rohen Pointer und guckst in die Röhre ... ätsch.

    RAII/RDID ist Dein Freund. Also für Pointer std::unique_ptr<> und std::shared_ptr<>, für Ressourcen die nicht mit delete oder delete[] freigegeben werden können eben mit custom-deleter. Sonst die Container der Standardlibrary. std::array<> wenn die Größe zur Compiletime feststeht, std::vector<> wenn nicht und es ein zusammenhängender Speicherbereich sein soll, std::deque<> wenn das nicht sein muss. Wenn Du einen anderen Container brauchst, dann weißt Du es.



  • @manni66
    also ich habe gelernt, dass zu jedem malloc immer ein free und du jedem new ein delete gehört und dass ich mir gleich nach der feststellung, dass speicher angefordert werden soll, gedanken machen muss, wo und wann der speicher freigegeben werden muss, damit sowas nicht passiert.

    also was ich sagen wollte: scheinbar passiert das mit den containern auch.



  • @Wade1234 sagte in array mit Zahlen füttern und sortieren:

    @manni66
    also ich habe gelernt, dass zu jedem malloc immer ein free und du jedem new ein delete gehört und dass ich mir gleich nach der feststellung, dass speicher angefordert werden soll, gedanken machen muss, wo und wann der speicher freigegeben werden muss, damit sowas nicht passiert.

    Was du nicht gelernt hast: man erwischt trotzdem nich alle Fälle. Immer.

    also was ich sagen wollte: scheinbar passiert das mit den containern auch.

    Woher du das auch immer wissen willst.



  • @Wade1234 sagte in array mit Zahlen füttern und sortieren:

    und dass ich mir gleich nach der feststellung, dass speicher angefordert werden soll, gedanken machen muss, wo und wann der speicher freigegeben werden muss, damit sowas nicht passiert.

    Nein, Himmeldonnerwetter nochmal. RAII + RDID !!

    @Wade1234 sagte in array mit Zahlen füttern und sortieren:

    also was ich sagen wollte: scheinbar passiert das mit den containern auch.

    Was passiert da "auch"?



  • Was @manni66 mit

    @manni66 sagte in array mit Zahlen füttern und sortieren:

    Was du nicht gelernt hast: man erwischt trotzdem nich alle Fälle. Immer.

    zB meint:

    #include <cstddef>
    #include <algorithm>
    
    class foo
    {
        std::size_t num_bars;
        int *bar;
        std::size_t num_quxs;
        int *qux;
    
    public:
        foo(std::size_t num_bars, std::size_t num_quxs)
        : num_bars { num_bars          },
          bar      { new int[num_bars] },
          num_quxs { num_quxs          },
          qux      { new int[num_quxs] }
        {}
    
        foo(foo const &other)
        : num_bars { other.num_bars    },
          bar      { new int[num_bars] },
          num_quxs { other.num_quxs    },
          qux      { new int[num_quxs] }    
        {
            std::copy(other.bar, other.bar + num_bars, bar);
            std::copy(other.qux, other.qux + num_quxs, qux);
        }
    
        foo& operator=(foo other)
        {
            std::swap(num_bars, other.num_bars);
            std::swap(bar, other.bar);
            std::swap(num_quxs, other.num_quxs);
            std::swap(qux, other.qux);
            return *this;
        }
    
        ~foo()
        {
            delete[] bar;
            delete[] qux;
        }
    };
    

    @Wade1234 Passt so, oder? Ich meine, Constructor besorgt Speicher, Copy-Constructor macht schön eine tiefe Kopie (also nicht nur die Pointerwerte - dann gäbe es ja wenn die Destruktoren von Origial und Kopie laufen bei einem von beiden ein delete[] auf ein bereits freigegebenes Pointervalue ~> Undefined Behaviour.), Assignment-Operator macht brav Copy-and-Swap und der Destruktor räumt das ganze wieder auf. Alles schön. (?)

    Oder einfacher, sowas:

    #include <cstddef>
    #include <limits>
    #include <stdexcept>
    #include <iostream>
    
    void read_pigs(int *first, int *last)
    {
    	for (auto *i{ first }; i != last; ++i) {
    		if (!(std::cin >> *i))
    			throw std::runtime_error{ "Eingabefehler!" };
    	}
    }
    
    void print_pigs(int const *first, int const *last)
    {
    	for (auto *i{ first }; i != last; ++i)
    		std::cout << *i << ' ';
    	std::cout.put('\n');
    }
    
    int main()
    {
    	std::size_t count;
    
    	while (std::cout << "Wie viele Schweiderl?\n", !(std::cin >> count)) {
    		std::cerr << "Eingabefehler.\n\n";
    		std::cin.clear();
    		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    	}
    
    	auto *pigs{ new int[count] };
    	read_pigs(pigs, pigs + count);
    
    	std::cout << "\nEingabe war:\n";
    	print_pigs(pigs, pigs + count);
    
    	delete[] pigs;
    }
    

    Am Anfang von main() sobald die Größe feststeht Speicher besorgen und am Ende wieder freigeben. Easy. (?)



  • @Wade1234 sagte in array mit Zahlen füttern und sortieren:

    also wenn ich bspw. prison architect spiele, verlangsamt sich das spiel ab einer gewissen größe sehr stark. wenn ich dann speichere und neu lade, läuft es wieder flüssig. vermutung: man knallt alles in einen container und gibt da auch nichts frei.

    Für Performance-Probleme gibt es tausende Gründe. Eventuell ist auch ein Container sehr groß und wird öfter kopiert.
    STL-Container ersetzen nicht die Gehirntätigkeit, sie reduzieren nur die Fehlerquote.



  • @It0101
    ja das meinte ich ja. raii bzw. das konzept dahinter (die bedeutung der bezeichnung musste ich erst einmal nachlesen) war mir ja an sich bekannt. aber wenn ich etwas in einen container stecke, muss ich das ja irgendwann auch mal wieder daraus entfernen und das kriegen die leute scheinbar nicht hin. im endeffekt ist das doch das gleiche, wie das vergessen von delete, oder nicht?


Anmelden zum Antworten