tags:

views:

234

answers:

6

Assuming that I have a program that has an array of unknown lenght that consists of Customers.

Here, a customer struct:

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

And here - an array:

Customer* CustomerDB;

Okay. But the thing is that I want to add and remove customers dynamically during runtime. I don't want to allocate like 100 customers during declaration or during runtime - I want to allocate one at a time when it is needed.

Think of a simple AddCustomer function that allocates memory, enters the given data and then increments a counter (which is probably needed for iteration).

This is my main problem.

What I want is the array to behave exactly like one that has been declared with 100 arrays instead of a dynamical one.

The customer program above is just an example, please don't tell me that it's a bad idea to do that and that or that.

  • How do I create an AddCustomer function working for the code above?

  • It is necessary that I can iterate through CustomerDB

+3  A: 

Use a standard library container, such as vector, deque, or list.

Fred Larson
I guess this is someone's homework...
graham.reeds
+6  A: 

Use standard template library std::vector or a vector of pointers.

Budric
+2  A: 

I suppose the AddCustomer function might be implemented like this:

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

where the memory re-allocation might be done in terms of realloc.


However, you do realize that you are not taking advantage of anything that C++ offers, so you could have just posted this as a C question (in C++ this is a no-brainer with vector/deque/list and push_back)?

UncleBens
A: 

If you can use std::vector or similar, use that, they're purpose-built for this sort of problem. I'd also replace the raw char * with std::string at the same time.

If you're stuck with the approach above, you might want to change the size of the allocated array using realloc() when the size changes. However that's a very manual way of implementing what a combination of vector & string can do for you much easier and without potential resource leaks.

Timo Geusch
A: 

Here are just some thoughts

Judging from your requirements it sounds as if you would be better off with a list than an array. A list would fit more natural to your requirements regarding the dynamics and having no max limit.

Either you could create your own linked list using a pointer in each list element or use std::dequeue or similar however you would anyway need to take care of what the pointers inside your struct are pointing to. Simplest case in your example would probably to use std::string instead of pointers - then the strings are automatically copied and you don't have to concern yourself with the memory (or use boost::shared_array as pointers).

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

Just my 2c

Anders K.
A: 

As you suggested, this is not the "Correct" way to do things - but heres what you asked for.

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.
}
NTDLS