C ++ malloc - динамический массив - PullRequest
0 голосов
/ 23 февраля 2010

Предполагается, что у меня есть программа с массивом неизвестной длины, состоящим из Customer с.

Здесь структура клиента:

struct Customer
{
 char* lastname;
 char* firstname;
 int money;
};

А вот - массив:

Customer* CustomerDB;

Хорошо. Но дело в том, что я хочу динамически добавлять и удалять клиентов во время выполнения. Я не хочу выделять около 100 клиентов во время декларации или во время выполнения - я хочу выделить одного за раз, когда это необходимо.

Подумайте о простой функции AddCustomer, которая выделяет память, вводит данные и затем увеличивает счетчик (который, вероятно, необходим для итерации).

Это моя главная проблема.

Я хочу, чтобы массив вел себя точно так же, как и тот, который был объявлен с 100 массивами вместо динамического.

Приведенная выше клиентская программа - это просто пример , пожалуйста, не говорите мне, что это плохая идея - делать то или иное или другое.

  • Как мне создать функцию AddCustomer, работающую для кода выше?

  • Необходимо, чтобы я мог перебирать CustomerDB

Ответы [ 6 ]

6 голосов
/ 23 февраля 2010

Используйте стандартную библиотеку шаблонов std :: vector или вектор указателей.

3 голосов
/ 23 февраля 2010

Используйте стандартный контейнер библиотеки, такой как vector, deque или list.

2 голосов
/ 23 февраля 2010

Полагаю, функция AddCustomer может быть реализована так:

void AddCustomer(Customer** db, int current_count);

где перераспределение памяти может быть выполнено в терминах realloc.


Тем не менее, вы понимаете, что не пользуетесь тем, что предлагает C ++, поэтому вы могли бы просто опубликовать это как вопрос на языке C (в C ++ это не представляет сложности с vector / deque / list и push_back)?

0 голосов
/ 23 февраля 2010

Как вы и предлагали, это не "правильный" способ сделать что-то, а вот то, что вы просили.

typedef struct _tag_Customer {
    char *LastName; 
    char *FirstName; 
    double Money; 
} CUSTOMER, *LPCUSTOMER;

typedef struct _tag_Customers {
    CUSTOMER *Collection;
    int Count;
} CUSTOMERS, *LPCUSTOMERS;

LPCUSTOMER AddCustomer(LPCUSTOMERS pCustomers, const char *sLastName, const char *sFirstName, double dMoney)
{
    int iRequiredMemory = (sizeof(CUSTOMER) * (pCustomers->Count + 1));
    if(!(pCustomers->Collection = (LPCUSTOMER) realloc(pCustomers->Collection, iRequiredMemory)))
    {
        return NULL; //Memory allocation error.
    }

    LPCUSTOMER pCutsomer = &pCustomers->Collection[pCustomers->Count];

    pCustomers->Count++;

    iRequiredMemory = strlen(sLastName) + 1;
    pCutsomer->LastName = (char *) calloc(iRequiredMemory, sizeof(char));
    strcpy(pCutsomer->LastName, sLastName);

    iRequiredMemory = strlen(sFirstName) + 1;
    pCutsomer->FirstName = (char *) calloc(iRequiredMemory, sizeof(char));
    strcpy(pCutsomer->FirstName, sLastName);

    pCutsomer->Money = dMoney;

    return pCutsomer;
}

void main(void)
{
    CUSTOMERS Database;
    memset(&Database, 0, sizeof(CUSTOMERS));

    AddCustomer(&Database, "Smith", "Joe", 100.99);
    AddCustomer(&Database, "Jackson", "Jane", 100.99);
    AddCustomer(&Database, "Doe", "John", 100.99);

    //You'll need to free the Memory, of course.
}
0 голосов
/ 23 февраля 2010

Вот только некоторые мысли

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

Либо вы можете создать свой собственный связанный список, используя указатель в каждом элементе списка, либо использовать std :: dequeue или подобное, однако вам все равно придется позаботиться о том, на что указывают указатели в вашей структуре. В простейшем случае в вашем примере, вероятно, будет использоваться std :: string вместо указателей - тогда строки автоматически копируются, и вам не нужно беспокоиться о памяти (или используйте boost :: shared_array в качестве указателей).

struct Customer
{
 string lastname;
 string firstname;
 int money;
};

Просто мой 2с

0 голосов
/ 23 февраля 2010

Если вы можете использовать std::vector или аналогичный, используйте его, они специально созданы для такого рода проблем. Я бы также заменил необработанный char * на std::string одновременно.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...