2013-09-12 5 views
2

Я хотел бы динамически выделять (таНос) многомерный массив символов в C. Массив будет иметь следующий формат: C Malloc многомерного массива символов

char *array[3][2] = { 
    {"one","two"}, 
    {"three","four"}, 
    {"five","six"} 
}; 

Перед тем как массив будет создан, я бы уже знать количество строк и длину всех массивов символов в многомерном массиве. Как бы я мог массировать такой массив символов?

Заранее благодарен!

+0

Существует простой способ просмотра и ответа на этот вопрос !! – JackCColeman

ответ

6

Это один из способов выделения двумерного массива char *.

Впоследствии вы можете назначить содержимое как [1] ​​[2] = "foo"; Обратите внимание, что элементы массива инициализируются (char *) 0.

#include <stdio.h> 
#include <stdlib.h> 

char ***alloc_array(int x, int y) { 
    char ***a = calloc(x, sizeof(char **)); 
    for(int i = 0; i != x; i++) { 
     a[i] = calloc(y, sizeof(char *)); 
    } 
    return a; 
} 

int main() { 
    char ***a = alloc_array(3, 2); 
    a[2][1] = "foo"; 
    printf("%s\n", a[2][1]); 
} 

[Charlies-MacBook-Pro:~] crb% cc xx.c 
[Charlies-MacBook-Pro:~] crb% a.out 
foo 
+0

Мне любопытно, почему голос? Есть ли способ лучше? –

+0

@CharlieBurns Да, этот код действительно делает именно то, что я хотел. Если, однако, как говорит SpaceDog, есть лучший способ сделать это, я хотел бы видеть это, прежде чем я выберу ответ. –

+0

@SheldonJuncker, я думаю, что этот ответ прекрасен и, вероятно, вы хотите (хотя могут быть разные решения, не использующие массивы в зависимости от реального приложения). – SpaceDog

1

char * array [3] [2] - не что иное, как двумерный массив указателей. Следовательно, для хранения указателей требуется пространство хранения 3 * 2 * sizeof (char *).

Как вы упомянули, указатели на самом деле указывают на строки с нулевым завершением, и вам может понравиться, что строки также должны быть malloc'ed. Предполагая, что общая длина всех строк равна N (включая нулевое завершение), требуется место для хранения (3 * 2 * sizeof (char *) + N).

Выделите память для вышеупомянутого размера и скопируйте строки как показано ниже.

В следующем коде, мы предполагаем, что число столбцов (2) является константой

char *(*dst)[2] = (char *(*)[2]) malloc(3*2*sizeof(char *) + N); 
char * s = ((char *) dst) + (3*2*sizeof(char *)); 
for (i = 0; i < 3; i++) 
{ 
    for (j = 0; j < 2; j++) 
    { 
     strcpy(s, src[i][j]); 
     dst[i][j] = s; 
     s += strlen(s)+1; 
    } 
} 

Примечание: В приведенном выше коде, «ДСТ» представляет собой указатель, который указывает на первую строку 2D-массив char *.

Если количество столбцов не является постоянным, синтаксис немного меняется, но размер хранилища тот же.

char **dst = (char **) malloc(3*2*sizeof(char *) + N); 
char * s = ((char *) dst) + (3*2*sizeof(char *)); 
for (i = 0; i < 3; i++) 
{ 
    for (j = 0; j < 2; j++) 
    { 
     strcpy(s, src[i][j]); 
     dst[i*2 + j] = s; /* 2 is the number of columns */ 
     s += strlen(s)+1; 
    } 
} 

Примечание: Здесь «ДСТ» указатель, который указывает на первый элемент массива 1D символ * и 2D индексации осуществляется вручную.

В приведенных выше примерах предполагается, что длины строк не будут изменены после выделения. Если строки могут меняться в любой момент времени после выделения, то лучше выделять для каждой строки отдельно.

1

Прежде всего, массивы обычно хранятся в форме строки, поэтому на самом деле у вас есть вектор длиной шесть элементов, каждая запись - это char * ptr.То есть, элементы, обозначенные по строкам, колонки подобны:

char *r1c1, *r1c2, *r2c1, *r2c2, *r3c1, *r3c1; 

Таким образом, сделать SIMPLE таНос из:

char *matrix = malloc(3*2*sizeof(char *)); 

Затем установите элементы, как:

matrix[0] = "one"; 
matrix[1] = "two"; 
matrix[2] = "three"; 
matrix[3] = "four"; 
matrix[4] = "five"; 
matrix[5] = "six"; 

Наконец, чтобы проверить это, напишите вложенный цикл как:

for (r=0; r<3; r++) 
{ 
    for (c=0; c < 2; c++); 
    { 
    print("%s\n,matrix[r][c]); 
    } 
} 

Обратите внимание, как maxtrix обрабатывается сначала как вектор, а затем как матрица. C не волнует !!

0

Держите его простым, Шелдон. Выбранный ответ использует char ***, который даже не близок к эквиваленту char *[2][3]. Разница заключается в количестве распределений ... Массив только когда-либо требует один.

Например, вот как я хотел бы подобрать ответ, который вы выбрали. Заметьте, насколько проще это?

#include <stdio.h> 
#include <stdlib.h> 

void *alloc_array(size_t x, size_t y) { 
    char *(*a)[y] = calloc(x, sizeof *a); 
    return a; 
} 

int main() { 
    char *(*a)[2] = alloc_array(3, 2); 
    a[2][1] = "foo"; 
    printf("%s\n", a[2][1]); 
} 
Смежные вопросы