2010-02-23 4 views
0

En supposant que j'ai un programme qui a un tableau de longueur inconnue qui se compose de Customer s.C++ malloc - tableau dynamique

Ici, un struct client:

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

Et ici - un tableau:

Customer* CustomerDB; 

D'accord. Mais la chose est que je veux ajouter et supprimer des clients dynamiquement pendant l'exécution. Je ne veux pas allouer comme 100 clients pendant la déclaration ou pendant l'exécution - je veux en allouer un à la fois quand c'est nécessaire. Pensez à une simple fonction AddCustomer qui alloue de la mémoire, entre les données données, puis incrémente un compteur (ce qui est probablement nécessaire pour l'itération).

Ceci est mon problème principal. Ce que je veux, c'est que le tableau se comporte exactement comme un tableau qui a été déclaré avec 100 tableaux au lieu d'un tableau dynamique.

Le programme client ci-dessus est juste un exemple, s'il vous plaît ne me dites pas que c'est une mauvaise idée de faire cela ou cela.

  • Comment puis-je créer une fonction AddCustomer travaillant pour le code ci-dessus?

  • Il faut que je peux itérer CustomerDB

+4

Vous n'êtes donc pas autorisé à utiliser 'vector' ou' string'? Toujours en C++, nous préférons le 'new' sûr de type et sûr sur 'malloc'. – GManNickG

+0

Est-ce que' new' peut être utilisé sur les structures? – nordic

+1

oui, 'new' peut être utilisé sur les structures --- en C++ les structures sont fondamentalement les mêmes que les classes (certaines des valeurs par défaut sont différentes, c'est tout). – dave4420

Répondre

3

Utiliser un conteneur de bibliothèque standard, comme vecteur, deque, ou une liste.

+0

Je suppose que ce sont les devoirs de quelqu'un ... –

6

Utilisez la bibliothèque de modèles standard std :: vector ou un vecteur de pointeurs.

2

Je suppose que la fonction AddCustomer peut être mis en œuvre comme ceci:

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

où la ré-allocation de mémoire peut être fait en termes de realloc.


Cependant, vous vous rendez compte que vous ne prenez pas parti de tout ce que C++ offre, vous auriez pu juste de publier cela comme une question de C (en C++ ceci est une évidence avec le vecteur/deque/liste et push_back)?

0

Si vous pouvez utiliser std::vector ou similaire, utilisez-les, ils sont spécialement conçus pour ce genre de problème. Je voudrais également remplacer le char * brut avec std::string en même temps.

Si vous êtes bloqué avec l'approche ci-dessus, vous pouvez changer la taille du tableau affecté en utilisant realloc() lorsque la taille change. Cependant, c'est une façon très manuelle de mettre en œuvre ce qu'une chaîne de & chaîne peut faire pour vous beaucoup plus facile et sans fuites de ressources potentielles.

0

Voici quelques-unes des pensées

A en juger par vos besoins, il semble que si vous seriez mieux avec une liste d'un tableau. Une liste s'adapterait plus naturellement à vos exigences concernant la dynamique et n'ayant pas de limite maximale. Soit vous pouvez créer votre propre liste chaînée à l'aide d'un pointeur dans chaque élément de la liste, soit utiliser std :: dequeue ou similaire, mais vous devrez quand même vous occuper de ce que pointent les pointeurs dans votre structure. Le cas le plus simple dans votre exemple serait probablement d'utiliser std :: string au lieu de pointeurs - alors les chaînes sont automatiquement copiées et vous n'avez pas à vous soucier de la mémoire (ou utilisez boost :: shared_array comme pointeurs).

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

Just my 2c

0

Comme vous l'avez dit, ce n'est pas la « bonne » façon de faire les choses - mais voici ce que vous avez demandé.

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