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 :

probleme etrange de passage de parametre


Sujet :

C

  1. #1
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut probleme etrange de passage de parametre
    salut a tous,

    Voici le code de deux fonctions, toutes simples :

    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
    /test/src> more parser.c
    #include "biblio.h"
    
    void* parser(void *p)
    {
            int i;
            printf("debut du parsing des fichiers GRE et FNR...\n");
            int lignedebut = 1;
            int lignefin = 5;
            char * entreeformatee;
            char ** donnees;
    
            donnees = lireligne("test.csv", lignedebut, lignefin);
    
            for (i = 0; i < (lignefin - lignedebut); i++)
            {
    printf("\n%s\n", donnees[i]);
                    entreeformatee = formaterentree(donnees[i]);
    printf("\n%s\n",entreeformatee);
                    ajouterentree(CHEMINFIC_DONNEES_COMP, entreeformatee);
            }
            (void)p;
            return NULL;
    }
    
    
    /test/src> more ajouterentree.c
    #include "biblio.h"
    
    void ajouterentree(char * cheminfichier, char * nouvellentree)
    {
    
            printf("%s\n", nouvellentree);
            FILE * fichier;
            if ((fichier = fopen(cheminfichier, "a"))!=NULL)
            {
                    fprintf(fichier, "%s\n", nouvellentree);
                    fclose(fichier);
            }
    
    
    
    }
    j'ai mis deux lignes en rouge.
    le résultat de cette première ligne est toto, par exemple. ou un truc beaucoup plus long. peu importe.
    le résultat de la deuxième ligne est "", soit rien.



    Pourquoi?

  2. #2
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    il faudrait avoir le code de formaterentree

  3. #3
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut
    le voici

    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
    /test/src> more formaterentree.c
    #include "biblio.h"
     
     
    char * formaterentree(char * donnees)
    {
            char * temp;
            char ** temp2;
            char donneefin[200];
            FILE * fichier;
            int i = 0;
     
            //remplir donneefin en fonction de donnnees P3G
     
            //MSISDN
            strcat(donneefin, strtok(donnees, ";"));
            strcat(donneefin, ";");
     
            //IMSI
            strcat(donneefin, strtok(NULL, ";"));
            strcat(donneefin, ";");
     
            //NO_HLR_REF
            temp = strtok(NULL, ";");
            strcat(donneefin, temp);
            strcat(donneefin, ";");
     
     
            //HLR_REF
            if (strcmp(temp, "")!=0)
            {
                    i = chercher(CHEMINTAB_ASS_HLR, temp);
                    if (i>0)temp2 = lireligne (CHEMINTAB_ASS_HLR, i, i);
                    strtok(temp2[0], ";");
                    strcat(donneefin, strtok(NULL, ";"));
            }
            strcat(donneefin, ";");
     
     
            //remettage du curseur de strtok a l'endroit precedent le HLR_REF
            strtok(donnees, ";");
            for(i = 0; i < 2; i++)strtok(NULL, ";")
     
            donnees = donneefin;
            return donnees;
    }
    le rendu? ça donne quelquchose comme ça :

    33660141414;208209865774349;HLR02;11089;

  4. #4
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    beaucoup de choses qui ne vont pas :

    • strtok modifie (en mettant des NULL) la chaîne en entrée
    • la chaine en entrée n'est pas passée par pointeur, donc son adresse n'est pas modifiable
    • tu assignes à une chaine ressortante un buffer local, qui donc n'a plus d'existence en sortie de la fonction.


    Corrige ça, et ça marchera..

  5. #5
    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
    Tu peux ajouter à la liste des erreurs celle-ci :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char * formaterentree(char * donnees)
    {
    ....
            char donneefin[200];
    ....
            strcat(donneefin, strtok(donnees, ";"));
    strcat suppose que les DEUX arguments soient des chaines correctement formées, c'est à dire terminée par '\0'. Ce n'est pas le cas ici du tableau (local) non initialisé donneefin.
    - initialise char donneefin[200] = "" ou donneefin[0] = '\0';
    - ou utilise strcpy

    * L'erreur de principe la plus grave est signalée par souviron34 : tu retournes l'adresse d'une variable locale (donneefin)

  6. #6
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut
    je vous remercie de vos conseils et je vais immédiatement les mettre avec exécution. Toutefois, une question se pose : comment se fait-il que même à ce paquet d'erreurs, je suis capable d'obtenir de la fonction appelante (parser.c) la chaîne voulue, sans défaut? en gros quand je vais printf(donneeformatee); dans parser(), ça m'écrit quand même en console la chaîne formatée correctement?

  7. #7
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut
    Je pense que personne ne répondra... c'est pas grave. Ca marche maintenant!! donc merci. Voici le code final :

    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
    /test/src> more formaterentree.c
    #include "biblio.h"
     
     
    char * formaterentree(char * donnees)
    {
            char * temp;
            char ** temp2;
            char donneefin[200] = "";
            FILE * fichier;
            int i = 0;
     
            //remplir donneefin en fonction de donnnees P3G
     
            //MSISDN
            strcat(donneefin, strtok(donnees, ";"));
            strcat(donneefin, ";");
     
            //IMSI
            strcat(donneefin, strtok(NULL, ";"));
            strcat(donneefin, ";");
     
            //NO_HLR_REF
            temp = strtok(NULL, ";");
            strcat(donneefin, temp);
            strcat(donneefin, ";");
     
     
            //HLR_REF
            if (strcmp(temp, "")!=0)
            {
                    i = chercher(CHEMINTAB_ASS_HLR, temp);
                    if (i>0)temp2 = lireligne (CHEMINTAB_ASS_HLR, i, i);
                    strtok(temp2[0], ";");
                    strcat(donneefin, strtok(NULL, ";"));
            }
            strcat(donneefin, ";");
     
     
            //remettage du curseur de strtok a l'endroit precedent le HLR_REF
            strtok(donnees, ";");
            for(i = 0; i < 2; i++)strtok(NULL, ";");
     
     
            strcpy (donnees, donneefin);//plante
            return donnees;
    }

    A propos, ok la fonction strtok ne correspond pas à mes besoins, je vais en écrire une moi-même qui ne bousille pas ma chaîne et qui fait ce que j'attends d'elle.

    Merci encore

  8. #8
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par crashtib Voir le message
    je vous remercie de vos conseils et je vais immédiatement les mettre avec exécution. Toutefois, une question se pose : comment se fait-il que même à ce paquet d'erreurs, je suis capable d'obtenir de la fonction appelante (parser.c) la chaîne voulue, sans défaut? en gros quand je vais printf(donneeformatee); dans parser(), ça m'écrit quand même en console la chaîne formatée correctement?
    parce que il n'y a encore eu aucune instruction (ton print est la première). Donc ce qui est à l'adresse n'est pas encore bousillé.. Mais ça va pas tarder

    Citation Envoyé par crashtib Voir le message
    A propos, ok la fonction strtok ne correspond pas à mes besoins, je vais en écrire une moi-même qui ne bousille pas ma chaîne et qui fait ce que j'attends d'elle.

    Merci encore
    tu as toujours le même problème à la fin :

    tu ne dois pas faire un strcpy dans donnees (puisque tu rajoutes quelque chose, vraisembablement donnes est plus petit que donnesfin). Ou alors il faut que donnes soit au minimum de la taille de donnesfin.

    Et ensuite tu continues a retourner donnes en résultat, ce qui, on l'a déjà dit, n'est pas correct puiqu'il est passé en paramètre..

  9. #9
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut
    mais comment faire alors? tu as raison et je suis en effet en train de me battre avec ça. Je ne vois pas de solution à part passer en parametre une chaine vide super grosse, que je traite après dans la fonction appelante.... c'est lourd. et en plus c'est gourmand.

    d'autre part, j'aimerai que vous jetiez un coup d'oeuil sur la fonction équivalente à strtok que j'ai faite, s'il vous plait :

    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
    /test/src> more estrtok.c
    #include "biblio.h"
     
    //cette fonction renvoie la n-ieme chaine de carateres dans la chaine originale passee en argument, dont delim est le caractere delimiteur
    //le n est passe en parametre egalement
     
    char * estrtok(char * chaine, char delim, int num)
    {
     
            int i;
            int numerolu;
            char resultat[200];
     
            i = 0;
            numerolu = 0;
            resultat[0] = '\0';
     
            //on cherche la num-ième occurence de delim pour lire le mot qui nous intéresse
            while ((i != num)&&(chaine[numerolu] != '\0'))
            {
                    if (chaine[numerolu] == delim)i++;
                    numerolu++;
            }
            i = 0;
            //le mot situé juste après le bon delim va etre copié dans résultat
            while ((chaine[numerolu] != delim)&&(chaine[numerolu] != '\0'))
            {
                    resultat[i] = chaine[numerolu];
                    numerolu++;
                    i++;
            }
            //terminer resultat par fin de chaine
            resultat[i] = '\0';
     
            return resultat;
    }
    alors je sais ce que vous allez me dire (d'ailleurs un warning du compilo me le dit aussi) : "TU RENVOIES UNE DONNEE LOCALE, TU VAS TE FAIRE JETER!"

    certes. mais comme tu l'as dit souviron, l'adresse n'est pas encore bousillée. Je compte me servir de cette fonction généralement dans des printf ou strcat, rien de plus. donc je ne souhaite pas stocker ces chaines renvoyées à long terme (puisque si j'ai besoin de nouveau de cette chaine, je réinvoque estrtok).

    Est-il correct d'utiliser cette fonction, donc d'utiliser une chaine qui sera bousillée prochainement, si on l'utilise toujours dans un cadre où ça marche systématiquement? en gros, vu que dans le cadre où je l'utilise, ça marche, est-il obligatoire de corriger cette connerie?

    ok c'est pas propre, mais ça marche...

    je sens que je vais pas me faire apprécier ici

  10. #10
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    bah pour ce que tu veux faire :

    • strchr serait mieux que strtok
    • faire de l'allocation dynamique, ou bien s'assurer que donnees est de dimension 200..

  11. #11
    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
    Est-il correct d'utiliser cette fonction, donc d'utiliser une chaine qui sera bousillée prochainement, si on l'utilise toujours dans un cadre où ça marche systématiquement? en gros, vu que dans le cadre où je l'utilise, ça marche, est-il obligatoire de corriger cette connerie?

    ok c'est pas propre, mais ça marche...
    C'est tout à fait incorrect et le comportement est totalement imprévisible (ça peut même parfois sembler marcher, ce qui est une grande malchance). Il n'y a pas de cadre où ça marche systématiquement.
    C'est effectivement une c.... et de taille. A corriger ABSOLUMENT.

  12. #12
    Membre confirmé Avatar de crashtib
    Homme Profil pro
    Support technico-fonctionnel
    Inscrit en
    Avril 2009
    Messages
    221
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Support technico-fonctionnel
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2009
    Messages : 221
    Par défaut
    c'est noté. et corrigé. merci en tout cas de vos réponses à tous.

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

Discussions similaires

  1. Probleme avec gridview...passage de parametre sqlDatasource
    Par tilily dans le forum Général Dotnet
    Réponses: 0
    Dernier message: 23/01/2009, 13h40
  2. Réponses: 7
    Dernier message: 20/03/2006, 12h19
  3. [XSL][PHP] probleme de passage de parametres...
    Par jesus144 dans le forum XSL/XSLT/XPATH
    Réponses: 3
    Dernier message: 20/06/2005, 23h25
  4. [pgplsql] probleme de passage de parametre
    Par Spoutnik dans le forum PostgreSQL
    Réponses: 1
    Dernier message: 21/05/2004, 01h11
  5. Probleme de passage de parametre a un TQuery
    Par gve21 dans le forum C++Builder
    Réponses: 7
    Dernier message: 15/01/2004, 15h49

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