Как я могу создать динамично размерный массив структур?

Другое событие NullPointerException возникает, когда объявляется массив объектов, а затем сразу же пытается разыменовать его внутри.

String[] phrases = new String[10];
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

Этот конкретный NPE можно избежать, если порядок сравнения отменяется ; а именно, использовать .equals для гарантированного непустого объекта.

Все элементы внутри массива инициализируются их общим начальным значением ; для любого типа массива объектов, это означает, что все элементы null.

Вы должны инициализировать элементы в массиве перед доступом или разыменованием их.

String[] phrases = new String[] {"The bird", "A bird", "My bird", "Bird"};
String keyPhrase = "Bird";
for(String phrase : phrases) {
    System.out.println(phrase.equals(keyPhrase));
}

50
задан halfer 21 February 2018 в 04:57
поделиться

7 ответов

Вы отметили это как C++, а также C.

, Если Вы используете вещи C++, намного легче. Стандартная библиотека шаблонов имеет шаблон, названный вектором, который позволяет Вам динамично создавать список объектов.

#include <stdio.h>
#include <vector>

typedef std::vector<char*> words;

int main(int argc, char** argv) {

        words myWords;

        myWords.push_back("Hello");
        myWords.push_back("World");

        words::iterator iter;
        for (iter = myWords.begin(); iter != myWords.end(); ++iter) {
                printf("%s ", *iter);
        }

        return 0;
}

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

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

typedef struct s_words {
        char* str;
        struct s_words* next;
} words;

words* create_words(char* word) {
        words* newWords = malloc(sizeof(words));
        if (NULL != newWords){
                newWords->str = word;
                newWords->next = NULL;
        }
        return newWords;
}

void delete_words(words* oldWords) {
        if (NULL != oldWords->next) {
                delete_words(oldWords->next);
        }
        free(oldWords);
}

words* add_word(words* wordList, char* word) {
        words* newWords = create_words(word);
        if (NULL != newWords) {
                newWords->next = wordList;
        }
        return newWords;
}

int main(int argc, char** argv) {

        words* myWords = create_words("Hello");
        myWords = add_word(myWords, "World");

        words* iter;
        for (iter = myWords; NULL != iter; iter = iter->next) {
                printf("%s ", iter->str);
        }
        delete_words(myWords);
        return 0;
}

Yikes, извините за миры самый длинный ответ. Таким образом, WRT к "не хотят использовать комментарий связанного списка":

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

typedef struct {
    char** words;
    size_t nWords;
    size_t size;
    size_t block_size;
} word_list;

word_list* create_word_list(size_t block_size) {
    word_list* pWordList = malloc(sizeof(word_list));
    if (NULL != pWordList) {
        pWordList->nWords = 0;
        pWordList->size = block_size;
        pWordList->block_size = block_size;
        pWordList->words = malloc(sizeof(char*)*block_size);
        if (NULL == pWordList->words) {
            free(pWordList);
            return NULL;    
        }
    }
    return pWordList;
}

void delete_word_list(word_list* pWordList) {
    free(pWordList->words);
    free(pWordList);
}

int add_word_to_word_list(word_list* pWordList, char* word) {
    size_t nWords = pWordList->nWords;
    if (nWords >= pWordList->size) {
        size_t newSize = pWordList->size + pWordList->block_size;
        void* newWords = realloc(pWordList->words, sizeof(char*)*newSize); 
        if (NULL == newWords) {
            return 0;
        } else {    
            pWordList->size = newSize;
            pWordList->words = (char**)newWords;
        }

    }

    pWordList->words[nWords] = word;
    ++pWordList->nWords;


    return 1;
}

char** word_list_start(word_list* pWordList) {
        return pWordList->words;
}

char** word_list_end(word_list* pWordList) {
        return &pWordList->words[pWordList->nWords];
}

int main(int argc, char** argv) {

        word_list* myWords = create_word_list(2);
        add_word_to_word_list(myWords, "Hello");
        add_word_to_word_list(myWords, "World");
        add_word_to_word_list(myWords, "Goodbye");

        char** iter;
        for (iter = word_list_start(myWords); iter != word_list_end(myWords); ++iter) {
                printf("%s ", *iter);
        }

        delete_word_list(myWords);

        return 0;
}
35
ответ дан Peter Mortensen 7 November 2019 в 11:05
поделиться

Если Вы хотите динамично выделить массивы, можно использовать malloc от stdlib.h.

, Если Вы хотите выделить массив 100 элементов с помощью Вашего words структура, попробуйте следующее:

words* array = (words*)malloc(sizeof(words) * 100);

размер памяти, которую Вы хотите выделить, передается в malloc, и затем это возвратит указатель типа void (void*). В большинстве случаев Вы, вероятно, захотите бросить его к типу указателя, которого Вы требуете, который в этом случае является words*.

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

, Как только Вы сделаны, убедиться использовать free() для освобождения памяти "кучи", которую Вы использовали для предотвращения утечки памяти :

free(array);

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

12
ответ дан coobird 7 November 2019 в 11:05
поделиться

Это похоже на академическое осуществление, которое, к сожалению, делает его тяжелее, так как Вы не можете использовать C++. В основном необходимо управлять некоторыми издержками для выделения и отслеживать, сколько памяти было выделено, если необходимо изменить размеры его позже. Это - то, где библиотека стандарта C++ сияет.

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

// initial size
int count = 100;
words *testWords = (words*) malloc(count * sizeof(words));
// resize the array
count = 76;
testWords = (words*) realloc(testWords, count* sizeof(words));

Имеют в виду, в Вашем примере, Вы просто выделяете указатель на символ, и все еще необходимо выделить саму строку и что еще более важно освободить его в конце. Таким образом, этот код выделяет 100 указателей для обугливания и затем изменяет размеры его к 76, но не выделяет сами строки.

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

РЕДАКТИРОВАНИЕ: Также имейте в виду, что это делает много смысла для создания функций, чтобы выполнить общие задачи и осуществить непротиворечивость, таким образом, Вы не копируете код везде. Например, Вы могли бы иметь a) выделяют структуру, b) присваивают значения структуре и c) свободный структура. Таким образом, Вы могли бы иметь:

// Allocate a words struct
words* CreateWords(int size);
// Assign a value
void AssignWord(word* dest, char* str);
// Clear a words structs (and possibly internal storage)
void FreeWords(words* w);

РЕДАКТИРОВАНИЕ: До изменения размеров структур это идентично изменению размеров массива символов. Однако различие - то, при создании массива структур больше необходимо, вероятно, инициализировать новые объекты массива к ПУСТОМУ УКАЗАТЕЛЮ. Аналогично при создании массива структур меньшим Вам нужно к очистке прежде, чем удалить объекты - который является бесплатными объектами, которые были выделены (и только выделенные объекты) перед изменением размеров массива структур. Это - основная причина, я предложил создать функции помощника, чтобы помочь управлять этим.

// Resize words (must know original and new size if shrinking
// if you need to free internal storage first)
void ResizeWords(words* w, size_t oldsize, size_t newsize);
5
ответ дан Ryan 7 November 2019 в 11:05
поделиться

В C++ используйте вектор . Это похоже на массив, но можно легко добавить и удалить элементы, и это будет заботиться о выделении и освобождении памяти для Вас.

я знаю, что в заголовке вопроса говорится C, но Вы отметили свой вопрос с C и C++...

2
ответ дан Jeremy Ruten 7 November 2019 в 11:05
поделиться

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

3
ответ дан Neil Williams 7 November 2019 в 11:05
поделиться

Ваш код в последнем обновлении не должен компилировать, а тем более работать. Вы передаете & x к LoadData. & x имеет тип ** слова, но LoadData ожидает слова*. Конечно, это отказывает при вызове перевыделения на указателе, это указывает в стек.

способ зафиксировать его состоит в том, чтобы изменить LoadData для принятия слов **. Влияние Thi, можно на самом деле изменить указатель в основном (). Например, вызов перевыделения был бы похож

*x = (words*) realloc(*x, sizeof(words)*2);

, Это - тот же principlae как в "цифре", являющейся интервалом*, а не интервалом

Помимо этого, необходимо действительно выяснить как строки в словах, прежде чем сохранено. Присвоение строки константы для обугливания * (как в str2 = "marley\0") разрешено, но это редко - правильное решение, даже в C.

Другая точка: не должен иметь "marley\0", если Вам действительно не нужны два 0s в конце строки. Компилятор добавляет 0 tho конец каждого строкового литерала.

1
ответ дан user3458 7 November 2019 в 11:05
поделиться

Если Вы хотите вырастить массив динамично, необходимо использовать malloc (), чтобы динамично выделить некоторую установленную сумму памяти, и затем использовать перевыделение () каждый раз, когда Вы выбегаете. Общая техника должна использовать функцию экспоненциального роста, таким образом, что Вы выделяете некоторую маленькую установленную сумму и затем заставляете массив вырасти путем дублирования выделенной суммы.

Некоторый пример кода был бы:

size = 64; i = 0;
x = malloc(sizeof(words)*size); /* enough space for 64 words */
while (read_words()) {
    if (++i > size) {
        size *= 2;
        x = realloc(sizeof(words) * size);
    }
}
/* done with x */
free(x);
0
ответ дан ob1 7 November 2019 в 11:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: