Как мне динамически выделить массив строк в C?

#c

#c

Вопрос:

Если у меня есть количество элементов в переменной с именем «totalstrings» и переменная с именем «размер строки», которая является размером строки каждого элемента, как мне динамически выделить массив с именем «массив»?

Это массив строк на C, а не на C .

Спасибо!

Комментарии:

1. Это зависит от того, что вы, возможно, пробовали, а что не сработало.

2. И, конечно, почему вы думаете, что это не сработало.

Ответ №1:

ПРИМЕЧАНИЕ: мои примеры не проверяют нулевые возвраты из malloc() … вам действительно следует это сделать; вы потерпите крах, если попытаетесь использовать нулевой указатель.

Сначала вам нужно создать массив указателей символов, по одному для каждой строки (char *):

char **array = malloc(totalstrings * sizeof(char *));

Далее вам нужно выделить место для каждой строки:

 int i;
for (i = 0; i < totalstrings;   i) {
    array[i] = (char *)malloc(stringsize 1);
}
  

Когда вы закончите использовать массив, вы должны запомнить free() каждый из выделенных вами указателей. То есть перебирать массив, вызывая free() каждый из его элементов, и, наконец free(array) , также.

Комментарии:

1. Но malloc возврат NULL обычно является слишком серьезной ошибкой, чтобы продолжать, в любом случае. Мы же не хотим быть чрезмерно параноидальными, не так ли? И что действительно неправильно, так это приведение malloc возвращаемого значения, которое в C совершенно не нужно и обычно является плохой практикой (но неважно, я тоже из C -фона). В противном случае хороший ответ. 1 для правильного free запоминания.

2. Действительно, в C приведение результата malloc может быть опасным, если кто-то забудет включить <stdlib.h> . Хороший ответ в противном случае.

3. Что, если каждая строка имеет разный размер, скажем, я пытаюсь сохранить список имен

4. @Aadishri это не проблема; вам не нужно, чтобы каждая строка malloc была одинакового размера, вы можете изменять их размер по своему усмотрению.

5. @sivaram для начала у вас должно быть хотя бы начальное количество строк, и вы захотите сохранить переменную с текущим размером вашего массива. Если вам позже понадобится расширить пространство, вы можете realloc() увеличить свой массив до большего размера.

Ответ №2:

Общая идиома для выделения массива N на M любого типа T:

 T **a = malloc(N * sizeof *a);
if (a)
  for (i = 0; i < N; i  )
    a[i] = malloc(M * sizeof *a[i]);
  

Начиная со стандарта 1989 года, вам не нужно приводить результат malloc , и фактически это считается плохой практикой (это может подавить полезную диагностику, если вы забудете включить stdlib.h или иным образом не имеете прототипа для malloc in scope). Более ранние версии C malloc возвращали char * возврат, поэтому приведение было необходимо, но вероятность того, что вам придется работать с компилятором до 1989 года, на данный момент довольно мала. C требует приведения, но если вы пишете C , вы должны использовать new оператор.

Во-вторых, обратите внимание, что я применяю sizeof оператор к выделяемому объекту; тип выражения *a равен T * , а тип *a[i] равен T (где в вашем случае T == char ). Таким образом, вам не нужно беспокоиться о синхронизации sizeof выражения с типом выделяемого объекта. Итак, если вы решите использовать wchar вместо char , вам нужно внести это изменение только в одном месте.

Ответ №3:

 char** stringList = (char**)malloc(totalStrings * sizeof(char*));

for( i=0; i<totalStrings; i   ) {
  stringList[i] = (char*)malloc(stringSize[i] 1);
}
  

Ответ №4:

Я знаю, что этот вопрос старый и на него уже был дан ответ. Я просто хочу указать, что malloc это системный вызов, и его не следует использовать несколько раз.

Было бы лучше выделить один большой кусок памяти и сделать так, чтобы массив указывал на него. Что-то вроде этого :

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

#define STR_SIZE 100 //STR_SIZE doesn't have to be a constant

int main(){
        int i;
        char **arr;
        char *long_string;
        long_string = (char *)malloc(sizeof(char)*STR_SIZE*10);
        arr = malloc(sizeof(char *)*10);

        //Pointing each item of the array to an allocated memory. 
        for (i=0; i<10; i  ){
                arr[i] = (long_string   STR_SIZE * i);
        }

        //Initialising the array
        for (i=0; i<10; i  ){
                strcpy(arr[i], "This is a line in a
 paragraphn");
        }

        //Printing the items of the array
        for (i=0; i<10; i  ){
                printf("%s n", arr[i]);
        }

        //freeing the allocated memory
        free(long_string);
        free(arr);

        return 0;
}
  

Ответ №5:

Ну, сначала вы можете выделить место для «массива», который будет представлять собой массив символов * длиной «totalstrings».

Какими тогда будут начальный и конечный индексы в «массиве»? Вы знаете, что первый равен 0; какой последний?

Затем для каждой записи в «массиве» вы могли бы (если хотите) выделить одну область памяти, которая равна «stringsize 1» (почему 1, скажите, пожалуйста?) длинный, вводящий начальный адрес этой области — этой строки — в правильный элемент «массива».

Это было бы хорошим началом, imo.