2009-10-06 18 views
0

Ce que j'essaye de faire est de créer un tableau bidimensionnel de chaînes de caractères Les erreurs de segmentation suivantes immédiatement, quel est le problème?tableau de charmes multidimensionnels?

void add2(char***b, char *i) 
{ 
    if (!i) { 
     b[0][0] = (char*) malloc(120); 
     sprintf(b[0][0], "%s", "hithere"); 
     b[0][1] = (char*) malloc(120); 
     sprintf(b[0][1], "%s", "bithere"); 
    } else { 
     strcat(b[0][0], "\\\\"); 
     strcat(b[0][0], i); 
     strcat(b[0][1], "\\\\"); 
     strcat(b[0][1], i); 
    } 

} 
void add1(char ***b) 
{ 
add2(b,NULL); 
add2(b,"one"); 
add2(b,"two"); 
add2(b,"three"); 
} 

int main() 
{ 
char **keys[2] = {0}; 
int i,j; 

add1(keys); 

for (i = 0; keys[i]; i++) 
    for (j = 0; keys[j]; j++) 
    { 
     fprintf(stderr, "%s\n", keys[i][j]); 
     free(keys[i][j]); 
    } 

} 

Répondre

2

Lorsque vous déclarez les clés du tableau que vous dites au compilateur que vous voulez travailler avec un tableau de 2 pointeurs de pointeurs vers les caractères et lui demander d'initialiser les pointeurs de pointeur vers un char à NULL. Tous les bons.

Ensuite, vous appelez add1(). Tous les bons.

Puis vous appelez add2() et essayez de mettre dans le premier élément de b[0] la valeur de retour de malloc(). Mais la valeur de b[0] est NULL. La valeur NULL a été ajoutée à la fonction main(). b[0] n'a pas d'éléments!

Lorsque vous avez tableaux de tableaux (de tableaux ...)sous forme de pointeurs vous devez malloc() (et free()) tous les niveaux individuellement.


Modifier

#include <stdlib.h> 

int main() 
{ 
    char **keys[2] = {0}; 
    keys[0] = malloc(20 * sizeof *keys[0]); /* 20 strings */ 
    keys[1] = malloc(20 * sizeof *keys[1]); /* 20 strings */ 

    for (int k=0; k<20; k++) { 
     keys[0][k] = malloc(120); /* string with 119 chars + '\0' */ 
     keys[1][k] = malloc(120); /* string with 119 chars + '\0' */ 
    } 

    /* use k[0][0] through k[0][19] */ 
    /* use k[1][0] through k[1][19] */ 

    for (int k=0; k<20; k++) { 
     free(keys[0][k]); 
     free(keys[1][k]); 
    } 
    free(keys[0]); 
    free(keys[1]); 

    return 0; 
} 

Je mets tout dans la fonction main(), mais c'est la même idée si les malloc() s et free() s sont dans leur propre fonction.

+0

alors comment puis-je malloc b [0] à b [n]? – user105033

+0

malloc (sizeof (char *) * n)? c'est ma conjecture, je peux me tromper. – pxl

+1

@pxl: pour être précis, il devrait être 'malloc (sizeof (char **) * n);', mais en pratique 'sizeof (char **)' est le même que 'sizeof (char *)' . C'est la raison principale pour laquelle j'aime utiliser 'sizeof' avec la chose pour laquelle je suis en train d'allouer la mémoire:' pointer = malloc (n * sizeof * pointer); '.Peu m'importe si le pointeur pointe vers un tableau de structures ou une structure avec des tableaux ou quoi que ce soit; le 'malloc()' obtient toujours la bonne taille :) – pmg

1

La procédure générale d'allocation dynamique un tableau 2D de char * est quelque chose comme ça (pour tout autre type T, remplacez char * avec le type désiré):

char ***new2DArr(size_t rows, size_t cols) 
{ 
    char ***newArr = NULL; 
    size_t i; 
    newArr = malloc(sizeof *newArr * rows); 
    if (newArr) 
    { 
    for (i = 0; i < rows; i++) 
    { 
     newArr[i] = malloc(sizeof *newArr[i] * cols); 
     if (newArr[i]) 
     { 
     /* initialize or assign newArr[i][0] - newArr[i][cols-1] here */ 
     } 
    } 
    } 
    return newArr; 
} 

Cela suppose que vous savez combien de lignes et de colonnes vous voulez à l'avance. Notez que vous avez alloué une table de pointeurs; vous devrez toujours allouer de la mémoire pour chaque entrée de chaîne, comme ceci:

char **myArr = new2DArr(10, 10); 
myArr[0][0] = malloc(strlen("Hello, World") + 1); 
if (myArr[0][0]) 
{ 
    strcpy(myArr[0][0], "Hello, World"); 
} 

Si vous voulez ajouter de nouvelles lignes ou de nouvelles entrées à des lignes existantes, vous allez devoir faire un peu de comptabilité supplémentaire.

est ici un exemple qui étend une seule ligne:

char **extendRow(char **row, char *newEntry, size_t *numEntries) 
{ 
    char **tmp = realloc(row, *numEntries + 1); 
    if (tmp) 
    { 
    row = tmp; 
    row[*numEntries] = malloc(strlen(newEntry) + 1); 
    if (row[*numEntries]) 
    { 
     strcpy(row[*numEntries], newEntry); 
     (*numEntries)++; 
    } 
    } 
    return row; 
} 

Et vous l'appelez comme

table[i] = extendRow(table[i], "This is a test", &entryCount); 

Le résultat est réaffecté à table[i] dans le cas où la valeur du pointeur est modifiée par realloc(). Je le fais de cette façon au lieu de passer un pointeur sur la table [i] juste pour garder la gymnastique du pointeur au minimum.