开发者

multi dimensional char array?

What I am trying to do is create an 2-d array of character strings The following seg faults instantly, what is wrong?

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], "\\\\");
       strc开发者_运维技巧at(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]);
     }

}


When you declare the array keys you are saying to the compiler that you want to work with an array of 2 pointers to pointers to chars and ask it to initialize those pointers to pointer to char to NULL. All good.

Then you call add1(). All good.

Then you call add2() and try to put into the first element of b[0] the return value from malloc(). But the value of b[0] is NULL. The NULL was put there in the main() function. b[0] has no elements!

When you have arrays of arrays (of arrays ...) in the form of pointers you need to malloc() (and free()) every level individually.


Edit

#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;
}

I put it all in the main() function, but it's the same idea if the malloc()s and free()s are in their own function.


The general procedure for dynamically allocating a 2D array of char * is something like this (for any other type T, replace char * with the desired type):

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

This assumes you know how many rows and columns you want ahead of time. Note that you have allocated a table of pointers; you will still have to allocate memory for each string entry, like so:

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

If you want to add new rows or new entries to existing rows, you're going to have to do some extra bookkeeping.

Here's one example that extends a single row:

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

And you'd call it like

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

The result is assigned back to table[i] in the event that the pointer value is changed by realloc(). I'm doing it this way instead of passing a pointer to table[i] just to keep the pointer gymnastics to a minimum.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜