IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Utiliser Struct


Sujet :

C

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 560
    Par défaut Utiliser Struct
    Bonjour
    j'ai un probleme avec les struct ,je ne sais pas comment les utiliser.
    Le programme suivant me cré un probleme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
     
    typedef int VEC_COMP[10][10];
     
    void Mise_a_zeroC(VEC_COMP v){
        int i;
        int *p;
        p=v;
        for(i=0;i<100;i++,p++)
            *p=0;
    }
    void AfficheC(VEC_COMP v){
        int i;
        int *p;
        p=v;
        putchar('\n');
        for(i=0;i<100;i++,p++)
            printf("%d  ",*p);
        putchar('\n');
    }
    et ce programme egalement
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
     
    struct VEC_L {
        int VAL [2];
        struct VEC_L * suivant ;
    };
    typedef struct VEC_L VEC_LIST, * suite;
     
    void Mise_a_zeroL(VEC_LIST V,int n){
        if(!n==0)
        {
            V.VAL[0]=0;
            V.VAL[1]=0;
            Mise_a_zeroL(V.suivant,n-1);
        }else 
         {
        V.suivant=null;
        V.VAL[0]=0;
        V.VAL[1]=0;
        }
     
    }
    void AfficheL(VEC_LIST v,int indice){
        if(indice==0)
        {
            printf("%d",v.VAL[0]);
            printf("%d",v.VAL[1]);
        }else
        {    
            printf("%d",v.VAL[0]);
            printf("%d",v.VAL[1]);
            AfficheL(v.suivant,n-1);
        }
    }
    Si quelqu'un peut trouver la solution ...
    D'avance merci .

  2. #2
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Pour le premier programme, tu as un problème de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef int VEC_COMP[10][10];
     
    void Mise_a_zeroC(VEC_COMP v)
    {
        int *p;
        p=v;...
    v est du type int (*)[10] (adresse d'un tableau de 10 int), pas du type int*. Le compilateur doit te donner un avertissement sur p = v.
    En l'occurence, tu peux confirmer ta volonté de faire ce changement de type (qui n'est pas franchement faux, puisque c'est l'adresse d'un int) et éviter le warning:
    C'est le problème de passer des tableaux à plusieurs dimensions à des fonctions. Je préfère pour ma part :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void Mise_a_zeroC(int * v)
    {
    ...
    et appeler la fonction par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    VEC_COMP x;
    ...
     Mise_a_zeroC( (int*)  x);
    Pour le second problème, je n'ai pas le temps de regarder maintenant. Désolé

  3. #3
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    - suivant est de type struct VEC_L *.
    - Mise_a_zeroL requiert en premier argument un VEC_LIST (= struct VEC_L) alors que plus bas tu passe un pointeur sur VEC_LIST (suivant). Même remarque pour AfficheL.
    - La ligne est ambiguë. Tu veux peut-être faire : - Pas de null en C mais NULL.
    - Pour mettre un objet à zéro tu peux utiliser la fonction memset.

  4. #4
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par diogene Voir le message
    Pour le premier programme, tu as un problème de type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    typedef int VEC_COMP[10][10];
     
    void Mise_a_zeroC(VEC_COMP v)
    {
        int *p;
        p=v;...
    v est du type int (*)[10] (adresse d'un tableau de 10 int), pas du type int*. Le compilateur doit te donner un avertissement sur p = v.
    En l'occurence, tu peux confirmer ta volonté de faire ce changement de type (qui n'est pas franchement faux, puisque c'est l'adresse d'un int) et éviter le warning:
    C'est le problème de passer des tableaux à plusieurs dimensions à des fonctions. Je préfère pour ma part :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    void Mise_a_zeroC(int * v)
    {
    ...
    et appeler la fonction par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    VEC_COMP x;
    ...
     Mise_a_zeroC( (int*)  x);
    Pour le second problème, je n'ai pas le temps de regarder maintenant. Désolé
    Pourquoi ne pas tout simplement écrire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
     
    void Mise_a_zeroC(int v[][10])
    {
        int *p;
        p = v[0];...
    C'est propre et on évite l'usage d'opérateur de conversion de type douteux.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  5. #5
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 560
    Par défaut re
    merci pour vos reponses .
    J'ai finalement reussi a faire fonctionner voila le code pour VEC_COMP:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    void Mise_a_zeroC(VEC_COMP v){
    	int i;
    	int *p;
    	p=(int *)v;
    	for(i=0;i<100;i++,p++)
    		*p=0;
    }
    void AfficheC(VEC_COMP v){
    	int i;
    	int *p;
    	p=(int *)v;
    	putchar('\n');
    	for(i=0;i<100;i++,p++)
    		printf("%d  ",*p);
    	putchar('\n');
    }
    mais j'ai toujours un probleme avec le code de VEC_LIST ,quand je compile il ne me met pas d'erreur mais quand je lance le programme il me met une erreur de segmentation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    void Mise_a_zeroL(liste V,int n){
    	if(n>0)
    	{	VEC_LIST Vi;
    		liste l;
     
    		(*V).suivant=&Vi;
    		(*V).VAL[0]=0;
    		(*V).VAL[1]=0;
    		Mise_a_zeroL((*V).suivant,n-1);
    	}else 
     	{
    	(*V).suivant=NULL;
    	(*V).VAL[0]=0;
    	(*V).VAL[1]=0;
    	}
     
    }
    void AfficheL(VEC_LIST v, int n){
     
     
    	if(n==0)
    	{
    		printf("%d",v.VAL[0]);
    		printf("%d",v.VAL[1]);
    	}else
    	{	
    		printf("%d",v.VAL[0]);
    		printf("%d",v.VAL[1]);
    		AfficheL(*v.suivant,n-1);
    	}
    }

  6. #6
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Thierry :
    Pourquoi ne pas tout simplement écrire:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void Mise_a_zeroC(int v[][10])
    {
        int *p;
        p = v[0];...
    C'est propre et on évite l'usage d'opérateur de conversion de type douteux.
    Tu as raison, c'est plus propre.
    Toutefois, la déclaration de la fonction possède alors une ambiguité : Elle traite le tableau en 1D en laissant croire que la dimension 10 est pertinente, alors qu'en fait, la fonction est utilisable quelle que soit cette valeur (si on prend la précaution de passer également le nombre d'éléments).

    J'adopte volontiers ta proposition sous la forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void Mise_a_zeroC(int * v)
    {...}
     
    VEC_COMP x;
    ...
     Mise_a_zeroC(x[0]);

  7. #7
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par diogene Voir le message
    Thierry :

    Tu as raison, c'est plus propre.
    Toutefois, la déclaration de la fonction possède alors une ambiguité : Elle traite le tableau en 1D en laissant croire que la dimension 10 est pertinente, alors qu'en fait, la fonction est utilisable quelle que soit cette valeur (si on prend la précaution de passer également le nombre d'éléments).

    J'adopte volontiers ta proposition sous la forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void Mise_a_zeroC(int * v)
    {...}
     
    VEC_COMP x;
    ...
     Mise_a_zeroC(x[0]);
    Oui, si on veut s'abstraire de la deuxième dimension, cela me semble effectivement une méthode plus propre, encore que si on désire vraiment insister sur l'aspect tableau à deux dimensions de taille variable, je suis plus favorable à l'utilisation d'un type abstrait de donnée qui pourrait être définit comme suit:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    struct Matrice
    {
        int *data; /* Allocation dynamique d'un tableau de taille ligs * cols * sizeof *data */
        size_t ligs;
        size_t cols;
    };
     
    struct Matrice * Matrice_creer(size_t ligs, size_t cols);
    void Matrice_detruire(struct Matrice **pp_self);
    void Matrice_mise_a_zero(struct Matrice *p_self);
    int Matrice_get(struct Matrice *p_self, size_t i, size_t j);
     
    /*...*/
     
    void Matrice_mise_a_zero(struct Matrice *p_self)
    {
        if (p_self != NULL)
        {
            int *p;
            p = p_self->data;
            /*...*/
        }
    }
     
    int Matrice_get(struct Matrice *p_self, size_t i, size_t j)
    {
        int ret = 0;
     
        if (p_self != NULL && i < p_self->ligs && j < p_self->cols)
        {
            size_t ncols = p_data->cols;
            ret = p_self->data[i * ncols + j];
        }
     
        return ret;
    }
    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  8. #8
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    On peu très bien passer un tableau statique de n'importe quelle dimension avec (par exemple pour un tableau à deux dimensions) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void f(void * p, size_t nb_lignes, size_t nb_colonnes)
    {
        int * t = p;
     
        ...
    }
    C'est très popre, très simple et très générique.

  9. #9
    Expert confirmé
    Avatar de Thierry Chappuis
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Mai 2005
    Messages
    3 499
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : Suisse

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Industrie Pharmaceutique

    Informations forums :
    Inscription : Mai 2005
    Messages : 3 499
    Par défaut
    Citation Envoyé par Melem Voir le message
    On peu très bien passer un tableau statique de n'importe quelle dimension avec (par exemple pour un tableau à deux dimensions) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    void f(void * p, size_t nb_lignes, size_t nb_colonnes)
    {
        int * t = p;
     
        ...
    }
    C'est très popre, très simple et très générique.
    Ce que je ne trouve pas très propre, c'est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    int (*)[10] -> void * -> int *
    Mais peut-être que je me complique la vie pour pas grand-chose.

    Thierry
    "The most important thing in the kitchen is the waste paper basket and it needs to be centrally located.", Donald Knuth
    "If the only tool you have is a hammer, every problem looks like a nail.", probably Abraham Maslow

    FAQ-Python FAQ-C FAQ-C++

    +

  10. #10
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Est très propre. Le premier est type est parfaitement aligné pour le second (dans la mémoire, il n'y a aucune différence entre un tableau à n dimensions et un tableau à une seule dimension) et la norme autorise la conversion. Le void * sert tout simplement à supprimer le cast.

  11. #11
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    Personnellement, je serais quand même plutôt du genre à passer explicitement &tab[0][0] à une fonction demandant un int*.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  12. #12
    Membre éclairé
    Profil pro
    Inscrit en
    Décembre 2007
    Messages
    560
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2007
    Messages : 560
    Par défaut re
    merci a tous pour vos reponses je vais potasser ca .

  13. #13
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    Citation Envoyé par Médinoc Voir le message
    Personnellement, je serais quand même plutôt du genre à passer explicitement &tab[0][0] à une fonction demandant un int*.
    Mais &tab[0][0] est strictement équivalent à tab[0] puisque traduit en &*(tab[0]+0) = tab[0] de la même façon que pour un tableau 1D, passer &tab[0] au lieu de simplement tab est juste mais (à mon goût) inutilement verbeux.

  14. #14
    Expert confirmé
    Avatar de Melem
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Janvier 2006
    Messages
    3 656
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Janvier 2006
    Messages : 3 656
    Par défaut
    Citation Envoyé par diogene
    Mais &tab[0][0] est strictement équivalent à tab[0] ...
    tab[0] mais pas tab.

Discussions similaires

  1. utilisation de struct et orderfields
    Par hksa93 dans le forum Images
    Réponses: 5
    Dernier message: 14/03/2011, 15h48
  2. Syntaxe et utilisation de struct
    Par cha7ri dans le forum Linux
    Réponses: 3
    Dernier message: 08/02/2009, 14h44
  3. utilisation map et struct
    Par senshi03 dans le forum SL & STL
    Réponses: 2
    Dernier message: 01/11/2007, 18h56
  4. Réponses: 2
    Dernier message: 27/09/2006, 10h37
  5. [Débutant] Utilisation de struct
    Par BNS dans le forum C++
    Réponses: 8
    Dernier message: 28/02/2006, 12h49

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo