Zweidimensionales Array erstellen (mit malloc)



  • Moin,
    Ich habe zur Zeit das Problem, dass ich ein zweidimensionales Array erstellen möchte. Wie man ein eindimensionales Array im Sinne von:

    int *Array1;
    Array1 = (int*) malloc(laenge*sizeof(int));
    

    erstellt, nun möchte ich ein Array wie:

    char Woerter[100][20];
    

    erstellen, kann mir bitte jemand sagen wie das funktioniert?

    Danke und Gruß
    Metalmind



  • Für int[5][3]

    int **myPtr = malloc(5*sizeof(int*)); // erste Dimension
    myPtr[0] = malloc(3sizeof(int));
    myPtr[1] = malloc(3
    sizeof(int));
    myPtr[2] = malloc(3sizeof(int));
    myPtr[3] = malloc(3
    sizeof(int));
    myPtr[4] = malloc(3*sizeof(int));

    Nicht vergessen für sämtliche malloc() Aufrufe auch free() aufzurufen:
    free(myPtr[4]);
    free(myPtr[3]);
    free(myPtr[2]);
    free(myPtr[1]);
    free(myPtr[0]);
    free(myPtr);


  • Mod

    Wie du siehst spricht bei der von JanJan gezeigten Methode auch nichts dagegen, nicht-rechteckige Arrays zu erstellen. Gut zu wissen, falls man das mal braucht.



  • Danke für die schnelle Hilfe, ich habe jetzt:

    int **myPtr = malloc(laenge*sizeof(int*)); // erste Dimension
    
    for(i=0;i<laenge;i++){
    myPtr[i] = malloc(3*sizeof(int));
    }
    

    erstellt, da ich nicht weiß wie viele "erste Dimensions"-Arrays ich brauche, geht das so auch?

    SeppJ schrieb:

    Wie du siehst spricht bei der von JanJan gezeigten Methode auch nichts dagegen, nicht-rechteckige Arrays zu erstellen. Gut zu wissen, falls man das mal braucht.

    Soweit bin ich scheinbar noch nicht, meinst du damit mehr als zweidimensionale?


  • Mod

    Metalmind schrieb:

    SeppJ schrieb:

    Wie du siehst spricht bei der von JanJan gezeigten Methode auch nichts dagegen, nicht-rechteckige Arrays zu erstellen. Gut zu wissen, falls man das mal braucht.

    Soweit bin ich scheinbar noch nicht, meinst du damit mehr als zweidimensionale?

    Nein, ich meine, dass die Arrays nicht unbedingt alle gleich lang zu sein brauchen. Z.B:

    int **myPtr = malloc(2*sizeof(int*)); 
    myPtr[0] = malloc(3*sizeof(int));
    myPtr[1] = malloc(1000*sizeof(int));
    

    Dann geht myPtr[0] von myPtr[0][0] bis myPtr[0][2] und myPtr[1] geht von myPtr[1][0] bis myPtr[1][999].



  • Achso, stimmt, das ist wirklich parktisch!
    Danke an euch beide, ich werde das gleich mal ausprobieren!



  • Wenn Nichtrechteckigkeit nicht erforderlich ist, kann man aber auch einfach ein normales zweidimensionales Array machen, für das dann ein malloc reicht:

    char (*Woerter)[20];
    Woerter = malloc(100 * sizeof *Woerter);
    


  • Es geht auch noch einfacher und noch schneller
    (jedoch nur für rechteckige arrays)

    anlegen:

    int *Array1;
    Array1 = (int*) malloc(breite*laenge*sizeof(int));
    

    schreiben:

    *(Array1 + y * breite + x) = value;
    

    lesen:

    int value = *(Array1 + y * breite + x);
    

    freigeben:

    free (Array1);
    

    Gruß Frank



  • Also bei einem Array1[5][5] wäre es dann

    int *Array1;
    Array1 = (int*) malloc(5*5*sizeof(int));
    

    richtig? Würde er da nicht einfach die beiden Zahlen multiplizieren?

    Sorry, aber was meinst du mit:

    *(Array1 + y * breite + x) = value;
    

    Den Teil verstehe ich nicht ganz.

    Danke schonmal für die vielen Möglichkeiten 😃



  • SeppJ schrieb:

    Wie du siehst spricht bei der von JanJan gezeigten Methode auch nichts dagegen, nicht-rechteckige Arrays zu erstellen.

    Nicht- rechteckig? Alter Seppl, wie sehen denn nicht- rechteckige Arrays aus? 😃

    Abgesehen davon, daß quadratisch und rechteckig schwer als Obermenge und Teilmenge auszumachen sind, hatten wir das Thema gefühlte 3000 mal hier, seit ich reg bin.

    Sowas gehört doch bitte endlich in die FAQ. 🙄



  • Metalmind schrieb:

    Also bei einem Array1[5][5] wäre es dann

    int *Array1;
    Array1 = (int*) malloc(5*5*sizeof(int));
    

    richtig? Würde er da nicht einfach die beiden Zahlen multiplizieren?

    korrekt,
    Er reserviert dann 25 Plätze für int, 5 * 5 * sizeof (int) eben.

    Sorry, aber was meinst du mit:

    *(Array1 + y * breite + x) = value;
    

    Den Teil verstehe ich nicht ganz.

    * -> inhalt (Dereferenzierung)
    (Array1 + y * breite + x) -> Pointer Arithmetik um die Adresse im Feld zu ermitteln.
    Wobei Array1 der Anfang des Feldes ist.
    y die Zeilenposition
    x die Spaltenposition
    breite die Breite des Feldes ist

    anders:
    diese Codezeile soll den Inhalt einer mit y und x angegeben Position
    im Feld mit dem Wert 'value' setzen.

    Gruß Frank

    @PointerCrash
    'nicht rechteckige arrays' ist schon ein schöner Ausdruck,
    ich hatte sofort verstanden was gemeint war 😉



  • Dieses umständliche manuelle Indexberechnen kann man sich aber sparen, wenn man gleich ein zweidimensionales Array erzeugt wie in meinen Betrag oben. Dabei passiert ja letztendlich nichts anderes (der erzeugte Code ist wahrscheinlich der selbe), aber man kann das Array ganz normal wie ein statisches zweidimensionales Array verwenden, und der Compiler erledigt die Zeigerarithmetik.

    Manuell machen muss man es nur, wenn die "Breite" erst zur Laufzeit bekannt ist und man keine variable-length arrays (die es ja erst seit C99 gibt) verwenden kann/will.



  • Ihr meintet dies Funktioniert nur für rechteckige Arrays, heißt das ich kann statt

    int *Array1;
    Array1 = (int*) malloc(5*5*sizeof(int));
    

    nicht

    int *Array1;
    Array1 = (int*) malloc(100*20*sizeof(int));
    

    benutzen?



  • ein Quadrat ist auch rechteckig,
    vergiss den irreführenden Ausdruck
    es geht sowohl

    Array1 = (int*) malloc(5*5*sizeof(int));
    

    als auch:

    Array1 = (int*) malloc(100*20*sizeof(int));
    

    Gruß Frank



  • Ich habe nun solch ein Array erstellt, scheitere aber leider am beschreiben, mein Code sieht so aus:

    char Bezeichnung[100][20];
    int laenge;
    laenge=0;
    
    do
    {
        error = fscanf(data1,"%s",&Bezeichnung[laenge]); //Daten werden dynamisch eingelesen
        laenge++;    //um die Anzahl der Datensätze zu zählen    //laenge ist hierbei 10
    }
    while (error != EOF);    //Bis die Datei am Ende ist
    
    int main(void)
    {
    ...
    char *Bezeichnung2;
    Bezeichnung2 = (char*) malloc(laenge*20*sizeof(char));
        for(i=0;i<laenge;i++){  
            strcpy(&Bezeichnung2[i],Bezeichnung[i]);    //hier wird die Datei beschrieben
        }
    
    for(i=0;i<laenge;i++){
        printf("%s\n",&Bezeichnung2[i]);
    }
    

    Dabei wiederholt sich bei der Ausgabe nun der erste Buchstabe des erst Wortes 9 mal, so das dort z.b. "NNNNNNNNNummer" steht, beim zweiten mal 8 mal, dann 7...
    Kann sich das jemand erklären? Ich bin dankbar für jede Hilfe!

    Gruß!
    Metalmind


  • Mod

    Mach dir mal Gedanken darüber, was Bezeichnung2 ist und wie sich Bezeichnung2[i] und Bezeichnung2[i+1] zueinander verhalten. Dann dürftest du relativ flott drauf kommen.



  • Mit den Zeigeroperationen bin ich noch am lernen, ich bin mir relativ sicher dass der Fehler in Zeile 18 sitzt, aber nicht wo genau, kann mir jemand vielleicht einen Tipp geben?
    Gruß
    Metalmind



  • Metalmind schrieb:

    ich bin mir relativ sicher dass der Fehler in Zeile 18 sitzt

    Das kommt darauf an wie du dich entschieden hast, dein Array zu erzeugen und die Elemente darin zu adressieren.
    Die Adressierung der Elemente kann prinzipiell so

    array[zeile][spalte]
    

    oder so

    array[y*spaltenbreite+x];
    

    aussehen.



  • Du machst ne Art Mischung beider Varianten, das geht so nicht.



  • Du beziehst dich jetzt auf diese Zeile:

    Bezeichnung2 = (char*) malloc(laenge*20*sizeof(char));
    

    richtig?


Anmelden zum Antworten