назначение массива во время выполнения для массива массивов

#arrays #c #dynamic-memory-allocation

#массивы #c #динамическое выделение памяти

Вопрос:

У меня, по-видимому, трагическое понимание распределения памяти и массивов. То, что я хочу, довольно просто, есть массив массивов, массив содержит интервал внутри него. Мой вопрос в том, что, хотя я назначаю новый массив ниже int arr_letter[2] и присваиваю его arr[arr_index], на каждой итерации ВСЕ значения: arr[0], arr[1], arr[2] …. , присваиваются тому, что находится в arr[arr_index].

Я полагаю, что из-за того, как я объявил int * arr[26], мне понадобится аналогичный массив для интервала [x,y] каждый раз, когда я хочу добавить новый элемент в этот массив, вместо того, чтобы делать то, что я делаю, то есть перезаписывать массив. Но мне было интересно, есть ли у кого-нибудь лучший способ?

 int * partitionLabels(char * S, int * returnSize)
{

    int * arr[26];
    memset(arr, 0, 26*sizeof(arr[0]));
    
    int idx_start = 0;
    int idx_end = 0;

    int i = 0;
    int j = 0;
    while(S[i] != '')
    {
        // this populates all the intervals
    //  printf("%c %dn ", S[i], S[i]-97);
        int arr_index = S[i]-97;
        if(arr[arr_index] == 0)
        {
            // S[i]-97 is the integer representation of the character

            idx_start = i;
            idx_end = i;
            j = i;
            while(S[j] != '')
            {
                if(S[j] == S[i]) idx_end = j;       
                j  ;
            }
            int arr_letter[2] = {idx_start, idx_end}; // problem is HERE
            arr[arr_index] = arr_letter;
        }
        i  ;
    }

    int main()
    {
        char * s = "ababcbacadefegdehijhklij";
    
        int returnSize = 0;
    
        partitionLabels(s, amp;returnSize);
    }
 

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

1. Вы знаете, что arr[26] и int arr_letter[2] допустимы только внутри partitionLabels(), верно? Также: Вопрос: является ли 26 хорошим «максимальным размером», или вы думаете, что вам может понадобиться больше 26? Если да, рассматривали ли вы просто создание связанного списка?

2. 26 — это хорошо. Я не буду возвращать arr[26] или arr_letter[2], однако они будут использоваться позже для returnSize . Мне просто нужен способ сгенерировать массив из 2 элементов, а затем назначить его arr[arr_index] . И что еще более важно, вылечите мое забытое понимание

3. Лично я бы просто объявил int arr[2][26] и объявил его вне «partitionLabels()».

4. Я думаю, что проблема даже проще, чем вы думаете. это просто, когда я говорю «int arr_letter[2] = { … }», происходит то, что для переменной используется один и тот же адрес памяти, и arr назначит его всем элементам. Что мне нужно, так это уникальное назначение памяти для arr_letter[2] каждый раз, когда я его вызываю. Что заставляет меня думать, что лучше использовать другой указатель? lol …. мозговой туман (это действительно проблема новичка)

Ответ №1:

Проблема в том, что вы не используете выделение памяти. 🙂 Ваш arr массив — это массив указателей на целые числа, но в нем нет места для хранения объявленных целых чисел. Когда вы это делаете int arr_letter[2] = {idx_start, idx_end} , вы инициализируете автоматическую переменную в стеке со значениями idx_start и idx_end , а затем присваиваете текущему индексу in arr[] . Но это значение, находящееся в стеке, является эфемерным. В худшем случае он не переживет область применения и в лучшем случае будет повторно использован на следующей итерации. Я бы рекомендовал, если я понимаю ваш вариант использования, объявить int arr[26][2] , который выделяет два целых числа для каждого из 26 индексов в arr . Тогда вы бы поставили arr[arr_index][1] = idx_start и. arr[arr_index][2] = idx_end (На самом деле, если бы это был я, я бы определил a struct interval { int start; int end }; , а затем создал массив из них, struct interval arr[26] и arr[arr_index].start=idx_start и arr[arr_index].end=idx_end , но это может быть дальше, чем то, где вы находитесь.) Также, как кто-то указал, arr исчезает, когда функция возвращается. Не уверен, как вы собираетесь получить к нему доступ.

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

1. но, скажем, я действительно хотел использовать выделение памяти — похоже, memset не сделал то, что я думал, что это сделает для меня. Структура — хорошая идея.

2. Может быть. Что memset , по-вашему, сделал? Все, что он делает, это записывает нули в уже выделенную память. malloc это то, что выделяет память.