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.
精彩评论