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 avec fgets


Sujet :

C

  1. #1
    Membre du Club Avatar de fabpeden
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 131
    Points : 60
    Points
    60
    Par défaut Problème avec fgets
    salut à tous, j'ai une erreur très étrange, j'ai deux fonctions :
    TraitementSMS et DetermineTypeBoitier

    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
    void TraitementSMS() 
    {
    char *LigneLue;   // Contient la ligne lue du fichier texte
    char TypeBoitier; // Contient la lettre qui détermine le type de boitier
     
        LigneLue = (char*)malloc(sizeof(char));
     
        //---Déclarations et initialisations des données---//
        TypeBoitier = DetermineTypeBoitier();
     
        //---Ouverture du fichier de données---//
        FILE *f = NULL;
        f = fopen("CompteurP.txt","r");   
        if(f == NULL)
        {
          perror("fopen");
          exit(EXIT_FAILURE);
        } 
     
        fgets(LigneLue,100,f);
        printf("%s",LigneLue);
    fclose(f);
    et

    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
    char DetermineTypeBoitier()
    {
     //---Déclarations et initialisations des variables---//
        char *pointeur;
        char LigneLue[100];
     
        int NbLigne = 0;
     
        FILE *fp;
     
        //---Ouverture du fichier de données---//
        fp = fopen("CompteurP.txt","r");
        if(fp == NULL)
        {
         perror("fopen");
         exit(EXIT_FAILURE);
        }
     
        //---On lit les 2 premières lignes du fichier---//
        while(NbLigne <2)
        {          
            fgets(LigneLue,100,fp);
            NbLigne++;
        }
    fclose(fp);
    }
    Le problème est que pour la fonction DetermineTypeBoitier, la fonction fgets fonctionne très bien, le résultat obtenu est correct. Ensuite je réouvre le même fichier, je refais fgets et là l'exécution du programme plante. De plus, à l'origine un autre programme utilisait ces fonctions qui marchaient très bien, donc je trouve cela bien étrange...

  2. #2
    Membre éprouvé
    Avatar de Freed0
    Profil pro
    Étudiant
    Inscrit en
    Mars 2005
    Messages
    635
    Détails du profil
    Informations personnelles :
    Âge : 36
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2005
    Messages : 635
    Points : 953
    Points
    953
    Par défaut
    Salut

    Ta fonction TraitementSMS est incomplète Donc il manque déjà le fclose

  3. #3
    Expert éminent sénior
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Points : 13 380
    Points
    13 380
    Par défaut
    Dans ta boucle while dans la 2ème fonction, la condition de sortie ne change jamais.

    D'où vient LigneLue ???

    Variable globale ?

    Pis y'a plein de variable pas déclaré c'est horrible ?

    Tu fais du multi-thread ???

  4. #4
    Membre du Club Avatar de fabpeden
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 131
    Points : 60
    Points
    60
    Par défaut
    Désolé pour les variables, je les ai enlevé de mon post pour ne pas rendre l'ensemble illisible. De même pour la boucle, j'ai essayé de réduire le code au minimum, mais je vais arranger cela.

  5. #5
    Expert éminent sénior
    Avatar de Skyounet
    Homme Profil pro
    Software Engineer
    Inscrit en
    Mars 2005
    Messages
    6 380
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Software Engineer
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2005
    Messages : 6 380
    Points : 13 380
    Points
    13 380
    Par défaut
    Quant au fclose il faut l'englober dans ton if(fp != NULL)

    [EDIT] J'ai rien dis tu as un if(fp == NULL) désolé.

  6. #6
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void TraitementSMS() 
    {
    char *LigneLue;   // Contient la ligne lue du fichier texte
    ...
        LigneLue = (char*)malloc(sizeof(char));
    ...
        fgets(LigneLue,100,f);
    Il y a la place pour stocker UN caractère, soit le zéro terminal de la chaîne. A la première lecture , on déborde du tableau réservé -> le programme est détruit.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    LigneLue = malloc(100);
    C'est mieux dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char DetermineTypeBoitier()
    {
    ...
        char LigneLue[100];
    ...
       fgets(LigneLue,100,fp);

  7. #7
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Points : 4 637
    Points
    4 637
    Par défaut
    Citation Envoyé par diogene
    C'est mieux dans
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    char DetermineTypeBoitier()
    {
    ...
        char LigneLue[100];
    ...
       fgets(LigneLue,100,fp);
    J'ai une preference pour

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    char LigneLue[100];
    fgets(LigneLue,sizeof LigneLue,fp);
    qui est a est plus facile a faire evoluer

  8. #8
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par fabpeden
    salut à tous, j'ai une erreur très étrange, j'ai deux fonctions :
    TraitementSMS et DetermineTypeBoitier

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    void TraitementSMS() 
    {
       <...>
        fgets(LigneLue,100,f);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    char DetermineTypeBoitier()
    {
       <...>
        while(NbLigne <2)
        {          
            fgets(LigneLue,100,fp);
            NbLigne++;
        }
    La forme canonique pour lire un fichier texte est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
       char ligne[TAILLE];
     
       while (fgets (ligne, sizeof ligne, fp) != NULL)
       {
          /* traiter la ligne */
       }
    ce que tu fais est très douteux... (en gros, aucun contrôle de la validité de la lecture...) et je ne parle pas des pointeurs sur des zones trop petites... C'est pas bien de mentir à son compilateur (genre allouer 1, autoriser 100...)

  9. #9
    Inactif  

    Profil pro
    Inscrit en
    Décembre 2002
    Messages
    534
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2002
    Messages : 534
    Points : 403
    Points
    403
    Par défaut
    Salut,

    De plus si une ligne du fichier excède 100 caractères, le buffer ( ligneLue ) dans fgets, sera en situation de débordement.

  10. #10
    Membre du Club Avatar de fabpeden
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 131
    Points : 60
    Points
    60
    Par défaut
    Voici le code de ma procédure :

    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
    //---Déclarations et initialisations des données---//
        char *LigneLue;   // Contient la ligne lue du fichier texte
        char *DebutSMS;   // Contient l'en tête du SMS
        char *pointeur;   // Contient la chaîne de caractère extraite entre chaque TAB
        char TypeBoitier; // Contient la lettre qui détermine le type de boitier
        char *NumModem;
     
        unsigned int VM_CptIn[96];     // Tableau contenant les DonnéesIn
        unsigned int VM_CptOut[96];    // Tableau contenant les DonnéesOut
     
        unsigned int nb_mot = 1;       // Contient le nombre de chaîne de caractère extraite de la ligne lue
        unsigned int i = 0;
        unsigned int NbLigne = 1;      // Permet de connaître le nombre de ligne du fichier donc l'heure de la fin
     
        DebutSMS = (char*)malloc(sizeof(char));  // allocation de la mémoire pour la variable DébutSMS
       // LigneLue = (char*)malloc(sizeof(char));
     
        //---initialisations des tableaux---//
        for(i=0;i<96;i++)
        {
             VM_CptIn[i] = 0;
             VM_CptOut[i] = 0;                         
        }                 
        i = 0;
     
        // Lecture des deux premières lignes afin de déterminer le type du compteur, P,Q,T,U
        TypeBoitier = DetermineTypeBoitier();
     
        //---Ouverture du fichier de données---//
        FILE *fp = NULL;
        fp = fopen("CompteurP.txt","r");   
     
        //------------------------------------------------------------------------------------//
        // LECTURE DU FICHIER, MISE EN FORME DE L'EN TETE ET REMPLISSAGE DU TABLEAU           //
        //------------------------------------------------------------------------------------//
        while (fgets(LigneLue,100,fp) != NULL)
         {                       
                 printf("Ligne : %s",LigneLue);
                 //--- On extrait la chaîne de caractère qui précède le caractère 0x09(Tabulation)---//
                 pointeur = strtok( LigneLue, "\x09" );
                 printf("s1 : %s\n",pointeur);
                 if(NbLigne == 1)
                 {
                     //---Mise en forme de l'en tête du SMS---//
                     switch (TypeBoitier)
                     {
                            case 'P' : strcat(DebutSMS,"P");
                                       break;
                            case 'T' : strcat(DebutSMS,"T");
                                       break;
                            case 'Q' : strcat(DebutSMS,"Q");
                                       break;
                            case 'U' : strcat(DebutSMS,"U");
                                       break;
                     }
     
                     strcat(DebutSMS,pointeur);
                     NumModem = pointeur;
     
                     //--- selon le type de boitier, on met en forme le début du SMS ---//
                     if ((TypeBoitier == 'P') || (TypeBoitier == 'Q'))
                     {
                         strcat(DebutSMS,"/012/0189/02/C");                 
                     }
                     else
                     {
                         strcat(DebutSMS,"/012/0189/02/I");
                     }
                 } 
                 printf("Ligne : %s",LigneLue);         
                // tant que l'on a pas lu tout le fichier...
                while( pointeur != NULL )
                {
                     // Cherche les autres caractères TAB '0x09' dans la ligne lue
                     pointeur = strtok( NULL, "\x09" );
                     // On a trouvé un caractère TAB
                     if ( pointeur != NULL )
                     {
                         nb_mot++; 
                         printf("s2 : %s\n",pointeur);
                         // Dans un compteur Pilot, on a 3 mots, NumModem,Date,DonnéeCumul
                         // si DonnéeCumul
                         if ((nb_mot == 3) && ((TypeBoitier == 'P') || (TypeBoitier == 'Q')))
                         {
                            VM_CptIn[i] = atoi(pointeur);
                            i++;                                   
                         }
     
                         // Dans un compteur Twin, on a 5 mots, NumModem, Date, DonnéeCumul, DonnéeIn, DonnéeOut
                         // si DonnéeIn
                         if (nb_mot == 4) 
                         {
                            VM_CptIn[i] = atoi(pointeur);
                         }
     
                         // si DonnéeOut
                         if (nb_mot == 5) 
                         {
                            VM_CptOut[i] = atoi(pointeur);
                            i++;
                         }
                     }  
                }
                nb_mot = 1;
                NbLigne++;     
         }
    Il se passe quelque d'étrange, lorsque NbLigne == 1, on passe dans la condition qui va bien, et quand j'affiche LigneLue celle-ci a changé de valeur :
    Par exemple, elle vaut 153TAB20070402150000000TAB1 elle se tranforme en /02/C, ce qui fausse la suite du traitement, je ne comprends pas commment cela est possible?

  11. #11
    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
    On a toujours les mêmes erreurs d'allocation qu'avant. Tu n'as toujours pas compris le problème!
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
        char *DebutSMS;   // 
        char *pointeur;   // Contient la chaîne de caractère extraite entre chaque TAB
    ...
        DebutSMS = (char*)malloc(sizeof(char));  // 1 caractère d'alloué
       // LigneLue = (char*)malloc(sizeof(char)); Pas d'allocation pour LigneLue
    ...
    while (fgets(LigneLue,100,fp) != NULL)
    
    strcat(DebutSMS,.....);

  12. #12
    Membre du Club Avatar de fabpeden
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 131
    Points : 60
    Points
    60
    Par défaut
    C'est en commentaire parce que j'ai testé avec plusieurs cas possibles. Voici ce que j'ai mis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
      DebutSMS = (char*)malloc(sizeof(char));  // allocation de la mémoire pour la variable DébutSMS
         LigneLue = (char*)malloc(100*sizeof(char));
    Mais comment puis-je connaître à l'avance le nombre de caractères que j'aurais besoin pour DebutSMS, je mets une valeur que je choisie?
    J'ai mis 200 et je crois que cela fonctionne bien, je fais faire d'autres tests. Merci en tous cas.

  13. #13
    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
    Mais comment puis-je connaître à l'avance le nombre de caractères que j'aurais besoin pour DebutSMS, je mets une valeur que je choisie?
    - Je ne peux pas répondre à cette question, tu connais ton problème mieux que moi.
    - Dans tous les cas, 1 caractère ne laisse de la place que pour le 0 terminant la chaîne et ça ne peut pas marcher.
    - A cause des strcat que tu fais sur DebutSMS, la chaîne DebutSMS doit être initialisée par un 0 en tête avant.

  14. #14
    Membre du Club Avatar de fabpeden
    Profil pro
    Étudiant
    Inscrit en
    Mars 2007
    Messages
    131
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mars 2007
    Messages : 131
    Points : 60
    Points
    60
    Par défaut
    En tout cas, merci à tous pour votre aide et vos précieux conseils!

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

Discussions similaires

  1. Problème avec fgets
    Par kadd18 dans le forum C
    Réponses: 3
    Dernier message: 28/07/2009, 19h58
  2. Probléme avec fgets
    Par Lucas42 dans le forum C
    Réponses: 2
    Dernier message: 18/11/2007, 03h08
  3. Problème avec fgets() et strlen()
    Par condor_01 dans le forum C
    Réponses: 6
    Dernier message: 28/10/2007, 12h41
  4. problème avec fgets
    Par salseropom dans le forum C
    Réponses: 1
    Dernier message: 03/08/2006, 14h54
  5. Problème avec fgets et tube...
    Par tchingoo dans le forum POSIX
    Réponses: 5
    Dernier message: 22/08/2003, 17h03

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