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 :

Tableau de structure : modifier une case identifée par un pointeur


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2021
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2021
    Messages : 11
    Par défaut Tableau de structure : modifier une case identifée par un pointeur
    Bonjour communauté,

    Ca fait 20 ans que je n'ai plus programmé en C, et je me retrouve confronté à de vrais problèmes de débutants.

    Voila, j'ai 3 tableaux de même taille qui contiennent à chaque case une structures quelconque (la même pour tous).
    J'ai un tableau original, et 2 copies de celui-ci qui sont modifiées à tour de rôle par des thread
    Dans cet exemple, les variables sont globales.

    Le code :
    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
     
    #define TAILLE 10
     
    typedef struct { int a; int b; int c;} maStruct;
     
    maStruct tab[TAILLE]; // tableau original
    maStruct tab1[TAILLE]; // tableau temporaire utilisable par les threads
    maStruct tab2[TAILLE]; // tableau temporaire utilisable par les threads
     
    maStruct ** currentTab; // adresse que les threads vont utiliser pour savoir sur quel tableau travailler. Pointera vers tab1 ou tab2
     
    int traitement(int val) {  return val + 1; /* traitement quelconque */}
     
    void Sort() {
     
       maStruct ** tmp; // structure temporaire indiquant le tableau sur lequelle je vais travailler dans cette fonction et qui est celui sur lequel les thread ne taperont pas
     
      if((maStruct**)currentTab == (maStruct**)&tab1) // si currentTab pointe vers tab1, alors je fais pointer tmp vers tab2 et inversement
        tmp = (maStruct **)&tab2;
      else
        tmp = (maStruct **)&tab1;
     
     
      for(uint8_t i = 0; i < TAILLE; i++) { 
        tab[i].a = traitement(tmp[i]->b); // un traitement quelconque qui modifie l'original
        tmp[i] = tab[i]; // c'est la que j'ai un problème
      }
    }
    Evidemment, il me dit à la ligne tmp[i] = tab[i] que y'a un conflit maStruct et *maStruct, ce que je peux entendre.
    Ce que je veux, c'est copier complètement le contenu de tab[i] à l'endroit pointé par tmp[i]...
    Je pourrais faire tmp[i]->a = tab[i].a; tmp[i]->b = tab[i].b; etc...
    Mais c'est pourrit, car je veux pouvoir modifier ma structure sans changer tout mon code !

    Je n'arrive vraiment pas à me rappeler comment on se débrouille avec une situation pareille, et votre aide serait la bienvenue.

    En vous remerciant par avance

    merci de ne pas proposer de faire différemment ni de ne pas revenir sur le fait que j'utilise des variables globales plutôt que des paramètres ou autres questions de conception, ce n'est pas le problème ni même mon vrai code, c'est juste un truc que je viens d'écrire pour illustrer mon soucis.

  2. #2
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Bpnjour
    Citation Envoyé par vieuxjeune Voir le message
    Evidemment, il me dit à la ligne tmp[i] = tab[i] que y'a un conflit maStruct et *maStruct, ce que je peux entendre.
    Ce que je veux, c'est copier complètement le contenu de tab[i] à l'endroit pointé par tmp[i]...
    Tu peux pas. tmp[i] est un "maStruct étoile", donc il doit recevoir un "maStruct étoile". En écrivant tmp[i] = tab[i] tu tentes de copier un "maStruct" dans un "maStruct étoile". Forcément ça ne matche pas.
    La bonne syntaxe sera tmp[i] = &tab[i] et là c'est cohérent avec le typage (quant à être cohérent avec le résultat attendu, là c'est une autre histoire)
    Mais ce que je ne comprends pas, c'est que tu pars de tableaux de maStruct (donc des tableaux 1D, simples, standard) et tu crées une variable maStruct **currentTab. Pourquoi un double étoile pour un tableau 1D? Je pense que c'est ce départ le noeud du souci. Quand on veut traiter des tableaux 1D on utilise des pointeurs 1 étoile.
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    int tab[]={1, 2, 3, 4, 5};
    int *pt;
    for (size_t i=0, pt=tab; i < 5; i++, pt++) printf("%d\n", *pt);

    Et je te conseillerais de supprimer les cast car j'ai l'impression que tu les mets pour "cacher la misère". Un cast ne se met que si le C ne connait pas un truc, pour lui indiquer "ce truc c'est ça". Il ne sert pas à "forcer" un truc à être ce qu'il n'est pas.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  3. #3
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 768
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 768
    Par défaut
    Citation Envoyé par vieuxjeune Voir le message
    Mais c'est pourrit, car je veux pouvoir modifier ma structure sans changer tout mon code !
    C'est ta façon de coder qui est pourrie surtout : variables globales, nom, ...

    Fais ta structure ainsi typedef struct s_mystruct { int a; int b; int c;} t_mystruct;.

    Et ensuite pense en programmation objet (PS: les fonctions peuvent renvoyer 1 booléen pour dire si l'opération s'est bien passée ou pas)
    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
    void mystruct_copy(t_mystruct* source, t_mystruct* dest) {
        if ((source != NULL) && (dest != NULL)) {
            dest->a = source->a;
            dest->b = source->b;
            dest->c = source->c;
        }
    }
     
    void mystruct_display(t_mystruct* s) {
        if (s != NULL) {
            print("(%d, %d, %d)", s->a, s->b, s->c);
        }
    }
     
    void mystruct_init(t_mystruct* s) {
        if (s != NULL) {
            s->a = 0;
            s->b = 0;
            s->c = 0;
        }
    }
     
    void mystruct_init_all(t_mystruct* s, int a, int b, int c) {
        if (s != NULL) {
            s->a = a;
            s->b = b;
            s->c = c;
        }
    }
     
    // ...

  4. #4
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

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

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,

    Tes cast risquent de masquer un problème, ton code devrait marcher sans.
    Si ton but est de copier tout l'élément tab[i] dans ce qui est pointé par tmp[i], il suffit d'un égal:
    Et c'est bien l'équivalent à : tmp[i]->a = tab[i].a; tmp[i]->b = tab[i].b; etc...

  5. #5
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par foetus Voir le message
    Citation Envoyé par vieuxjeune Voir le message
    merci de ne pas proposer de faire différemment ni de ne pas revenir sur le fait que j'utilise des variables globales...
    C'est ta façon de coder qui est pourrie surtout : variables globales, nom, ...
    Je pense qu'il en a conscience...
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  6. #6
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2021
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2021
    Messages : 11
    Par défaut
    Merci pour les réponses.

    *tmp[i] = tab[i]; semble fonctionner !

    Pour les cast, je suis surpris de ne pas pouvoir faire autrement...

    Dans mes lointains souvenirs, truc * myvar et truc myvar[] étaient équivalent... Qu'en fait non...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    maStruct tab2[TAILLE]; 
    maStruct ** tmp;
    tmp = &tab2; // marche pas, sauf si j'écris tmp = (maStruct **)&tab2;
    -> cannot convert 'maStruct (*)[10]' to 'maStruct**' in assignment

  7. #7
    CGi
    CGi est déconnecté
    Expert confirmé
    Avatar de CGi
    Profil pro
    Inscrit en
    Mars 2002
    Messages
    1 061
    Détails du profil
    Informations personnelles :
    Localisation : France, Allier (Auvergne)

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 061
    Par défaut
    Le transtypage ne sert pas à cacher la misère ! Si ça marche pas c'est que les types ne colle pas !
    &tab2 est de type maStruct (*)[10] alors ton pointeur devrait avoir le même type :
    Citation Envoyé par vieuxjeune Voir le message
    Dans mes lointains souvenirs, truc * myvar et truc myvar[] étaient équivalent... Qu'en fait non...
    Ça c'est pour les paramètres de fonction.
    Site : http://chgi.developpez.com

    Pourquoi faire simple quand on peut faire compliqué ? (Jacques Rouxel)

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 833
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 833
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par vieuxjeune Voir le message
    Dans mes lointains souvenirs, truc * myvar et truc myvar[] étaient équivalent...
    Ils sont "similaires", pas "équivalents".
    L'équivalence implique une absolue égalité, qui se répercute par transitivité (si ça marche pour une étoile ça marchera pour deux, trois, etc). La similarité implique une prudence dans ses conclusions. Ca peut marcher pour un niveau mais pas deux.
    Et de fait c'est le cas. Le tableau 1D est assimilable à un pointeur une étoile, le tableau 2D n'est pas assimilable à un pointeur deux étoiles. Et ce, parce que la mémoire n'est qu'une immense suite de cases (donc un tableau 1D).

    Exemple
    • si j'aligne 36 cases en une ligne, je te mets le doigt sur la case [1] et te demande de me désigner la case [10], tu n'auras aucun mal => tu déplaceras ton doigt de 9 cases vers la droite.
    • si maintenant j'aligne ces mêmes 36 cases mais que je te demande la case [3][2] cela te sera impossible => il te manque la taille d'une "ligne" pour pouvoir en compter 3.

    En C c'est pareil.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  9. #9
    Membre habitué
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2021
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2021
    Messages : 11
    Par défaut
    Encore merci, tout cela est vraiment trèèèèès loin !

    Le code que j'ai mis ici n'est pas le vrai code, c'était une illustration d'un problème que je rencontrais. Je m'étais trop emmêlé les pinceaux pour vous demander des explications sur mon vrai code.

    A la base, je voulais un tableau unique que je devais trier selon certain paramètres. Le contenu du tableau change tout le temps, et mes threads (en vérité, ce sont des interruptions, mais la nature du problème reste le même) ont besoin d'un tableau trié. Donc plutôt que de trier le tableau lui même avec le risque certain qu'à un moment, les interruptions vont taper dedans pendant le tri, je voulais faire un tableau de pointeurs vers les cases du tableau dans le bon ordre.
    Sauf que ça ne résout pas vraiment le problème des accès concurrent (comprendre intempestif) puisqu'il aut bien prendre le temps de construire le tableau de pointeurs. Donc je voulais faire 2 tableaux de pointeurs, triés chacun leur tours, et une variable qui indique quel tableau de pointeur n'est pas en train d'être trié et peut donc être utilisé par les threads.
    Et la, j'ai réalisé que mon tableau principal pouvait être modifié pendant le tri... Donc je me suis dit tant pis, je ne peux pas travailler sur un simple tableau de pointeur, il faut que je travaille sur des copies du tableau qui se seront figé jusqu'au prochain rafraichissement du tri.

    Oui, c'est compliqué... Surtout pour se remettre au C après 15-20 ans...

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. modifier une case d'une liste de structures
    Par kronoss dans le forum C#
    Réponses: 5
    Dernier message: 02/05/2010, 09h22
  2. Ajouter une case à cocher par ligne dans mon tableau
    Par beegees dans le forum Langage
    Réponses: 4
    Dernier message: 02/11/2008, 10h30
  3. Réponses: 2
    Dernier message: 12/05/2007, 01h57
  4. Réponses: 3
    Dernier message: 27/02/2007, 21h12
  5. Comment modifier une BufferedImage alimenté par un Thread
    Par jlassiramzy dans le forum AWT/Swing
    Réponses: 3
    Dernier message: 02/08/2006, 15h04

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