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 :

Problème de conversion


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 14
    Points : 7
    Points
    7
    Par défaut Problème de conversion
    Bonjour,

    J'ai une erreur que je n'arrive vraiment pas à résoudre ....

    Voici la fonction que j'appelle :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    arbre defineInt(char * element, arbre defGauche, arbre defDroit)
    {
    arbre arb;
    arb=(arbre)malloc(sizeof(noeud));
     
    arb->ope=(char)NULL;
    arb->value = element;
    arb->filsGauche=defGauche;
    arb->filsDroit=defDroit;
     
    return arb;
    }
    Et dans une autre fonction je déclare un char tmp[100] = ""; dans lequel j'ajoute des caractères de cette façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    sprintf(tmp,"%s%c",tmp,chaine[i]);
    // J'ai aussi essayé en faisant tmp[i] = chaine[i]
    Puis j'appelle ma fonction defineInt en y ajoutant mon paramètre tmp. Hors une fois arrivée dans la fonction, ma variable vaut plein de IIIIIII .... Alors que lors de l'appel tmp vaut bien par exemple 15 ....

    Merci d'avance pour votre aide.

  2. #2
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    Citation Envoyé par RodolpheL Voir le message
    Puis j'appelle ma fonction defineInt en y ajoutant mon paramètre tmp. Hors une fois arrivée dans la fonction, ma variable vaut plein de IIIIIII .... Alors que lors de l'appel tmp vaut bien par exemple 15 ....
    Peux tu nous montrer le code de defineInt avec ce paramètre supplémentaire ?

  3. #3
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    En fait, je vais expliquer ce que prennent les variables lorsque je debug mon programme.

    par exemple :

    char tmp[sizeTab] = "";

    Après traitement d'une fonction, ma variable tmp = "15".
    Jusque là aucun problème.

    Hors une fois que j'appel :
    defineInt(tmp,NULL,NULL)

    Lors du débogage, ma variable element de la fonction defineInt qui aura la valeur du tmp dans mon cas présent aura :

    "ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌQ"

    PS : J'ai copié la valeur à partir de visual studio ....

  4. #4
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Hors une fois que j'appel :
    defineInt(tmp,NULL,NULL)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    arbre defineInt(int element, arbre defGauche, arbre defDroit)
    Quel micmac : tmp est un tableau de char, pas un int. Le compilateur a certainement signalé cette erreur comme avertissement.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Citation Envoyé par diogene Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    arbre defineInt(int element, arbre defGauche, arbre defDroit)
    Quel micmac : tmp est un tableau de char, pas un int. Le compilateur a certainement signalé cette erreur comme avertissement.
    Oups, excusez moi, j'ai mal copié le code, ma fonction defineInt prend bien en premier paramètre un char *.

  6. #6
    Invité(e)
    Invité(e)
    Par défaut
    Le problème est ici : Une copie de chaine de caratère ne se fait pas avec '=', mais avec str[n]cpy.

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    J'obtiens une violation d'accès lorsque je fais le strncpy. Ca devient vraiment compliqué ...

    En fait j'utilise un arbre binaire pour stocker les chiffres (pas en int mais en char *) d'une opération saisie par l'utilisateur. Et vu que je ne veux plus utiliser les int qui nous bloquent en longueur, j'utilise encore en plus une liste doublement chaînée avec laquelle je fais appel à des fonctions que j'ai créée qui me font des soustractions, addition et multiplication ... Sacré prof qui veut nous rendre fou !

    Tanpis je vais laisser tomber cette façon de faire avec l'arbre binaire.

    Merci.

  8. #8
    Invité(e)
    Invité(e)
    Par défaut
    Citation Envoyé par RodolpheL Voir le message
    J'obtiens une violation d'accès lorsque je fais le strncpy. Ca devient vraiment compliqué ...
    Poste ton code.

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Voici le code de la fonction creation et define Int et valeurProchaine :

    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
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
     
    arbre defineInt(char * element, arbre defGauche, arbre defDroit)
    {
        arbre arb;
        arb=(arbre)malloc(sizeof(noeud));
     
        arb->ope=(char)NULL;
        strcpy(arb->value,element);
        arb->filsGauche=defGauche;
        arb->filsDroit=defDroit;
     
        return arb;
    }
     
    arbre defineChar(char element, arbre defGauche, arbre defDroit)
    {
        arbre arb;
        arb=(arbre)malloc(sizeof(noeud));
     
        arb->ope=element;
        arb->value = "";
        arb->filsGauche=defGauche;
        arb->filsDroit=defDroit;
     
        return arb;
    }
     
    char * prochainEntier(char* chaine, int position)
    {
        int i = position;
        char tmp[sizeTab] = "";
     
        if((chaine[i-2] == OPT_MULT) && ((chaine[i-1] == OPT_MOINS) || (chaine[i-1] == OPT_PLUS)))
        {
            sprintf(tmp,"%s%c",tmp,chaine[i-1]);
        }
     
        while((chaine[i] != OPT_PLUS) && (chaine[i] != OPT_MOINS) && (chaine[i] != OPT_MULT) && (i < strlen(chaine)))
        {   
            sprintf(tmp,"%s%c",tmp,chaine[i]);
            i++;
        }
     
        return (tmp);
    }
     
     
    arbre creation(char* chaine)
    {
        int i = 0;
        int y = 0;
        char * valeurProchaine = "";
        char * valeurAvant = "";
        char * tmpValue = "";
        char tmp[sizeTab] = "";
        char tmp2[sizeTab] = "";
        noeud *nodeTmp;
        nodeTmp = NULL;
        int increment = 0;
        bool par = false;
     
        for(i = 0; i < strlen(chaine); i++)
        {
            if (((chaine[i] == OPT_PLUS) || (chaine[i] == OPT_MOINS) || (chaine[i] == OPT_MULT)) && (!par) && (i!=0))
            {
                if ((chaine[i+1] != PAR_OPEN))
                {
                    if((chaine[i+1] == OPT_PLUS) || (chaine[i+1] == OPT_MOINS))
                    {
                        if((chaine[i] == OPT_MOINS) && (chaine[i+1] == OPT_PLUS))
                            chaine[i+1] = OPT_MOINS;
                        if((chaine[i] == OPT_MOINS) && (chaine[i+1] == OPT_MOINS))
                            chaine[i+1] = OPT_PLUS;
                        i++;
                    }
     
                    valeurProchaine = prochainEntier(chaine,i+1);
                    if (nodeTmp != NULL)
                    {
                        if(chaine[i] == OPT_MULT || chaine[i-1] == OPT_MULT){
                            sprintf(nodeTmp->filsDroit->value,"%d",atoi(nodeTmp->filsDroit->value) * atoi(valeurProchaine))    ;       
                        }           
                        else{
                            if((chaine[i-1] == OPT_MULT) && ((chaine[i] == OPT_MOINS) || (chaine[i] == OPT_PLUS)))
                                i--;
                            nodeTmp = defineChar(chaine[i], nodeTmp, defineInt(valeurProchaine, NULL, NULL));
                        }
                    }
                    else if (tmpValue == "")
                    {
                        if((chaine[i-1] == OPT_MULT) && ((chaine[i] == OPT_MOINS) || (chaine[i] == OPT_PLUS)))
                        {
                            sprintf(tmp,"%d",atoi(tmp)*atoi(valeurProchaine))    ;
                            valeurProchaine = "";
                            i--;
                            chaine[i] == OPT_PLUS;
                        }
    					valeurAvant = tmp2;
                        nodeTmp = defineChar(chaine[i], defineInt(valeurAvant, NULL, NULL), defineInt(valeurProchaine, NULL, NULL));
                    }
     
                }
                else if(chaine[i+1] == PAR_OPEN)
                {
                    valeurProchaine = traitementPar(chaine, i+2);
                    if (nodeTmp != NULL)
                    {
                        if(chaine[i] == OPT_MULT){
                            sprintf(nodeTmp->filsDroit->value,"%d",atoi(nodeTmp->filsDroit->value) * atoi(valeurProchaine))    ;           
                        }
                        else{
                            nodeTmp = defineChar(chaine[i], nodeTmp, defineInt(valeurProchaine, NULL, NULL));
                        }
                    }
                    else
                    {
                        nodeTmp = defineChar(chaine[i], defineInt(valeurAvant, NULL, NULL), defineInt(valeurProchaine, NULL, NULL));
                    }           
                }
     
            }
            else if((nodeTmp == NULL) && (!par))
            {
                if(chaine[i] == PAR_OPEN)
                {
                    valeurProchaine = traitementPar(chaine, i+1);   
                    nodeTmp = defineChar('+', defineInt(0, NULL, NULL), defineInt(valeurProchaine, NULL, NULL));
                }
                else
                    tmp2[i] = chaine[i];
            }
            if (chaine[i] == PAR_OPEN)
            {
                par = true;
                increment++;
            }
            if (chaine[i] == PAR_CLOSE)
            {
                increment--;
                if (increment == 0)
                    par = false;
            }
        }
     
        tempValue = "";
        return nodeTmp;
    }
    Et j'ai un problème dès que j'arrive dans la fonction defineInt. Element aura une valeur horrible.

  10. #10
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Je parie que le champ value est un pointeur et pas un tableau.

    Pour stocker une chaine, il faut un tableau.
    Donc, fait une allocation dynamique pour ce tableau de longueur strlen(element)+1 avant la copie et met l'adresse dans value.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    En fait value est compris dans une structure qui est définie comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    typedef struct elem{
        char ope;
        char * value;
        struct elem* filsGauche;
        struct elem* filsDroit;
    }noeud, *arbre;
    Il faudrait que je pousse le char * value en char value[sizeTab]?
    Ca me paraitrait bizarre que ça change quelque chose vu qu'en déboguant avec visual studio comme dit précédemment, je passe bien en paramètre une chaine qui vaut 15 mais dans la fonction defineInt element vaut IIIIIIIIIIIIII (chaine bizarre ).

  12. #12
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    De toute façon, il te faut un tableau, alloué dynamiquement ou non !

    ...je passe bien en paramètre une chaine qui vaut 15 mais dans la fonction defineInt element vaut IIIIIIIIIIIIII (chaine bizarre ).
    Que veux tu qu'on puisse dire sur ça, on ne connait pas le code qui appelle la fonction ?

    Une chaine qui vaut 15 (???) ou une chaine qui vaut "15" ?
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  13. #13
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Elle vaut bien "15" ma variable valeurAvant que je passe en paramètre à la fonction defineInt ou la variable 'element' devrait donc valoir "15" mais là j'obtiens une chaîne de n'importe quoi ...

    C'est pas grave, je vais laisser tomber cette façon de faire avec des chaînes dans chaque node d'un arbre.

  14. #14
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    C'est pas grave, je vais laisser tomber cette façon de faire avec des chaînes dans chaque node d'un arbre
    Ce n'est pas une solution d'abandonner à la première difficulté : tu ne feras jamais de progrès.


    Un problème grave ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    char * prochainEntier(char* chaine, int position)
    {
        int i = position;
        char tmp[sizeTab] = "";
    .....
        return (tmp);
    }
    Il ne faut jamais retourner l'adresse d'une variable locale : celle-ci est détruite en sortie de fonction. Il est alors interdit d'utiliser en quelque façon la valeur de retour de cette fonction !
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  15. #15
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Je ne comprends pas la gravité de ce problème, je retourne tmp et immédiatement lors de l'appel de la fonction, j'alloue cette valeur de retour (tmp) dans une variable de la fonction creation.

    Tmp sera bien détruite mais la valeur aura été transmise à une autre variable vu qu'elle m'a toujours retourné la bonne valeur à moins qu'il y ait une façon de faire en C bien plus propre ?

  16. #16
    Membre chevronné
    Profil pro
    Inscrit en
    Août 2006
    Messages
    1 104
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 1 104
    Points : 1 750
    Points
    1 750
    Par défaut
    Je ne comprends pas la gravité de ce problème
    Ce tableau (qui est local) est stocké sur la pile, qui est un espace mémoire où des valeurs sont empilées et dépilées en permanence (appel de fonctions, sortie de fonction, etc). Une fois que tu quittes la fonction, absolument rien ne peut donc te garantir que les données qui étaient écrites à cet emplacement sont toujours intactes. Ces données peuvent ensuite être écrasées.
    Retourner une adresse sur un objet local peut conduire à un bug voire un crash, car tu retournes une adresse sur un espace mémoire dont le contenu est susceptible d'être modifié n'importe quand par n'importe quoi.

    je retourne tmp et immédiatement lors de l'appel de la fonction, j'alloue cette valeur de retour (tmp) dans une variable de la fonction creation.
    Voilà ce qui se passe :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
                    valeurProchaine = prochainEntier(chaine,i+1);
                    if (nodeTmp != NULL)
                    {
                        if(chaine[i] == OPT_MULT || chaine[i-1] == OPT_MULT){
                            sprintf(nodeTmp->filsDroit->value,"%d",atoi(nodeTmp->filsDroit->value) * atoi(valeurProchaine))    ;       
                        }(...)
    Tu stockes l'adresse retounée (et non pas le contenu de cette adresse) par la fonction prochainEntier dans un pointeur. Puis une ou plusieurs fonctions sont appelées par la suite, qui provoque de nouveaux empilements sur la pile. En gros, un beau remue-ménage de la pile. A ce stade, rien ne permet d'affirmer que les valeurs du tableau sont encore intactes.

    à moins qu'il y ait une façon de faire en C bien plus propre ?
    Tu peux par exemple passer l'adresse d'un tableau (dynamique ou non) à ta fonction (et non pas créer ce tableau dans la fonction appelée). Ou bien allouer dynamiquement un tableau à l'intérieur de ta fonction appelée... voire de la fonction appelante (mais dans ce cas, ça va devenir compliqué, avec l'apparition de pointeurs de pointeurs).

  17. #17
    Expert éminent sénior
    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
    Points : 13 926
    Points
    13 926
    Par défaut
    Tmp sera bien détruite mais la valeur aura été transmise à une autre variable
    Ce qui est alors transmis, c'est l'adresse d'une variable qui n'existe plus (l'adresse du premier élément du tableau qui lui est détruit en sortie de la fonction).
    Le système peut récupérer à sa guise et sans prévenir cette zone mémoire pour en faire ce qu'il veut.

    Le tableau peut encore être intact (ou non, on ne peut pas prévoir) au retour dans creation() et ne plus l'être dans defineInt()

    C'est une erreur fatale !
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  18. #18
    Futur Membre du Club
    Profil pro
    Inscrit en
    Février 2010
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2010
    Messages : 14
    Points : 7
    Points
    7
    Par défaut
    Alors là chapeau, merci à vous deux pour cet éclairement !! J'utilise depuis peu le C et ça me permet de voir les traitements effectués autrement. Il va falloir que je revois tout mon code.

Discussions similaires

  1. problème de conversion de dimension dans BUSINESS OBJECT
    Par greatmaster1971 dans le forum Deski
    Réponses: 4
    Dernier message: 28/04/2014, 13h15
  2. - [CAST ou CONVERT] Problème de conversion de date
    Par Boublou dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 06/07/2004, 14h31
  3. Problème de conversion 3DS->.X
    Par JBernn dans le forum DirectX
    Réponses: 5
    Dernier message: 08/04/2004, 19h08
  4. Problème de conversion unicode
    Par djmalo dans le forum C
    Réponses: 5
    Dernier message: 09/03/2004, 11h48
  5. Réponses: 11
    Dernier message: 02/09/2003, 14h20

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