Zweidimensionales Array erstellen (mit malloc)



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



  • Nein, auf Zeile 18.



  • Big Brother schrieb:

    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.

    Ich hatte das jetzt so verstanden, dass in Zeile 18
    Bezeichnung[100][20];
    und
    Bezeichnung2 = (char*) malloc(laenge*20*sizeof(char));
    verglichen werden, die nach anderem Schema erzeugt werden, was nicht funktioniert.
    Habe ich mich da geirrt?


  • Mod

    Verglichen? Nein, da wird das eine in das andere kopiert.

    Dein Problem ist, dass du Bezeichner und Bezeichner2 auf unterschiedliche Weise erzeugt hast. Na gut, eigentlich ist das kein Problem. Aber du benutzt sie beide gleich. Bei Bezeichner hast du dem Compiler mit [100][20] gesagt, dass du 100 mal 20 Elemente haben willst. Bei Bezeichner2 hast du gesagt, dass du einmal 2000 Elemente haben willst. Daher bezieht sich Bezeichner[i] auf das insgesamt i*20-te Element. Bezeichner2[i] hingegen ist wirklich nur das i-te Element, weil der Compiler keine Ahnung hat, dass du dir die 2000 Elemente als 100*20 vorstellst. Das musst du ihm schon irgendwie klarmachen, dass du mit Bezeichner2[i] eigentlich das i*20-te Element meinst.

    P.S.: Kleiner Tipp: Die Lösung ist nicht schwer, ich hab's quasi schon hingeschrieben. Ich will nur, dass du nochmal drüber nachdenkst, damit du es beim nächsten Mal auch alleine hinbekommst.

    :hoppschwiiz:



  • Ich doktore dadran jetzt einige Zeit rum und habe (glaube ich) zwei Lösungen gefunden:
    entweder erzeuge ich das Array auf dieselbe Art, auf die mein "Grundarray" erstellt wurde, wie vorher zuwähnt:

    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));

    Oder ich finde einen Weg das 2000er Feld in 100*20er Felder aufzuteilen.
    Soweit richtig?



  • Ja.
    Etwas eleganter wäre noch
    int **myPtr = calloc(5,sizeof(int*));


Anmelden zum Antworten