Frage zur dynamischen Speicherverwaltung



  • Hallo,
    ich soll das folgende Programm so umschreiben, dass man beliebig viele float Werte eingeben kann und das Programm diese sortiert. Soweit so gut. Das ganze soll mit Befehlen der dynamischen Speicherverwaltung passieren. Wie kann ich ein array mit beliebig vielen feldern anlegen? es gibt ja keine befehle für max anzahl???? weiter sollen dann solange tempearaturen eingegeben werden, bis der benutzer eine 0 eingibt, nach eingabe der 0 soll das sortieren beginnen. ich weiß, wie ich z.b. mit malloc den benutzer fragen kann, wieviel zahlen er eingeben will, jedoch was hat das mit der 0 auf sich?

    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        int i, j;
        float temp[10], k;
    
        printf("Bitte geben Sie nun 10 Temperaturen ein, dass Programm sortiert diese von niedrig nach hoch:\n");
            for(i=0;i<10;i++)                   //Schleife zum Eingeben der Temperaturen
            {
            printf("Temperatur %d:", i+1);
            scanf("%f", &temp[i]);
            }
    
            for(j=0;j<10;j++)                   // Schleife für die Durchgänge des Sortierens
            {
                    for (i=0;i<9;i++)          // Schleife für den Sortiervorgang
                    {
                    if (temp[i]>temp[i+1]){
                        k = temp[i];
                        temp[i] = temp[i+1];
                        temp[i+1] = k;
                        }
                    }
            }
    
            for(i=0;i<10;i++)                                   //Schleife zur Ausgabe der Temperaturen
                printf("%d. Temperatur: %f\n", i+1, temp[i]);
    
        return 0;
    }
    


  • Du brauchst malloc und realloc.

    Wenn für die Temperatur 0 eingegeben wird, ist die Eingabe fertig.



  • und welche größe gebe ich beim malloc befehl ein? ich brauche ja eine größe für den float speicherbereich welcher reserviert werden soll?



  • Ein float-Array der Laenge 'length' kannst du so erzeugen:

    float *arr;
    size_t length = 10;
    arr = (float*) malloc(length * sizeof(*arr));
    

    Dabei bezeichnet *arr das erste Element des Arrays, ein float Element, d.h. sizeof(*arr) gibt die Groesse (in bytes) einer float Variable zurueck.


  • Mod

    vfbf4n1893 schrieb:

    und welche größe gebe ich beim malloc befehl ein? ich brauche ja eine größe für den float speicherbereich welcher reserviert werden soll?

    Eine gute Strategie ist, zunächst einmal mit einem Element anzufangen und jedes Mal, wenn der verfügbare Speicher voll ist, macht man ein realloc zu X-Mal so vielen Elementen wie man bisher hatte (mit X > 1). X=2 ist bewährt für einen guten Kompromiss zwischen Speicherverbrauch und Geschwindigkeit. Je kleiner X, desto öfter muss man reallokieren (langsam), je größer X ist, desto mehr Speicher wird möglicherweise verschwendet, den man niemals benutzt. Außerdem bekommt man mit X=2 auch Potenzen von 2 als Größe, was vielleicht irgendwie technisch günstig sein könnte (keine Ahnung ob das wirklich etwas ausmacht).



  • Sollte so funktionieren, wobei neue_T_Liste und alte_T_Liste Pointer auf float sind:

    neue_T_Liste = (float*) realloc (alte_T_Liste, Anzahl_Werte * sizeof(float));
    

  • Mod

    icarus2, C-Coder: Wozu die Casts? stdlib.h nicht eingebunden? C++-Compiler benutzt? In beiden Fällen habt ihr nun ein zur Compilezeit findbares Problem verdeckt, ohne einen Vorteil zu haben. Dafür aber auch noch mehr Code geschrieben.



  • SeppJ schrieb:

    icarus2, C-Coder: Wozu die Casts? stdlib.h nicht eingebunden? C++-Compiler benutzt? In beiden Fällen habt ihr nun ein zur Compilezeit findbares Problem verdeckt, ohne einen Vorteil zu haben. Dafür aber auch noch mehr Code geschrieben.

    Schlechte Gewohnheit, die ich irgendwie nicht wegkriege 🙂



  • icarus2 schrieb:

    SeppJ schrieb:

    icarus2, C-Coder: Wozu die Casts? stdlib.h nicht eingebunden? C++-Compiler benutzt? In beiden Fällen habt ihr nun ein zur Compilezeit findbares Problem verdeckt, ohne einen Vorteil zu haben. Dafür aber auch noch mehr Code geschrieben.

    Schlechte Gewohnheit, die ich irgendwie nicht wegkriege 🙂

    Sorry, bei mir auch. Ich gelobe nächstes mal Besserung...



  • kann mir nochmal jemand genauer erklären, wie ich hier nun vorgehen soll? wieso wird die eingabe bei 0 beendet?

    wie schaffe ich es, dass das programm soviele speicherstellen reserviert, bis 0 eingegeben wird??



  • In einer Schleife fragst du den Wert vom User ab und besorgst dafür Speicher mit realloc.
    Wenn der User 0 eingegeben hat, bist du mit der Schleife fertig.

    Der Speicher wird nicht am Anfang auf einmal geholt sondern in der Schleife immer ewas mehr.

    realloc ist da sehr hilfreich, da es die alten Daten an die neue Stelle kopiert.
    ⚠ Auch realloc kann NULL zurückgeben wenn nicht genug Speicher vorhanden ist.



  • int i, j, a=0, b=1;
        float *temp, k;
        temp = (float *) malloc(b * sizeof(float));
        while(temp[a]!=0)
                    {
                    temp= (float *) realloc(b * sizeof(float));
                    printf("Bitte geben Sie eine Temperatur ein!\n 0 beendet die Eingabe:\n");
                    scanf("%d", &temp[a]);
                    a++;
                    }
    

    bekomme folgende fehler:

    error: too few arguments to function 'realloc'|
    warning: passing argument 1 of 'realloc' makes pointer from integer without a cast|

    ich will oben zunächst mal 1 speicherstelle für den temp array zuweisen mit malloc. danach in der schleife mit realloc immer weiter zuweisen, bis die eingabe von temp[a] == 0. An was liegt das?



  • also ich habe nun die eingabe hinbekommen, sodass ich beliebig viele temperaturen eingeben kann.

    int main()
    {
        int i, j, a=0, b=1;
        float *temp, k;
        temp = (float *) malloc(b * sizeof(float));
        while(*temp!=0.0)
                    {
                    realloc(temp, b);
                    printf("\nTemperatur %d (0 beendet die Eingabe):", a+1);
                    scanf("%d", &temp[a]);
                    a++;
                    }
    

    jedoch bricht er mir bei "0" noch nicht ab. AN was könnte das liegen?



  • Du rufst realloc immer mit b=1 auf. Wie soll das funktionieren? Du vergrößerst den Puffer nicht. In deinem gesamten Code ist keine Stelle, die b nach der Initialisierung verändert.

    Deine Abbruchbedingung für die Schleife schaut immer nur auf den ersten Wert und vergleicht den mit 0.0. Wenn du sofort 0 eingibst, bricht die Schleife auch ab. Würdest du allerdings mehrere Werte eingeben und weiter hinten irgendwann 0, dann kriegt deine Abbruchbedingung das nicht mit. Aber mehrere Werte zu erfassen, ist sowieso nicht sinnvoll, weil du ab Wert 2 über den gültigen Speicher hinaus schreibst. 😉

    Variablen sollten immer sinnvoll benannt werden. a und b sind nicht sinnvoll. Es ist am Namen überhaupt nicht ersichtlich, was der Zweck dieser Variablen ist.



  • !beliebig schrieb:

    beliebig - wunschdenken.
    die ressourcen eines rechners sind begrenzt. du hast nicht beliebig viel speicher.

    Völlig unnötig zu erwähnen. Hilf ihm lieber. 🙄



  • Außerdem nutzt du den von realloc besorgten Speicher gar nicht.
    Ich habe mir extra dei Mühe gemacht und den Link zu einer Referenz gepostet.

    realloc gibt einen Wert zurück. Genau wie malloc auch.

    Und wenn du die Beiträge hier gründlich gelesen hättest, würdest du auch auf den cast bei malloc verzichten.


  • Mod

    _matze schrieb:

    !beliebig schrieb:

    beliebig - wunschdenken.
    die ressourcen eines rechners sind begrenzt. du hast nicht beliebig viel speicher.

    Völlig unnötig zu erwähnen. Hilf ihm lieber. 🙄

    Ach, einfach ignorieren. Mittlerweile bin ich dazu übergegangen, groben Unsinn* einfach stillschweigend zu löschen, aber manchmal sehe ich es nicht schnell genug.

    *: Auch ernst gemeinten Unfug (z.B. Sone an einem schlechten Tag), Trollerei natürlich sowieso.



  • Immer, wenn du eine dir unbekannte Funktion verwenden willst, solltest du erst mal einen Blick in die Doku werfen. Dort gibt es eine Beschreibung der Parameter, der Rückgabewerte, allgemeinen Text zur Verwendung und sogar noch ein Beispiel. Wer die Doku fleißig liest, macht deutlich weniger Fehler und kommt schneller voran. Lohnt sich also eher als reines Ausprobieren. 🙂

    @SeppJ: Ja, hast wohl Recht. Manchmal fällt mir das Ignorieren einfach schwer. Lösch' halt schneller! 😉


Anmelden zum Antworten