multi dimensional char array?

我是研究僧i 提交于 2019-12-19 12:00:07

问题


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], "\\\\");
       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]);
     }

}

回答1:


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.




回答2:


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.



来源:https://stackoverflow.com/questions/1527806/multi-dimensional-char-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!