Initialisation d'un tableau dynamique

Discutez d'informatique ici !
Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

initialisation d'un tableau dynamique

par Rockleader » 04 Fév 2014, 13:52

Bon; mon type de tableau a commencé à prendre forme

J'ai commencé par créer un type de case

dans mon fichier main.c

Code: Tout sélectionner
typedef struct uneCase {
   int val; //valeur de la case
   int vide; //vide ou plein
}laCase;



Dans mon headdeur

Code: Tout sélectionner
#ifndef tabDynamique
#define tabDynamique

#define VIDE 0
#define PLEIN 1
#define SIZE_BEGIN 5

typedef struct uneCase* Case;

typedef struct unTableauDynamique { //Case est protégé donc il n'est pas nécessaire de protéger TableauDynamique
   Case *t; //tableau de case (valeur numerique + booleene) taille indéfini
   int nbVal; // nb valeur dans le tableau
   int size_max;
}TableauDynamique;


TableauDynamique tabDynamiqueCreer(int N);

#endif // tabDynamique


Et dans le .c lié voici le code de la fonction pour créer le tableau

J'ai tout d'abord tenté ceci
Code: Tout sélectionner
TableauDynamique tabDynamiqueCreer(int N)
{
   TableauDynamique tab;
   tab.nbVal=0;
   tab.size_max=N;
   tab.t[N]={0,VIDE};

   return tab;
}


Puis je me suis souvenu que l'on ne pouvait déclarer avec les accolades qu'à la création du tableau; autrement l'on est obligé de passer par une boucle, c'est donc ce que j'ai fait

Code: Tout sélectionner
TableauDynamique tabDynamiqueCreer(int N)
{
   TableauDynamique tab;
   tab.nbVal=0;
   tab.size_max=N;
   int k;
   for (k=0;k<N;k++)
   {
      tab.(t[k].val)=0;
      tab.(t[k].vide)=VIDE;

   }
   return tab;
}


Malheureusement sans succès, j'ai du coup un peu de mal à voir comment je vais initialiser ce tableau =)
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !



Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 07:03

par ampholyte » 04 Fév 2014, 14:02

Bonjour,

Sachant que 't' est défini par un Case *t, tu as besoin de le déclarer à l'aide un malloc / calloc.
Code: Tout sélectionner
t = calloc(N, sizeof(Case)));
if (t == NULL) {
    fprintf(stderr, "error calloc\n");
    return (NULL);
}


Ne pas oublié de free lorsque tu n'en auras plus l'utilité.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 04 Fév 2014, 14:08

Donc si j'ai bien compris je dois faire un truc comme ça

Code: Tout sélectionner
t=malloc(N * sizeof(Case));
//suivi d'un test pour savoir si l'allocation s'est bien passé avec le ptr null


Je place donc ces lignes dans mon fichier fonction.c ? Je n'aurais pas un conflit d'intérêt entre t de la fonction et t de la structure ?


EDIT: je n'avais pas vu ton bout de code; ce que j'ai écris avec un malloc est équivalent non ?

En ce qui concerne le free; oui, c'est à cela que servira un des champ de la structure afin de connaitre la nouvelle taille du tableau à chaque fois.

Juste une question; la réservation d'espace par le malloc se fait bien à l'exécution et pas à la compilation ? Sa serait bête de perdre en mémoire en faisant des tests...



EDIT2:


Le code suivant me renvoi l'erreur

fonction.c:19:7: error: expected identifier before ‘(’ token
tab.(t[k].val)=0;
^
fonction.c:20:7: error: expected identifier before ‘(’ token
tab.(t[k].vide)=VIDE
;



Code: Tout sélectionner
TableauDynamique tabDynamiqueCreer(int N)
{
   TableauDynamique tab;
   tab.nbVal=0;
   tab.size_max=N;
   tab.t = malloc(N * sizeof(Case));
   if (tab.t == NULL)
   {
       fprintf(stderr, "error malloc\n");
   }
   int k;
   for (k=0;k<N;k++)
   {
      tab.(t[k].val)=0;
      tab.(t[k].vide)=VIDE;

   }
   return tab;
}


Aurais je encore mal fait quelque chose ?
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 07:03

par ampholyte » 04 Fév 2014, 14:52

Il faut retirer les parenthèses ou à la limite écrire :
Code: Tout sélectionner
tab.t[k].val = 0;
// ou
(tab).t[k].val = 0;


Le malloc est équivalent sauf qu'il faut penser à initialiser ton tableau (avec un memset ou autre). Je préfère utiliser le calloc qui fait directement l'initialisation à 0 du pointeur.

L'allocation se fera directement lors de l'execution du programme.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 04 Fév 2014, 15:01

J'ai enlevé les parenthèse et essayer seulement autour de tab; mais ça ne passe toujours pas au compilo

fonction.c:19:13: error: request for member ‘val’ in something not a structure or union
(tab).t[k].val=0;
^
fonction.c:20:13: error: request for member ‘vide’ in something not a structure or union
(tab).t[k].vide=VIDE;
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 07:03

par ampholyte » 04 Fév 2014, 15:11

Le problème est différent maintenant =). Il faut que tu apprennes à comprendre les erreurs qui te sont fournies.

Ton problème semble provenir de ta déclaration de tes structures. Personnellement lorsque j'ai une imbrication de structure je préfère procéder ainsi :

Code: Tout sélectionner
typedef struct Case Case;
typedef struct TableauDynamique TableauDynamique;

struct Case {
   /* ... */
};

struct TableauDynamique {
    Case *t;
   /* ... */
};

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 04 Fév 2014, 15:22

Même problème en procédant de cette façon.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 07:03

par ampholyte » 04 Fév 2014, 15:24

Pourrais-tu remettre tout ton code ici ou en passant par le site suivant (http://pastebin.com/) ? Ou peut-être as-tu un github ?

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 04 Fév 2014, 15:30

Voilà le tout; l'erreur se comprend facilement; j'essaie d'affecter quelque chose qui n'est pas une structure donc j'appelle de la mauvaise façon; le hic c'est que je vois pas le soucis dans cette façon d'appeler

main.c

Code: Tout sélectionner
#include
#include
#include "tabDynamique.h"

struct uneCase {
   int val; //valeur de la case
   int vide; //vide ou plein
};

int main()
{
   return 0;
}



fonction.c

Code: Tout sélectionner
#include
#include
#include "tabDynamique.h"


TableauDynamique tabDynamiqueCreer(int N)
{
   TableauDynamique tab;
   tab.nbVal=0;
   tab.size_max=N;
   tab.t = calloc(N , sizeof(Case));
   if (tab.t == NULL)
   {
       fprintf(stderr, "error malloc\n");
   }
   int k;
   for (k=0;k<N;k++)
   {
      tab.t[k].val=0;
      tab.t[k].vide=VIDE;

   }
   return tab;
}


Code: Tout sélectionner
headdeur

#ifndef tabDynamique
#define tabDynamique

#define VIDE 0
#define PLEIN 1
#define SIZE_BEGIN 5

typedef struct uneCase* Case;
typedef struct TableauDynamique TableauDynamique;

struct TableauDynamique { //Case est protégé donc il n'est pas nécessaire de protéger TableauDynamique
   Case *t; //tableau de case (valeur numerique + booleene) taille indéfini
   int nbVal; // nb valeur dans le tableau
   int size_max;
};


TableauDynamique tabDynamiqueCreer(int N);

#endif // tabDynamique
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 07:03

par ampholyte » 04 Fév 2014, 15:40

Je te conseille de reprendre depuis le début ton problème. Essaye de travailler avec les pointeurs surtout lorsque tu travailles avec des structures et des tableaux.

Par exemple tu pourrais plutôt utiliser la fonction :

Code: Tout sélectionner
TableauDynamique *tabDynamiqueCreer(int N)


Avant de te lancer dans ce genre de chose essaye déjà de simplifier ton problème.

Commence déjà en partant d'un tableau plus simple, par exemple un tableau de Case.

Une fois que tu auras bien compris comment est-ce que cela fonctionne tu pourras intégrer dans une nouvelle structure ce que tu veux.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 04 Fév 2014, 15:45

J'avais déjà fait avec un tableau simple à l'initialisation un truc comme ça marchait très bien, sinon je serais pas passé à l'étape suivante.

Case t[NB_CASE]={0,VIDE};

Mais avec la structure ça ne passe plus.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 07:03

par ampholyte » 04 Fév 2014, 15:53

Cela compile en mettant :

Code: Tout sélectionner
tab.t[k]->val = 0;
tab.t[k]->vide = VIDE;


mais ce que tu fais, semble assez compliqué pour ton problème de base.

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 04 Fév 2014, 16:03

ampholyte a écrit:Cela compile en mettant :

Code: Tout sélectionner
tab.t[k]->val = 0;
tab.t[k]->vide = VIDE;


mais ce que tu fais, semble assez compliqué pour ton problème de base.



Non toujours pas ;)

error: dereferencing pointer to incomplete type
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 04 Fév 2014, 16:09

Si tu devais créer une structure de tableau dynamique tu l'aurais faite comment toi ?
En sachant qu'il faut bien pouvoir déterminer si les cases du tableau sont vide ou non. A part passer par un tableau de structure je vois pas d'autre solution.
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
ampholyte
Membre Transcendant
Messages: 3940
Enregistré le: 21 Juil 2012, 07:03

par ampholyte » 04 Fév 2014, 16:46

Rockleader a écrit:Si tu devais créer une structure de tableau dynamique tu l'aurais faite comment toi ?
En sachant qu'il faut bien pouvoir déterminer si les cases du tableau sont vide ou non. A part passer par un tableau de structure je vois pas d'autre solution.


Personnellement je serais passer par un tableau de structure mais de la forme suivante.

Code: Tout sélectionner
#include
#include
#include
#include
#include

typedef struct  {
    bool is_empty;
    int value;
}s_case;

s_case *create_tab(unsigned int N) {
   unsigned int i = 0;
   s_case *tab = NULL;
   /* On alloue tab */
   tab = calloc(N, sizeof(s_case));
   if (tab == NULL) {
       fprintf(stderr, "calloc : %s\n", strerror(errno));
       return (NULL);
   }
   
   /* On initialise tab */
   for (i = 0; i < N; i++) {
       tab[i].is_empty = true;
   }
   
    return tab;
}

int main(void) {
    s_case *my_tab = NULL;
    my_tab = create_tab(10);
    free(my_tab);
    return 0;
}


Non toujours pas ;)

error: dereferencing pointer to incomplete type


Désolé j'avais oublié que j'avais modifié ta fonction ^^.

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 04 Fév 2014, 16:48

benjamin t a donne un moyen de tracker les cases vides
(au moyen d un second tableau par exemple)
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 04 Fév 2014, 17:08

Sauf que ma fonction doit obligatoirement être appelé sous la forme TableauDynamique f(int N); je peux donc pas mettre de pointeur à ce niveau là.

EDIT: Le principal but de l'exo (en tout cas de la façon dont je l'ai compris) c’est de créer une structure de tableau dynamique; et donc les fonction renverront et travailleront sur des structures qui représenteront ces tableaux dynamique.

D'où ma représentation

Dans le code proposé plus haut; c'est vrai que l'on a un tableau de s_case et donc un tableau dynamique avec le calloc après; mais ça ne passe pas par une structure ;)
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 04 Fév 2014, 18:12

Ben t'as plusieurs moyen d'aborder le problème de savoir si un tableau a une case vide ou pas.

Tu peux faire un tableau de case, et chaque case sait si elle est vide
Ou tu peux faire un tableau d'élément, et c'est le tableau qui sait si telle ou telle case est vide.

cas 1): approche de Ampholyte
cas 2): approche type Benjamin
Code: Tout sélectionner
//header
struct TableauDynamique{
    case* t;
    bool* emptyCells;
}
TableauDynamique f(int N);
bool TableauDynamique_isEmptyCell(size_t index);

//src
TableauDynamique f(int N){
    TableauDynamique tab;
    tab.t = malloc(sizeof(case)*N);
    tab.emptyCells = malloc(sizeof(bool)*N);
    //plus init of emptyCells
    return tab;
}
bool TableauDynamique_isEmptyCell(size_t index){
    return emptyCells[index];
}

Les deux approches sont un peu différentes.
Dans le premier cas, tu supposes que l'élément du tableau présente la particularité isEmpty (ce qui peut t'obliger à créer un wrapper si ton élément, un int par exemple, ne propose pas cette méthode)
Dans le deuxième cas, c'est pas nécessaire, car c'est le tableau lui même qui controle ca.
Mais attention aux pointeurs. Si tu manipules des tableaux, il faut bien faire gaffe à utiliser l'interface du tableau plutot que manipuler les éléments qui sont stockés en son sein. (imagines tu récupères le pointeur d'un élément alors que celui ci était invalide. Si tu modifies sa valeur, il est théoriquement valide, sauf que comme t'as pas utilisé l'API du tableauDynamique, ben aux yeux de tableauDYnamique, il restera invalide).

attention également à la copie de tableau et leur destruction..
la vie est une fête :)

Avatar de l’utilisateur
fatal_error
Membre Légendaire
Messages: 6610
Enregistré le: 22 Nov 2007, 12:00

par fatal_error » 04 Fév 2014, 18:18

concernant ton poste de 15h30
tu as pas défini la structure case au bon endroit.
Dans la mesure ou tableauDynamique protège case, alors tu dois définir case dans le cpp de tableau dynamique.
Et toutes les méthodes de tableauDYnamique doivent etre déclarées dans le header et définit dans ce même cpp.
De cette facon, case est utilisée par tableauDynamique dans le cpp (et son type est complètement défini), et de l'extérieur tous les utilisateurs de tableauDynamique n'ont besoin que de connaitre le pointeur (qui est juste un int)

Donc le struct dans le main.cpp tu le mets dans fonction.cpp.
la vie est une fête :)

Avatar de l’utilisateur
Rockleader
Habitué(e)
Messages: 2126
Enregistré le: 11 Oct 2011, 18:42

par Rockleader » 04 Fév 2014, 18:28

Ben, en fait fatal; c'est ce que j'ai fait ;) La seule chose que tu rajoutes en plus c'est le malloc sur empty parce que dans ta structure de tableau dynamique tu met un tableau pour ça aussi.

En fait tu évites une structure et tu fais 2 tableaux sur lesquels on fera au final les mêmes opérations.
C'est différent de ce que j'ai fais, mais le résultat est le même sauf erreur.



Le problème que j'avais ce n'était pas de vérifier si mes cases était vide ou non; c'était bel et bien de procéder à l'initialisation de mon tableau de structure (dans ton cas à l'initialisation des deux tableaux). Ce que tu ne fais pas dans ton code; du coup le problème persiste toujours =)


Cependant si le but de ton post était de me faire comprendre que je pouvais passer par deux tableaux plutôt qu'une structure, je le savais déjà c'est un peu le principe de la définition d'une structure au final; il me semblait quand même plus logique de passer par une structure pour mieux représenter les choses (même si au codage ce doit être plus hard; mais j'admet volontiers ta solution de deux tableaux :d )


EDIT

Donc le struct dans le main.cpp tu le mets dans fonction.cpp.


Ouai ça je m'en étais aperçu après coup j'ai fais la modif après coup; je l'aurais mis dans le main si je n'avais pas eu un second .c; ce qui n'est pas le cas ici :++:
Merci

EDIT2:


En fait si on devait simplifier au max le problème; ça serait initialiser une valeur d'un tableau dans une structure.


Code: Tout sélectionner
struct a{
   int t[5];
};
typedef struct a A;
A A2;
A2.t[0]=3;


Ici l'affectation de valeur ne se fait pas correctement et je comprends pas pourquoi. C'est le même soucis que pour le reste
Cette histoire est entièrement vraie puisque je l'ai inventé du début à la fin !

 

Retourner vers ϟ Informatique

Qui est en ligne

Utilisateurs parcourant ce forum : Aucun utilisateur enregistré et 10 invités

Tu pars déja ?



Fais toi aider gratuitement sur Maths-forum !

Créé un compte en 1 minute et pose ta question dans le forum ;-)
Inscription gratuite

Identification

Pas encore inscrit ?

Ou identifiez-vous :

Inscription gratuite