Lecture dans un fichier : ligne par ligne

Lecture dans un fichier : ligne par ligne - C++ - Programmation

Marsh Posté le 26-04-2003 à 15:42:28    

Salut,
voilà je dois lire un fichier comprenant des commentaires, en évuitant ces caractères !
Mon fichier à lire se présente sous le forme :  


# ceci est un commentaire
nb_noeuds 10
nb_aretes 20
# encore un commentaire
noeud1 noeuds2 10
noeud1 noeuds2 10
noeud1 noeuds2 10
noeud1 noeuds2 10

et ainsi de suite
 
voilà le code de ma fonction.

Code :
  1. void LireGRAPHE ( char * fic_name , GRAPHE *graphe ) {
  2.   FILE * fichier;
  3.   char tampon[256];
  4.   int test_commentaire;
  5.   int test_noeuds;
  6.   int valeur_recuperee, i;
  7.   char * noeud1;
  8.   char * noeud2;
  9.   int poids_arete;
  10.   int dic_num_n1; /* Le N° retourné par le Dico pour le noeud 1 */
  11.   int dic_num_n2; /* Le N° retourné par le Dico pour le noeud 2 */
  12.  
  13.   fichier = fopen( fic_name , "r" );
  14.   if (fichier==NULL) {
  15.     printf("\nProblème lors de l'acces en lecture du fichier !!\nVous n'avez pas les permissions requises, ou le fichier n'existe pas !!\n" );
  16.     exit (1);
  17.   }
  18.   while ( !feof (fichier) ) {
  19.  
  20.     fscanf ( fichier, "%s", tampon);
  21.  
  22.     test_commentaire = strncmp ( tampon , "#" , 1 );
  23.     if ( test_commentaire != 0 ) { /* on a pas à faire à un commentaire !! */
  24. test_noeuds = strcmp ( tampon , "nbNoeuds" );
  25.       if ( test_noeuds == 0 ) {
  26.         /* On recupere le nombre de noeuds du graphe */
  27.         fscanf ( fichier, "%d", &(graphe->nb_noeuds) );
  28.         /* En théorie, on ne fera celà qu'une fois */
  29.         graphe->tla = (TLA) malloc ( (graphe->nb_noeuds+1) * sizeof ( Liste ));
  30.         if ( graphe->tla == NULL ) {
  31.           fprintf(stderr,"\nProblème lors de l'allocation mémoire du Tla du Graphe !!!\n" );
  32.           exit (1);
  33.         }
  34.         for ( i=1 ; i<=graphe->nb_noeuds ; i++ ) {
  35.           /* On initialise le tla du graphe */
  36.           graphe->tla[i] = CreerVide();       
  37.         }
  38.       }
  39.       else {
  40.         test_noeuds = strcmp ( tampon , "nbArretes" );
  41.         if ( test_noeuds == 0 ) {
  42.           /* On recupere le nombre d'arètes du graphe */
  43.           fscanf ( fichier, "%d", &(graphe->nb_aretes) );
  44.          
  45.           /* Mettons à jours la variable taille du dico */
  46.           graphe->g_dico.taille = graphe->nb_aretes;
  47.          
  48.           /* On va maintenant lancé la création du Dico */
  49.           Construire_Dico ( fichier , &(graphe->g_dico) );
  50.         }
  51.         else { /* Il ne s'agit ni du nb d'aretes, ni du nb de noeuds */
  52.           /* Il s'agit donc d'une ligne du type "noeuds noeuds poids" */
  53.          
  54.           /* Récupération du nom du 1er noeuds */
  55.           fscanf ( fichier, "%s", &noeud1 );
  56.           /* Récupération du nom du 1er noeuds */
  57.           fscanf ( fichier, "%s", &noeud2 );
  58.           /* Récupération du poids de l'arete */
  59.           fscanf ( fichier, "%d", &poids_arete );
  60.          
  61.           /* Il faut récuperer la correspondance des Mots - N° depuis le DICO :: */
  62.           dic_num_n1 = Recup_Num( noeud1 , &(graphe->g_dico) );
  63.           if ( dic_num_n1 == -1 ) {
  64.             printf("\nLe nom du noeud n°1 ne figure pas dans le Dictionnaire !!\n Le programme va s'arreter !!\n" );
  65.             exit (1);
  66.           }
  67.           dic_num_n2 = Recup_Num( noeud2 , &(graphe->g_dico) );
  68.           if ( dic_num_n2 == -1 ) {
  69.             printf("\nLe nom du noeud n°1 ne figure pas dans le Dictionnaire !!\n Le programme va s'arreter !!\n" );
  70.             exit (1);
  71.           }
  72.           /* On met l'arete dans le graphe */
  73.           graphe->tla[dic_num_n1] = Ajoute_GRAPHE ( graphe->tla[dic_num_n1] , dic_num_n2 , poids_arete );
  74.         }
  75.       }
  76.     }
  77.     else { /* sinon, c'est un commentaire et donc on ZAP !! */
  78.       /* Faut lire la ligne entière pour passé à la suivante ! */
  79.       /* Mais on fait comment */
  80.     }
  81.  
  82.  
  83.   }
  84.   /* On a atteint la fin du fichier ! */
  85.   fclose ( fichier );
  86. }

 
 
Voilà, donc je sais faire pour lire une chaine de caractère : fscanf ( fichier, "%s", tampon);
mais celà ne lit qu'une chaine de caractère jusqu'à l'espace ou le retour à la ligne qui la suit !
 
Ce que je voudrais, c'est savoir comment lire une ligne entière !!
En fait quand je lit la 1ere chaine de caract. et que celle là est en fait commence par #, alors c'est un commentaire ; donc je voudrais passer à la ligne suivante !
Comment fait-on ?
 
Merci @+
Miles

Reply

Marsh Posté le 26-04-2003 à 15:42:28   

Reply

Marsh Posté le 26-04-2003 à 15:52:42    

utilise fgets

Code :
  1. while(fgets(tampon, 256, fichier) != NULL)
  2. {
  3. // traiter la ligne
  4. }


 
pour passer les lignes de commantaire il suffite de tester tampon[0] == '#'
 
ca ne marche que si le # est les premier caractère de la ligne. Ca ne marche pas si il y a des espaces avant par exemple.
 

Reply

Marsh Posté le 26-04-2003 à 17:41:56    

et également mauvaise utilisation de feof, ...., fais une recherche sur le forum si tu veux en savoir plus

Reply

Marsh Posté le 26-04-2003 à 19:49:05    

Heu, pour le feof, je vois pas le pb !!
J'ai bien cherché ds le forum, mais ce que j'ai vu semble pareil à ce que j'ai mis !
 
De plus, j'ai mis ceci :
 

Code :
  1. fgets ( tampon, sizeof(tampon) , fichier );

 
Cette ligne de code est traitée si tampon est = au char #
Mon algo tourne de la façon suivante :
je prend la 1ere chaine de caractère du fichier (elle s'arrete au 1er espace rencontré)
je teste si cette chaine commence par un #
  si oui, alors, je lit le reste de la ligne avec le fgets, et je repars au début
  si non  
    je teste si elle est égale à "nb_noeuds"
      si oui, je lit ensuite un entier
      si non
        je teste si elle est égale à "nb_arete"
           si oui je lit ensuite un entier
           si non je lit une chaine de caractère, puis une autre puis un entier
 
Voilà, maintenant ca à l'air de fonctionner !
Je vais faire un debug pas à pas (ce qui n'est pas franchement pratique sous win avec dev-c++)
 
 
merci @+
Miles

Reply

Marsh Posté le 26-04-2003 à 19:50:27    

http://forum.hardware.fr/forum2.ph [...] subcat=386


Message édité par Taz le 26-04-2003 à 19:50:41
Reply

Marsh Posté le 26-04-2003 à 20:56:15    

Merci pour le lien, je viens de le lire, mais ca ne m'éclaire pas des masses !!
Un coup de pousse svp ?
Merci @+
Miles

Reply

Marsh Posté le 26-04-2003 à 22:44:42    

J'ai ca comme code qui marche bien :
 

Code :
  1. /* cette structure contient
  2.    les infos pour une ligne.
  3.    name = nom du champ
  4.    data = recoti la valeur apres lecture.
  5. */
  6. struct CFGField
  7. {
  8.     char* name ;
  9.     char* data ;
  10. };
  11. /* Lecture du fichier config :
  12.    - filename = nom du fichier config à lire
  13.    - CFGInfo = tableau de CFGField decrivant le fichier
  14. */
  15. int read_cfg_file( const char* filename, struct CFGField* CFGInfo )
  16. {
  17.     char  buffer[BUFFERSIZE];
  18.     char* WorkPtr ;
  19.     char* CfgName ;
  20.     char* CfgData ;
  21.     struct CFGField* Cfg ;
  22.     FILE* CfgFile ;
  23.     CfgFile = fopen( filename, "r" );
  24.     /* Tentons d'ouvrir le ficheir de config */
  25.     if( NULL == CfgFile )
  26.     {
  27.         return RETURN_ERR_FOPEN;
  28.     }
  29.     /* Lisons le fichier ligne par ligne */
  30.     while( NULL != fgets( buffer, BUFFERSIZE, CfgFile ))
  31.     {
  32.         /* Si l'on trouve un #, on a un commentaire */
  33.         if( NULL != (WorkPtr = strchr( buffer, '#' )))
  34.         {
  35.           /* On stoppe tout ! */
  36.           *WorkPtr = '\0';
  37.         }
  38.         else
  39.         { 
  40.           /* Sinon on avance */
  41.           WorkPtr = buffer + strlen( buffer );
  42.         }
  43.         WorkPtr--;
  44.         /* Eliminons les espaces superflus de la fin
  45.            de la ligne */
  46.         while( isspace( *WorkPtr ) && WorkPtr >= buffer )
  47.         { *WorkPtr-- = '\0'; }
  48.        
  49.         WorkPtr = buffer;
  50.         while( isspace( *WorkPtr )) WorkPtr++;
  51.        
  52.        /* Si la longeur de la chaine est nulle
  53.           on passe à la ligne suiavnte */
  54.        if( 0 == strlen( WorkPtr )) continue;
  55.         /* Bon cherchons le = qui delimite
  56.            le debut de la valeur du champ */
  57.         CfgName = strtok( WorkPtr, " =" );
  58.         if( NULL != CfgName )
  59.         {
  60.             strlwr( CfgName );
  61.             /* Récupérons la chaine qui se
  62.                trouve APRES le = */
  63.             CfgData = strtok( NULL, "" );
  64.            
  65.             /* Eliminons les espaces superflues */
  66.             while( isspace( *CfgData )) CfgData++;
  67.             if( '=' == *CfgData ) CfgData++;
  68.             while( isspace( *CfgData )) CfgData++;
  69.             /* Cherchons la ligne du tableau
  70.                correspondant au nom de variable
  71.                trouvée
  72.             */
  73.             Cfg = CFGInfo;
  74.             while( NULL != Cfg->name && 0 != strcmp( Cfg->name, CfgName )) Cfg++;
  75.             /* Si notre tableau de description
  76.                n'st pas fini, on copie les données */   
  77.             if( NULL != Cfg->name )
  78.             {
  79.                 Cfg->data = (char*)strdup( CfgData );
  80.                                      
  81.                 if( NULL == Cfg->data )
  82.                 {
  83.                     /* Oops pas assez de memoire */
  84.                     fclose( CfgFile );
  85.                     return RETURN_ERR_MEMORY;
  86.                 }
  87.             }
  88.            
  89.         }   
  90.     }
  91.    
  92.     /* On ferme le fichier et on sort */
  93.     fclose(CfgFile);
  94.     return RETURN_OK;
  95. }


 
Ca lit des fichiers du style
 

Code :
  1. #
  2. # Commentaires
  3. #
  4. variable=10
  5. variable2 = toto.txt
  6. test_du_truc =      1.0f


 
les nom des champs doivent etre en minuscule c'est la seule contrainte.
 
Bon je sais que c pas EXACTEMENT le format mais bon ca peut servir de base.
 
Pour s'en servir :
 

Code :
  1. struct CFGField data[] =
  2. {
  3. {"variable",NULL},
  4. {"variable2",NULL},
  5. {"test_du_truc",NULL},
  6. {NULL,NULL}, /* TRES IMPORTANT */
  7. };
  8. read_cfg( "test.ini", data );
  9. printf("variable = %s\n", data[0].data);


 
Voila avec les commentaires c mieux :P


Message édité par Joel F le 27-04-2003 à 08:58:34
Reply

Marsh Posté le 26-04-2003 à 23:19:02    

Eh Bhé !!!!!!
J'ai rien compris de ton bout de code !!!
Je sais pas comment tu fait pour t'y retrouver, mais pour moi ce n'est que du charabiat !!!
Les noms de variables ne m'inspirent rien du tout !
 
Peut-etre que ca te ferait le même effet si je te montrais mes prog en C, mais là franchement ...  :??:  :??:  :??:  :??:  :??:  
 
Peut-etre qu'avec qq explications ...
 
Mais, bon, je te remerecie quand même !
 
@+
Miles

Reply

Marsh Posté le 27-04-2003 à 08:48:54    

Oops désolé  :pt1cable:  
Je commente tt de suite   :ange:

Reply

Marsh Posté le 27-04-2003 à 13:40:11    

Merci pour tes commentaires,  
ca m'éclaire bien mieux !!
 
Mais, bon c'est un peu compliqué pour moi !
Surtout qu'on a pas vu toutes ces fcts en cours ! ( c'est un projet que je doit faire ! Dijkstra sur un réseau de la stas )
J'ai presque fini de refaire ma fonction, je la poste des que j'ai fini !!!
 
@+
Miles

Reply

Marsh Posté le 27-04-2003 à 13:40:11   

Reply

Marsh Posté le 27-04-2003 à 13:53:13    

Voilà, je pense avoir fini !!
J'ai compiler (sans erreurs), mais pas testé !
 
Voilà le code de ma fonction :

Code :
  1. void LireGRAPHE ( char * fic_name , GRAPHE *graphe ) {
  2.   FILE * fichier;
  3.   char ligne[1024];
  4.   char tampon[256];
  5.   char noeud1[256];
  6.   char noeud2[256];
  7.   int test_commentaire;
  8.   int test_noeuds;
  9.   int valeur_recuperee, i;
  10.   int poids_arete;
  11.   int dic_num_n1; /* Le N° retourné par le Dico pour le noeud 1 */
  12.   int dic_num_n2; /* Le N° retourné par le Dico pour le noeud 2 */
  13.  
  14.  
  15.   fichier = fopen( fic_name , "r" );
  16.   if (fichier==NULL) {
  17.     printf("\nProblème lors de l'acces en lecture du fichier !!\nVous n'avez pas les permissions requises, ou le fichier n'existe pas !!\n" );
  18.     exit (1);
  19.   }
  20.   while( fgets(ligne,1024*sizeof(char),fichier) != NULL) {
  21.     /* histoire de pas lire 2 fois le meme caractere ;) */
  22.  
  23.     if (ligne[0] != '#') {
  24.       /* Ce n'est pas une ligne de commentaire !! */
  25.       /* On va traiter la ligne lue */
  26.       sscanf( ligne , "%s " , tampon );
  27.       if ( strcmp(tampon,"nb_noeud" ) == 0) {
  28.         /* traitenement si nb_noeud */
  29.         sscanf( ligne+strlen(tampon)+1 , "%d" , &(graphe->nb_noeuds) );
  30.         graphe->tla = (TLA) malloc ( (graphe->nb_noeuds+1) * sizeof ( Liste ));
  31.         if ( graphe->tla == NULL ) {
  32.           fprintf(stderr,"\nProblème lors de l'allocation mémoire du Tla du Graphe !!!\n" );
  33.           exit (1);
  34.         }
  35.         for ( i=1 ; i<=graphe->nb_noeuds ; i++ ) {
  36.           /* On initialise le tla du graphe */
  37.           graphe->tla[i] = CreerVide();       
  38.         }
  39.       }
  40.       else {
  41.         if ( strcmp(ligne,"nb_arete" ) == 0) {
  42.           /* traitenement si nb_arete */
  43.           sscanf( ligne+strlen(tampon)+1 , "%d" , &(graphe->nb_aretes) );
  44.          
  45.           /* Mettons à jours la variable taille du dico */
  46.           graphe->g_dico.taille = graphe->nb_noeuds;
  47.          
  48.           /* On va maintenant lancé la création du Dico */
  49.           Construire_Dico ( fichier , &(graphe->g_dico) );
  50.          
  51.         }
  52.         else {
  53.           /* traitenement sinon */
  54.           /* cad que l'on doit lire 2 chaines de caract l'une */
  55.           /* à la suite de l'autre, et apres un entier */
  56.           sscanf( ligne , "%s %s %d" , noeud1 , noeud2 , &poids_arete );
  57.          
  58.           /* Il faut récuperer la correspondance des Mots - N° depuis le DICO :: */
  59.           dic_num_n1 = Recup_Num( noeud1 , &(graphe->g_dico) );
  60.           if ( dic_num_n1 == -1 ) {
  61.             printf("\nLe nom du noeud n°1 ne figure pas dans le Dictionnaire !!\n Le programme va s'arreter !!\n" );
  62.             exit (1);
  63.           }
  64.           dic_num_n2 = Recup_Num( noeud2 , &(graphe->g_dico) );
  65.           if ( dic_num_n2 == -1 ) {
  66.             printf("\nLe nom du noeud n°1 ne figure pas dans le Dictionnaire !!\n Le programme va s'arreter !!\n" );
  67.             exit (1);
  68.           }
  69.           /* On met l'arete dans le graphe */
  70.           graphe->tla[dic_num_n1] = Ajoute_GRAPHE ( graphe->tla[dic_num_n1] , dic_num_n2 , poids_arete );
  71.          
  72.         }
  73.       }
  74.     }
  75.     /* sinon c'est une ligne de commentaire !! */
  76.     /* et repart au début, lire une autre ligne */
  77.   }
  78.   /* On a atteint la fin du fichier ! */
  79.   fclose ( fichier );
  80. }


 
UNe explication des diverses fonctions non explicitées que j'appelle :
- Construire_Dico : va me contruire un dictionnaire avec mes nom de noeuds associés à un N°
- Ajoute_GRAPHE : va ajouter une arete au graphe tq A = ( S1 , S2, Pds )
 
voilà les différentes structures utilisées :

Code :
  1. struct dico {
  2.   char ** tab; /* Un tableau de ptr sur des char * */
  3.   int taille;  /* taille du tableau */
  4.   int nb_mots; /* nombre de mots dans le dico */
  5. };
  6. typedef struct dico DICO;
  7. struct elementliste {
  8.   int valeur; /* Evident !! */
  9.   int poids; /* Poids sur l'arète */
  10.   struct elementliste *suivant; /* Pointeur sur un elementliste */
  11.                                 /* désignant l'elt suivant      */
  12. };
  13. typedef struct elementliste ElementListe, *Liste;
  14. typedef Liste *TLA;
  15. /* La structure pour le Graphe */
  16. struct s_graphe {
  17.   TLA tla; /* le tla */
  18.   int nb_noeuds;  /* le nb de noeuds du graphe    */
  19.                   /* aussi appelés sommets        */
  20.   int nb_aretes;  /* le nb d'aretes du graphe     */
  21.   DICO g_dico;    /* le dico necessaire au graphe */
  22. };
  23. typedef struct s_graphe GRAPHE;
  24. struct elementtas {
  25.   int poids_noeud;
  26.   ElementListe * elt_tas;
  27. };
  28. typedef struct elementtas ElementTAS;
  29. struct s_tas {
  30.   ElementTAS** tab; /* Un tableau de pointeurs sur des ElementListe */
  31.   int nb_elt;         /* nb d'elt à prendre en compte dans le tas */
  32.   int taille;         /* nb total d'elt du tas (le max) */
  33. };
  34. typedef struct s_tas TAS;

 
Bon c'est peut-être pas dans le bon ordre pour que ca fonctionne, mais du pts de vue de mes includes, c'est OK ! J'ai juste mis en vrac !!
 
Voilà, merci de votre aide,
 
AU fait, est-ce correct ?
 
 
[edit]
au fait, voilà le code de la fonction qui me cree le dico :

Code :
  1. void Construire_Dico ( FILE * fichier , DICO * Le_Dico ) {
  2.   char tampon[256];
  3.   int fini=0;
  4.   int test_fin;
  5.   int i; /* servira d'indexeur pour l'elt à ajouter dans le tableau du dico */
  6.   Le_Dico->nb_mots = 0;
  7.   /* ON alloue l'espace mémoire necessaire au dico */
  8.   Le_Dico->tab = (char **) malloc ((Le_Dico->taille+1) * sizeof (char *));
  9.   if ( Le_Dico->tab == NULL ) {
  10.     fprintf (stderr,"Erreur lors de l'allocation mémoire pour le tableau du dico !! " );
  11.     exit (1);
  12.   }
  13.   i = 1; /* on commence l'indexation à 1 */
  14.  
  15.   /* on arrete de lire les aretes qd on atteindra la ligne "###l.ligne.01.txt.arete" */
  16.   /* Qd on atteindra cette ligne, fini passera à 1 !! */
  17.   while ( fini==0 ) {
  18.     test_fin = strncmp ( tampon , "###" , 3 );
  19.     if ( test_fin == 0 ) { /* C'est la fin de la lecture du dico */
  20.       fini = 1;
  21.     }
  22.     else {
  23.       fscanf ( fichier , "%s" , &tampon );
  24.       Le_Dico->tab[i] = (char *) strdup (tampon);
  25.       i++; /* pour passer à l'elt suivant */
  26.       Le_Dico->nb_mots++;
  27.     }
  28.  
  29.   }
  30. }

 
Est-ce que avec la méthode de lecture du fichier faite dans LireGRAPHE, celle de Construire_DICO va marcher ?
[/edit]
 
@+
Miles


Message édité par Miles--Teg le 27-04-2003 à 14:00:05
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed