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 :

Modification tableau par référence


Sujet :

C

  1. #1
    Membre confirmé
    Profil pro
    Developpeur
    Inscrit en
    Septembre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Septembre 2004
    Messages : 114
    Par défaut Modification tableau par référence
    Bonjour,

    Je vous explique mon problème.
    J'ai un tableau à plusieurs dimensions :

    automate[0][1]="a\0";
    automate[0][2]="b\0";
    automate[1][1]="b\0";
    automate[1][2]="a\0";
    automate[2][0]="b\0";

    Je le passe par référence à une fonction censée modifiée ses valeurs.

    La fonction ressemble à cela :
    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
    37
    38
    39
     
     for(n=0;n<nbPred;n++)
             for(p=0;p<nbSucc;p++){
     
                 char tmp[4096]="";
     
                 strcat(tmp ,accoD);
     
                 // Creation de la grammaire pour le chemin pred[n] -> succ[n]
                 strcat(tmp ,automate[pred[n]][noeud]);           
     
                 if(automate[noeud][noeud]!=" "){
                    strcat(tmp ,automate[noeud][noeud]);
                    strcat(tmp ,"*\0");
                }
     
                strcat(tmp ,automate[noeud][succ[p]]);             
     
                strcat(tmp ,accoF);
     
                // Si chemin directe entre pred[n] -> succ[n] on l'ajoute avec un |
                if(automate[pred[n]][succ[p]]!=" "){
                    strcat(tmp ,"|\0");
                    strcat(tmp ,accoD);
                    strcat(tmp ,automate[pred[n]][succ[p]]);
                    strcat(tmp ,accoF);
     
     
                 }
     
                printf("de %i à %i : %s \n",pred[n],succ[p],tmp);
                automate[pred[n]][succ[p]]=tmp;
    printf("après -  %s \n",automate[pred[n]][succ[p]]);
     
             strcat(expr ,tmp);
     
     
             }
    ...
    Pour vous expliquer mon problème, si j'affiche les valeurs de tmp après chaque tour de boucle, les résultats sont corrects.
    Mon tableau automate est bien modifié cependant, toutes les valeurs qui doivent être modifiées se retrouvent avec la dernière valeur de tmp et non leur valeur respective.
    Comme si la valeur tmp etait un pointeur sur une valeur et que c'était l'adresse qui etait mis dans le tableau.

    QUelqu'un pourrait m'aider ?

    Merci d'avance

  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
    Le code que tu fournis est, à mon sens, insuffisant pour se prononcer. Montre la partie appel de la fonction, sa déclaration et la déclaration des variables impliquées.

  3. #3
    Membre confirmé
    Profil pro
    Developpeur
    Inscrit en
    Septembre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Septembre 2004
    Messages : 114
    Par défaut
    La declaration du tableau est ainsi :
    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
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
     
    char* automate[Dimension][Dimension];
    char * expr;
     
    	automate[0][1]="a\0";
    	automate[0][2]="b\0";
    	automate[1][1]="b\0";
    	automate[1][2]="a\0";
    	automate[2][0]="b\0";
     
    // appel de la premiere fonction
    //char * afer(char * automate[Dimension][Dimension]){
     
     expr = afer(automate);
     
    // Dans cette meme fonction j'appel x fois la fonction pour chaque noeud 
    //char * supprNoeud(int noeud, char * automate[Dimension][Dimension]){
     
    tmp = supprNoeud(0, automate);
     
    ...
    // dans suppr noeud il y a le code en haut 
    ...
     for(n=0;n<nbPred;n++)
             for(p=0;p<nbSucc;p++){
     
                 char tmp[4096]="";
                  strcat(tmp ,accoD);
     
                 // Creation de la grammaire pour le chemin pred[n] -> succ[n]
                 strcat(tmp ,automate[pred[n]][noeud]);
     
                 if(automate[noeud][noeud]!=" "){
                    strcat(tmp ,automate[noeud][noeud]);
                    strcat(tmp ,"*\0");
                }
     
                strcat(tmp ,automate[noeud][succ[p]]);
                strcat(tmp ,accoF);
     
                // Si chemin directe entre pred[n] -> succ[n] on l'ajoute avec un |
                if(automate[pred[n]][succ[p]]!=" "){
                    strcat(tmp ,"|\0");
                    strcat(tmp ,accoD);
                    strcat(tmp ,automate[pred[n]][succ[p]]);
                    strcat(tmp ,accoF);
     
                                }
               automate[pred[n]][succ[p]]=tmp;
     
             strcat(expr ,tmp);
     
     
             }
     
        // On supprime les anciens cehmins
        for(n=0;n<nbPred;n++){
             for(p=0;p<nbSucc;p++){
                automate[pred[n]][noeud]=" ";
                automate[noeud][succ[p]]=" ";
             }
        }
     
         for(n=0;n<Dimension;n++)
          for(p=0;p<Dimension;p++)
            if(automate[n][p]!=" ")
                printf("%d ---- %s ---- %d\n",n,automate[n][p],p);
     
        chaine = NULL;
        chaine = (char*) malloc(strlen(expr)*sizeof(char));
        chaine = expr;
        return chaine;
    Cela est-il assez pour diagnostiquer ?
    Je pensais à un malloc qu'il fallait faire mais vu que le tableau est passé par référence la valeur qu'on lui attribue n'a pas à etre reservé?

    Louis

  4. #4
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char const* automate[Dimension][Dimension];
     
    automate[0][1]="a";
    automate[0][2]="b";
    automate[1][1]="b";
    automate[1][2]="a";
    automate[2][0]="b";

  5. #5
    Membre confirmé
    Profil pro
    Developpeur
    Inscrit en
    Septembre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Septembre 2004
    Messages : 114
    Par défaut
    En effet s'agissant d'une chaine de caractère le caractère fin de chaine est ajouté automatiquement.

    Je ne suis pas d'accord sur le const car je dois pouvoir le modifier ?

    Par contre cela ne résout pas le problème de duplication.
    Mes deux valeurs modifiées se retrouvent identiques dans le tableau automate alors qu'elles ne le sont pas lors de l'affichage dans la boucle :\

  6. #6
    Membre Expert Avatar de nicolas.sitbon
    Profil pro
    Inscrit en
    Août 2007
    Messages
    2 015
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Août 2007
    Messages : 2 015
    Par défaut
    Dans ce cas poste un code qui compile s'il te plaît.

  7. #7
    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
    Ce code n'est pas très cohérent :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    char* automate[Dimension][Dimension];
    char * expr;
     
    	automate[0][1]="a\0";
    	automate[0][2]="b\0";
    Ici, on place dans automate[0][1],... l'adresse d'une chaîne non modifiable , ce qui a fait suggérer à nicolas.sitbon de le déclarer explicitement avec le qualificatif const.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     for(n=0;n<nbPred;n++)
             for(p=0;p<nbSucc;p++){
     
                 char tmp[4096]="";
    ....
               automate[pred[n]][succ[p]]=tmp;
    ici, on place dans automate l'adresse d'une variable locale (tmp=adresse du premier élément du tableau temp). Or le tableau sera détruit en sortie de la fonction et cette adresse n'aura plus de sens. De plus, la même valeur tmp (adresse du premier élément du tableau temp) est utilisée pour toutes les valeurs de n et p.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    ...
        chaine = NULL;
        chaine = (char*) malloc(strlen(expr)*sizeof(char));
        chaine = expr;
        return chaine;
    Je ne sais pas bien la nature de expr d'après le code présenté.
    Par contre, après allocation de chaine, la ligne suivante détruit la valeur retournée par le malloc (la mémoire allouée est alors perdue dans la nature) pour la remplacer par l'adresse expr. Je suppose que l'intention était de dupliquer la chaine expr dans la chaîne chaine. Si c'est le cas, il faut faire une copie de la chaîne (par exemple avec strcpy) et il faut allouer 1 caractère de plus pour placer le 0 terminal.

  8. #8
    Membre confirmé
    Profil pro
    Developpeur
    Inscrit en
    Septembre 2004
    Messages
    114
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Developpeur

    Informations forums :
    Inscription : Septembre 2004
    Messages : 114
    Par défaut
    Le problème avait l'air de venir de la non reserve en mémoire pour la chaine tmp ainsi que l'assignation via = au lieu de strcpy :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    chaine = NULL;
    chaine = (char*) malloc(strlen(tmp)*sizeof(char));
    strcpy(chaine,tmp);
    Merci aussi à nicolas.sitbon de m'avoir accorder du temps via MP.

    Bonne journée à vous

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    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 395
    Par défaut
    N'oublie pas le zéro terminal.
    De plus, sizeof(char) vaut 1 par définition, alors on va plutôt utiliser un sizeof qui ne nécessite pas de modifier trop le code si un jour on passe en wchar_t :
    Code C : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    chaine = malloc((strlen(tmp)+1)*sizeof(*chaine));
    strcpy(chaine, tmp);
    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.

Discussions similaires

  1. Modification des String dans un tableau par référence
    Par koukoula dans le forum Windows Forms
    Réponses: 13
    Dernier message: 06/06/2008, 15h29
  2. Réponses: 3
    Dernier message: 09/10/2007, 10h50
  3. Réponses: 3
    Dernier message: 19/05/2005, 10h46
  4. Passage d'un tableau par référence?
    Par sebduth dans le forum C
    Réponses: 9
    Dernier message: 16/07/2003, 18h32

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