Если вы заранее знаете, сколько строк вам понадобится (назовите это M) и максимальную длину для каждой строки (назовите это N), тогда вы просто объявите двумерный массив char:
#define M ... // number of strings
#define N ... // max length of each string
struct someStruct
{
char someStrings[M][N+1]; // +1 for 0 terminator
...
};
Если вы не знаете, сколько строк вам понадобится, но знаете максимальную длину, вы можете объявить указатель на массив символов:
#define N ...
struct someStruct
{
char (*someStrings)[N+1];
size_t numStrings;
...
};
Затем, когда вам нужночтобы выделить массив строк, вы должны сделать что-то вроде:
struct someStruct s = {NULL, 0};
size_t count = getNumStrings();
s.someStrings = malloc(sizeof *s.someStrings * count);
if (s.someStrings)
s.numStrings = count;
И теперь вы можете обрабатывать someStrings
как массив строк:
strcpy(s.someStrings[i], "foo");
printf("%s\n", s.someStrings[j]);
s.someStrings[i][j] = 'a';
Когда вы закончитес массивом освободите память следующим образом:
free(s.someStrings);
ПРИМЕЧАНИЕ : при работе с указателями на массивы вы должны разыменовывать указатель перед применением индекса;учитывая код
T (*a)[N];
a = malloc(sizeof *a); // allocates a single N-element array of T
, вам обычно нужно написать (*a)[i]
для правильного доступа к i-му элементу массива (*a[i]
анализируется как *(a[i])
, что здесь не так),Помните, однако, что a[0]
эквивалентно *a
;применение индекса к a
неявно разыменовывает его, поэтому a[0][i]
эквивалентно (*a)[i]
.Если бы мы выделяли его как
a = malloc(sizeof *a * M); // allocates M N-element arrays of T
, то мы могли бы ссылаться на каждый массив как a[0]
, a[1]
и т. Д., А каждый элемент каждого массива - как a[0][0]
, a[0][1]
и т. Д.почему вы не видите указателя гимнастики в коде выше.
Если вы не знаете, сколько строк или максимальная длина каждой строки, вам придется выполнить двухэтапное распределение, например так:
struct someStruct
{
char **someStrings;
size_t numStrings;
size_t maxLength;
};
struct someStruct s = {NULL, 0, 0};
size_t count = getNumStrings();
s.maxLength = getMaxLength();
s.someStrings = malloc(sizeof *s.someStrings * count);
if (s.someStrings)
{
size_t i;
s.numStrings = count;
for (i = 0; i < s.numStrings; i++)
{
s.someStrings[i] = malloc(sizeof *s.someStrings[i] * s.maxLength + 1);
if (s.someStrings[i])
// initialize string value here
}
}
Опять выможет обрабатывать someStrings
как обычный двумерный массив:
strcpy(s.someStrings[i], "foo");
printf("%s", s.someStrings[j]);
s.someStrings[i][j] = 'a';
Подобно выделению, освобождение происходит в два этапа:
for (i = 0; i < s.numStrings; i++)
free(s.someStrings[i]);
free(s.someStrings);
Обратите внимание, что в отличие от первых двух методов, этот методне гарантирует, что строки являются смежными в памяти.
Вы должны будете отслеживать количество строк и максимальную длину каждой строки вручную;нет способа получить эту информацию из одних только значений указателя.