dynamische mehrdimensionale Arrays [C]



  • Wutz ich denke da hast du Recht, mit normalen Arrays hätte man diese Probleme nicht 🙂 trozdem möchte ich dieses Problem irgendwie lösen 😃

    DirkB danke für den Hinweis, ich habe es irgendwie ganz verschlafen, das ich durch die Funktion einen pointer dazurechnen sollte

    ist jedoch bei richtiger speicherzuweisung die Funktion richtig?

    void setName(sturct Member *m, char ***name)
    {
    
    name =& m->membername;
    
    while(m->member)
    {
    m->member++; // ist diese vorgehensweise richtig?
    }
    return(name);
    }
    
    int main()
    {
    
    m = malloc(sizeof(struct Member));
    m->member= malloc(sizeof(char**));
    m-membername = malloc(sizeof(char*));
    
    m-membername =& m->member;
    
    setName(m, "Name");
    printf("%s", m->member);
    
    return 0;
    }
    


  • Deine struct ist schon falsch. Zumindest zu dem Vorhaben, wie du es erklärt hast.

    struct Member
    {
    char **member;
    char *membername;
    };
    

    Und beachte auch unbedingt die Compiler-Warnungen nicht nur die Fehler.

    void setName(sturct Member *m, char ***name)
    {
    ...
    return(name);  // Dann merkst du auch so was. return mit Wert bei einer void-Funktion
    }
    
    m->member++; // ist diese vorgehensweise richtig?
    

    Nein, denn meber zeigt auf einen mit malloc besorgten Speicherbereich.
    Die Information wo dieser liegt geht dadurch verloren.
    Dann funktioniert das free() nicht mehr und du bekommst Speicherlecks. Dein Programm/Computer stürzt ab.



  • dimi_C schrieb:

    trozdem möchte ich dieses Problem irgendwie lösen 😃

    das ist auch gut so, denn es gibt fälle, in denen ein 'nomrales' array
    nicht ausreicht.
    prinzipiell kannst du das mit einem char** machen.
    hier ohne prüfung der rückgabewerte

    char** names = malloc ( 10 * sizeof(char* ); // für 10 namen
    for ( i=0; i < 10; i++ )
        names[i] = malloc(16); // für einen namen mit maximal 15 zeichen.
    

    verwendung

    strcpy(names[0], "sinnvollernick");
    strcpy(names[1], "gustav gans");
    puts(names[0]);
    

    sicherlich musst du die anzahl irgendwo speichern, das alles lässt sich gut in einer struktur unterbringen.
    sieht dann auch nicht viel anders aus

    meine_instanz.names = malloc ...
    

    weiterhin happy coding.
    mfg



  • Mit "normalen Arrays" hätte man nicht nur diese Probleme nicht, das Ganze wäre auch noch schneller... 😉



  • alles klar ich habe mein Problem verstanden

    ich werde es mit einer matrix machen

    int i = 7;
    
    char **member = malloc(8 * sizeof(char*));
    
    while(i--)
    {
    member[i] = malloc(20 * sizeof(char));
    }
    

    somit wird ein speicherblock erstellt mit einem member mit 20 char

    somit ist das hauptproblem eigentlich erledigt,

    viel dank DirkB



  • vielen dank für euere Hilfe 😃



  • dot schrieb:

    Mit "normalen Arrays" hätte man nicht nur diese Probleme nicht, das Ganze wäre auch noch schneller... 😉

    die 'normalen arrays' kann man aber nicht immer verwenden, z.b.
    bei großen datenmengen.



  • Ich meinte damit natürlich einen einfachen, linearen Speicherbereich anstatt sowas fragmentiertes...



  • Für chars ist das ziemlich einfach in einem Stück zu haben:

    char **two_dimensional_char_array(size_t x, size_t y) {
      size_t i;
      char **index;
    
      index = malloc(sizeof(char*) * y + y * x);
    
      if(index != NULL) {
        for(i = 0; i < y; ++i) {
          index[i] = (char*) (index + y) + i * x;
        }
      }
    
      return index;
    }
    


  • Jepp nen linearen, zusammenhängenden Speicherbereich bekommt man ziemlich einfach.
    Der Speicherbedarf für die Zeiger typs char** kann eingespart werden.
    Die Indizierung geht in diesem Fall ein wenig anders als bei der 'zweidimensionalen' Allokation, hmm... umständlicher.
    Dafür hat man weniger mallocs und frees.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define NAMELEN_MAX 63
    
    int main(void)
    {
    	const size_t iterator_distance = NAMELEN_MAX + 1;
    	size_t names_count = 8, i;
    	char* linear_block = calloc ( names_count * ( NAMELEN_MAX + 1 ), 1 );
    
    	if ( linear_block == NULL )
    		return 0;
    
    	for ( i = 0; i < names_count; i++ )
    	{
    		char buf [ NAMELEN_MAX+1 ];
    		sprintf_s ( buf, sizeof ( buf ), "%u %s", i, "Johnny Flitzpiepe" );
    		strncpy ( linear_block + i * iterator_distance, buf, NAMELEN_MAX );
    	}
    
    	for ( i = 0; i < names_count; i++ )
    	{
    		puts ( linear_block + i * iterator_distance );
    	}
    
    	free ( linear_block );
    	system ( "pause" );
    
    	return 0;
    }
    


  • CJosef schrieb:

    const size_t iterator_distance = NAMELEN_MAX + 1;
        size_t names_count = 8, i;
        char* linear_block = calloc ( names_count * ( NAMELEN_MAX + 1 ), 1 );
     
    ...
       
        for ( i = 0; i < names_count; i++ )
        {
    ...
            strncpy ( linear_block + i * iterator_distance, buf, NAMELEN_MAX );
        }
    

    Furchtbar.

    sinnvollernick schrieb:

    char** names = malloc ( 10 * sizeof(char* ); // für 10 namen
    for ( i=0; i < 10; i++ )
        names[i] = malloc(16); // für einen namen mit maximal 15 zeichen.
    

    Furchtbar.

    dimi_C schrieb:

    int i = 7;
    
    char **member = malloc(8 * sizeof(char*));
    
    while(i--)
    {
    member[i] = malloc(20 * sizeof(char));
    }
    

    somit wird ein speicherblock erstellt mit einem member mit 20 char

    1 Speicherblock ja, aber noch nicht mal zusammenhängend und mit 8x malloc realisiert.
    Wenn man wie in deinem Fall eine konstante (max.) Stringlänge voraussetzen kann, nutzt man das aus und kommt mit 1x calloc UND einfacher Array-Schreibweise aus:

    char (*a)[21]=calloc(8,sizeof*a);
    int i;
    for(i=0;i<8;++i) *a[i]='1'+i;
    for(i=0;i<8;++i) puts(a[i]);
    ...
    free(a); /* auch nur 1x free notwendig */
    


  • Wutz schrieb:

    Furchtbar.

    Kommt da noch ne Begründung, oder willst du einfach nur wieder mal deinen Frust abladen?



  • Wutz schrieb:

    char (*a)[21]=calloc(8,sizeof*a);
    int i;
    for(i=0;i<8;++i) *a[i]='1'+i;
    for(i=0;i<8;++i) puts(a[i]);
    ...
    free(a); /* auch nur 1x free notwendig */
    

    Woher weiß free(a) denn eigentlich, dass das num-Argument des calloc eine 8 war, sprich, dass da 8 sizeof(*a) hintereinanderliegen und nicht eins oder 29786345?


  • Mod

    Schock schrieb:

    Woher weiß free(a) denn eigentlich, dass das num-Argument des calloc eine 8 war, sprich, dass da 8 sizeof(*a) hintereinanderliegen und nicht eins oder 29786345?

    Weil das malloc sich das gemerkt hat.



  • Merkt sich malloc "beliebig viel" oder nur seinen letzten Aufruf, sprich wäre Folgendes ok?

    int * a = Calloc(1,5);
    int * b = Calloc(2,5);
    int * c = Calloc(3,5);
    
    free(a);
    free(b);
    free(c);
    

    Wenn ja - wie macht es das, legt es sich eine dynamische Liste an, hat es einen vorgegebenen Buffer?





  • Vielen Dank. Ich hatte nur nach "wie funktioniert free()" gegoogelt; aber jetzt weiß ich ja, wer mir freundlich und kompetent zur Seite steht. 🤡



  • Wutz schrieb:

    [...]
    Furchtbar.

    Das ist gängige C-Praxis.
    Wenn es dir das Fürchten lehrt, dann ist C anscheinend nichts für dich.



  • Das ist gängige C-Pfuscherpraxis.
    Wie man es für den Fall vernünftig macht, habe ich gezeigt, hast du aber nicht verstanden.
    Lerne erstmal C.
    Lerne erstmal Deutsch. (Dativpronomen) Davon hast du nämlich auch keine Ahnung.
    Troll dich.



  • Wutz schrieb:

    Das ist gängige C-Pfuscherpraxis.
    Wie man es für den Fall vernünftig macht, habe ich gezeigt, hast du aber nicht verstanden.
    Lerne erstmal C.
    Lerne erstmal Deutsch. (Dativpronomen) Davon hast du nämlich auch keine Ahnung.
    Troll dich.

    im gegensatz zu dir, liebes wutz, bin ich nicht von einer im voraus bekannter, maximaler stringlänge ausgegangen.
    klar, habe ich konstanten, 16, 10 benutzt.
    das man diese aber durch variablen ersetzen kann, kapiert jeder anfänger nach wenigen minuten.
    tja, bloß du offensichtlich nicht.


Anmelden zum Antworten