Если вы знаете заранее, сколько строк вам понадобится (назовем его М) и максимальная длина для каждой строки (назовем его N), то вы бы просто объявить 2D массив полукокса:
#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;
...
};
Затем, когда вам нужно Распределяйте string array, вы бы сделали что-то вроде:
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
, как обычный 2D массив:
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);
Обратите внимание, что в отличие от первых двух методов этот метод не гарантирует непрерывность строк в памяти.
Вам нужно будет отслеживать количество строк и максимальную длину для каждой строки вручную; невозможно получить эту информацию только из значений указателя.
Вы хотите ограничить someString, чтобы удерживать десять строк или каждую строку, чтобы удерживать десять символов? – mkb
каждая строка, чтобы удерживать десять символов – jarryd
Я не думаю, что вы действительно можете сделать это на C, а не автоматически. Размер массива не является частью его типа (например, в Go). – mkb