Partage
  • Partager sur Facebook
  • Partager sur Twitter

Lire ligne par ligne un fichier

Sujet résolu
    4 août 2021 à 19:44:09

    Bonsoir à tous !

    Alors voilà je suis au deuxième TP sur le cours de Langage C où je dois notamment faire un pendu.

    Après plusieurs tentatives, j'ai enfin réussi à lire ligne par la ligne mon fichier, enfin presque parce que là par exemple , si je pioche le mot 17, mon code prend le mot 18 :/

    Voici ma fonction qui doit aller chercher le mot secret dans le fichier ( pendu.txt ) :

    int choisirMot(int position,char motChoisi[])
    {
        FILE *pendu = NULL;
        int i=0;
    
        pendu=fopen("pendu.txt","r+");
        rewind(pendu);
    
        if (pendu==NULL)
        {
            printf ("Une erreur s'est produite ! \n");
            return 0;
        }    
    
        for (i=0;i<position;i++) // Boucle qui permet de se placer sur le bon mot 
        {
            while (fgetc(pendu)!='\n'); // Pour chaque itération on lit tous les caractères de la ligne et on passe à la suivante
        }
        fgets(motChoisi,TAILLE_MAX,pendu);
    }

    Mais j'ai réussi à régler le problème en mettant dans la condition du for " i < (position - 1) "

    Mais je comprend pas pourquoi ça a marché car si j'ai besoin par exemple du mot 15, ma boucle doit normalement lire toutes les lignes ( caractères plutôt ) jusqu'à la ligne 14 et ainsi je pourrais avec le fgets prendre le mot 15 ?

    Donc si une âme charitable pouvait m'éclairer ^^

    -
    Edité par Rol45 4 août 2021 à 19:47:51

    • Partager sur Facebook
    • Partager sur Twitter
      4 août 2021 à 20:43:36

      Hello,

      Tou dépend de ce que position indique pour le 1er mot : vaut-il 0 (zéro) ou 1 ? Si le premier mot est indiqué par 0, alors ton code est correct. Sinon, si le premier mot est indiqué par 1, alors tu dois effectivement limiter la boucle for à position-1.

      -
      Edité par edgarjacobs 4 août 2021 à 20:44:14

      • Partager sur Facebook
      • Partager sur Twitter

      On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

        4 août 2021 à 21:04:56

        edgarjacobs a écrit:

        Hello,

        Tou dépend de ce que position indique pour le 1er mot : vaut-il 0 (zéro) ou 1 ? Si le premier mot est indiqué par 0, alors ton code est correct. Sinon, si le premier mot est indiqué par 1, alors tu dois effectivement limiter la boucle for à position-1.

        -
        Edité par edgarjacobs il y a 18 minutes


        Yo merci de ta réponse ! 

        En effet le premier mot est indiqué par 0 ( j'ai rajouté une condition dans mon code pour que quand c'est 0 il fasse le fgets directement sinon le mot ne s'affichait pas correctement si c'est 0 )

        Mais je ne comprend toujours pas en quoi si c'est 0 on doit mettre position - 1 

        -
        Edité par Rol45 4 août 2021 à 21:06:02

        • Partager sur Facebook
        • Partager sur Twitter
          4 août 2021 à 23:51:37

          Il faut mettre position-1 si 1 pour position indique le 1er mot, pas sdans le cas où 0 indique le premier mot.

          Un simple exemple:

          #include <stdio.h>
          #include <stdlib.h>
          
          #define SIZE	64
          
          void GetWord(int pos,char word[])
          {
              FILE *st=fopen("pendu.txt","r");
              if(st==NULL) {
                  perror("pendu.txt");
          		exit(1);
              }   
           
              for(int i=0;i<pos;i++)
                  while(fgetc(st)!='\n');
              
          	fgets(word,SIZE,st);
          	fclose(st);
          }
          
          int main(void) {
          	char str[SIZE];
          	
          	GetWord(0,str);
          	printf("0: %s\n",str);
          	GetWord(1,str);
          	printf("1: %s\n",str);
          	
          	return(0);
          }
          	

          Avec pendu.txt qui contient

          abc
          def
          ghi
          

          on obtient en sortie

          1: abc
          
          2: def
                    
          


          Attention que fgets() conserve le \n final (si il existe dans le fichier). Il faut donc l'éliminer. Une solution est de faire

          #include <string.h>
          
          char *ptr=strchr(word,'\n');
          if(ptr!=NULL)
              *ptr=0;
          
          

          -
          Edité par edgarjacobs 5 août 2021 à 0:16:43

          • Partager sur Facebook
          • Partager sur Twitter

          On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

            5 août 2021 à 15:48:34

            edgarjacobs a écrit:

            Il faut mettre position-1 si 1 pour position indique le 1er mot, pas sdans le cas où 0 indique le premier mot.

            Un simple exemple:

            #include <stdio.h>
            #include <stdlib.h>
            
            #define SIZE	64
            
            void GetWord(int pos,char word[])
            {
                FILE *st=fopen("pendu.txt","r");
                if(st==NULL) {
                    perror("pendu.txt");
            		exit(1);
                }   
             
                for(int i=0;i<pos;i++)
                    while(fgetc(st)!='\n');
                
            	fgets(word,SIZE,st);
            	fclose(st);
            }
            
            int main(void) {
            	char str[SIZE];
            	
            	GetWord(0,str);
            	printf("0: %s\n",str);
            	GetWord(1,str);
            	printf("1: %s\n",str);
            	
            	return(0);
            }
            	

            Avec pendu.txt qui contient

            abc
            def
            ghi
            

            on obtient en sortie

            1: abc
            
            2: def
                      
            


            Attention que fgets() conserve le \n final (si il existe dans le fichier). Il faut donc l'éliminer. Une solution est de faire

            #include <string.h>
            
            char *ptr=strchr(word,'\n');
            if(ptr!=NULL)
                *ptr=0;
            
            

            -
            Edité par edgarjacobs il y a environ 15 heures

            Aha merci beaucoup de ton aide ! En effet dans vscode je voyais que le mot était sur la ligne 1 ce qui m'a induit en erreur ^^

            Merci aussi pour la fin en effet quand je testais un srtlen sur le mot ça me donnait un chiffre au dessus de la taille exacte du mot ( par exemple pour chat strlen me renvoyait 5 ) j'ai oublié le '\n' 

            Merci encore je passe en résolu 

            EDIT : [ Mais du coup pourquoi mettre 0 ? J'aurais pu mettre n'importe quel chiffre vu que c'est une chaine que je veux à la base ? ]

            Comment faire pour que la position du premier mot soit 1 et non 0 ?

            EDIT 2 : j'avais aussi une question qui me taraude depuis pas mal de temps : si je crée un tableau de char de taille 100, le '\0' symbolisant la fin de la chaine se trouve t'il à la 100ème position ? Si je met dans ce tableau le mot " chat " , le '\0' se place t'il alors en 5ème position ou bien reste t'il toujours à la 100 ème position  ( si c'est le cas ) ?

            EDIT 3 : Dans mon code, à quel moment fgets prend le '\n' ? Car en supposant que la position du 1er mot est la position 1, si le mot que je veux est le 4ème mot, fgetc prendra le '\n' de la fin de la ligne du troisième mot ( d'après la condition ( while(fgetc(fichier)!='\n' )

            Du coup fgets prend le \n de la ligne 4 ? 

            -
            Edité par Rol45 5 août 2021 à 17:06:35

            • Partager sur Facebook
            • Partager sur Twitter
              5 août 2021 à 16:31:26

              Pipa a écrit:

              si je crée un tableau de char de taille 100, le '\0' symbolisant la fin de la chaine se trouve t'il à la 100ème position ?

              Qu'est-ce que tu entends par « 100ème position » ? Il faut être précis (et alors tout devient plus compréhensible). Avec les tableaux, je te suggère de parler d'indice. Mais je crois que tu parles de l'indice 99. Donc tu demandes si, lorsqu'on déclare un tableau char[100], un '\0' est mis automatiquement à l'indice 99. Réponse : non. Si on initialise la chaîne de caractère, un '\0' est mis juste après les caractères de la chaîne, donc en indice 4 pour "chat". Si on ne fait pas d'initialisation, on a juste réservé 100 cases mémoire pour y mettre des caractères, mais pour l'instant elles contiennent n'importe quoi.

              (C'est vrai que ce serait judicieux que le système ajoute un octet avec le caractère nul, ainsi on n'aurait jamais de dépassement. Mais je crois qu'en C, un octet est un octet, on ne va pas en gaspiller...)

              -
              Edité par robun 5 août 2021 à 16:42:37

              • Partager sur Facebook
              • Partager sur Twitter
                5 août 2021 à 16:57:21

                robun a écrit:

                Pipa a écrit:

                si je crée un tableau de char de taille 100, le '\0' symbolisant la fin de la chaine se trouve t'il à la 100ème position ?

                Qu'est-ce que tu entends par « 100ème position » ? Il faut être précis (et alors tout devient plus compréhensible). Avec les tableaux, je te suggère de parler d'indice. Mais je crois que tu parles de l'indice 99. Donc tu demandes si, lorsqu'on déclare un tableau char[100], un '\0' est mis automatiquement à l'indice 99. Réponse : non. Si on initialise la chaîne de caractère, un '\0' est mis juste après les caractères de la chaîne, donc en indice 4 pour "chat". Si on ne fait pas d'initialisation, on a juste réservé 100 cases mémoire pour y mettre des caractères, mais pour l'instant elles contiennent n'importe quoi.

                (C'est vrai que ce serait judicieux que le système ajoute un octet avec le caractère nul, ainsi on n'aurait jamais de dépassement. Mais je crois qu'en C, un octet est un octet, on ne va pas en gaspiller...)

                -
                Edité par robun il y a 12 minutes

                Merci de ta réponse ! ^^

                Ah oui je parlais bien de l'indice 99 c'est vrai que ça peut porter à confusion ^^

                Mais si sans initialisation un tableau de 100 char contient " n'importe quoi " , si j'y met le mot chat , c'est donc tout ce qui était dans la chaine qui est effacé puis le char est "inclus" d'où le '\0' qui vient se mettre après  ? Parce que si j'écrase seulement les cases nécessaires à la saisie du mot " chat " , le reste contenant n'importe quoi , comment le '\0' peut 'il venir après " chat " ? que contiennent les autres cases alors ?

                -
                Edité par Rol45 5 août 2021 à 17:01:31

                • Partager sur Facebook
                • Partager sur Twitter
                  5 août 2021 à 17:55:59

                  Re,-

                  fgets(var,size,file) lit file et remplit var jusqu'à ce que soit un \n soit rencontré (qui est aussi mis dans var), soit que size-1 caractères ait été lus (voir ici)

                  Donc le code pourrait être

                  void GetWord2(int pos,char word[])
                  {
                      FILE *st=fopen("pendu.txt","r");
                      if(st==NULL) {
                          perror("pendu.txt");
                  		exit(1);
                      }
                  
                      for(int i=0;i<=pos;i++)			// attention: la condition est changée
                          fgets(word,SIZE,st);
                  
                  	fclose(st);
                  	
                  	char *ptr=strchr(word,'\n');
                  	if(ptr!=NULL)
                  		*ptr=0;
                  }
                  
                  

                  ceci en supposant que le 1er mot est indiqué par pos=0. Si le premier mot est indiqué par pos=1, alors la condition du for devient i<pos

                  _______________________________________________________


                  En fait, en mémoire, "chat" est écrit 'c' 'h' 'a' 't' '\0'. Si tu fais un strcpy(var,"chat"), strcpy() copie tous les caractères à partir du 'c' de "chat" jusque et y compris  le '\0' qui suit le 't' de "chat". Et si var au départ contenait n'importe quoi, hé bien les indices 5 à 99 (dans le cas de char var[100]) contiennent toujours n'importe quoi.

                  -
                  Edité par edgarjacobs 5 août 2021 à 18:22:08

                  • Partager sur Facebook
                  • Partager sur Twitter

                  On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                    5 août 2021 à 19:29:50

                    edgarjacobs a écrit:

                    Re,-

                    fgets(var,size,file) lit file et remplit var jusqu'à ce que soit un \n soit rencontré (qui est aussi mis dans var), soit que size-1 caractères ait été lus (voir ici)

                    Donc le code pourrait être

                    void GetWord2(int pos,char word[])
                    {
                        FILE *st=fopen("pendu.txt","r");
                        if(st==NULL) {
                            perror("pendu.txt");
                    		exit(1);
                        }
                    
                        for(int i=0;i<=pos;i++)			// attention: la condition est changée
                            fgets(word,SIZE,st);
                    
                    	fclose(st);
                    	
                    	char *ptr=strchr(word,'\n');
                    	if(ptr!=NULL)
                    		*ptr=0;
                    }
                    
                    

                    ceci en supposant que le 1er mot est indiqué par pos=0. Si le premier mot est indiqué par pos=1, alors la condition du for devient i<pos

                    _______________________________________________________


                    En fait, en mémoire, "chat" est écrit 'c' 'h' 'a' 't' '\0'. Si tu fais un strcpy(var,"chat"), strcpy() copie tous les caractères à partir du 'c' de "chat" jusque et y compris  le '\0' qui suit le 't' de "chat". Et si var au départ contenait n'importe quoi, hé bien les indices 5 à 99 (dans le cas de char var[100]) contiennent toujours n'importe quoi.

                    -
                    Edité par edgarjacobs il y a 18 minutes

                    Merci beaucoup je comprend beaucoup mieux maintenant ! Je trouve mieux d'utiliser fgets directement ^^

                    Bon dernier problème ( ^^ ) , j'ai une fonction qui prend en paramètre le mot choisi, le caractère que le joueur a entré ainsi que la chaine du mot choisi qui est cachée pour le coup ( dans cette chaine, on a des '*' )

                    Mais on dirait que ça marche que lors de la première itération dans mon main ( j'ai utilisé un do - while pour la boucle de lecture/verification des caractères ) . Cette fonction me renvoie 1 si tout s'est bien passé ( le caractère est bien dans le mot choisi et il l'a remplacé  dans la chaine caché ) et 0 si le caractère n'y est pas .

                    Problème : Si le mot est par exemple chat , la fonction me renvoie 1 que pour le ' C ' et pour toutes les autres lettres elle me renvoie 0 

                    Voici la fonction :

                    int verif_Replace(char motChoisi[],char caractereSaisi,char motChoisiCache[])
                    {
                        int i=0;
                    
                        if ((strchr(motChoisi,caractereSaisi)!=NULL))
                        {
                            for (i=0;i<strlen(motChoisi);i++)
                            {
                                if (motChoisi[i]==caractereSaisi)
                                {
                                    motChoisiCache[i]=caractereSaisi;
                                }
                            }
                            
                            return 1;
                        }
                        
                        return 0;
                    }




                    -
                    Edité par Rol45 5 août 2021 à 19:33:41

                    • Partager sur Facebook
                    • Partager sur Twitter
                      5 août 2021 à 19:41:58

                      Ta fonction me semble correcte. Montre ton programme, le problème vient sans doute d'ailleurs.
                      • Partager sur Facebook
                      • Partager sur Twitter

                      On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                        5 août 2021 à 20:15:26

                        edgarjacobs a écrit:

                        Ta fonction me semble correcte. Montre ton programme, le problème vient sans doute d'ailleurs.


                        Voici le programme au complet :

                        #include <stdio.h>
                        #include <stdlib.h>
                        #include <string.h> 
                        #include <ctype.h>
                        #include <time.h>
                        #include "pendu.h"
                        #define TAILLE_MAX 50
                        
                        int main()
                        {
                            char caractereSaisi = 0;
                            int positionAleatoire=0,tentativesRestantes=10,nombreDemots = 0,reponse=0,valeurDeRetour=0;
                            const int min=1;
                            char motChoisi[TAILLE_MAX]="",motChoisi_Cache[TAILLE_MAX]="";
                        
                            do
                            {
                                tentativesRestantes=10;
                                nombreDemots=nombreMots();
                                if (nombreDemots==0)
                                {
                                    printf ("Une erreur s'est produite ! \n");
                                    return 0;
                                }
                        
                                srand(time(NULL));
                                positionAleatoire=(rand() % (nombreDemots - min + 1)) + min;
                        
                                if (choisirMot(positionAleatoire,motChoisi)==0)
                                {
                                    printf ("Une erreur s'est produite !\n");
                                    return 0;
                                }
                        
                                miseAetoile(motChoisi_Cache,motChoisi);
                        
                                printf ("\nBienvenue au jeu du Pendu !\n");
                                do
                                {
                                    printf ("\nIl vous reste %d coups a jouer !\n",tentativesRestantes);
                                    printf ("Quel est le mot mystere ? %s\n",motChoisi_Cache);
                                    printf ("Proposez une lettre : ");
                                    caractereSaisi = lireCaractere();
                                    valeurDeRetour = verif_Replace(motChoisi,caractereSaisi,motChoisi_Cache);
                        
                                    
                                    if (valeurDeRetour==0)
                                    {
                                        tentativesRestantes--;
                                    }
                        
                                } while (tentativesRestantes!=0 && (strcmp(motChoisi,motChoisi_Cache))!=0);
                                
                                if (tentativesRestantes==0)
                                {
                                    printf ("\nPlus de tentatives restantes ! C'est perdu ^^\n");
                                    printf ("Voulez vous reessayer ? \n[ TAPEZ 1 POUR REESSAYER ET 0 POUR ARRETER ] : ");
                                    scanf ("%d",&reponse);
                                }
                                else 
                                {
                                    printf ("Bravo ! %s etait bien le mot mystere ^^",motChoisi_Cache);
                                    printf ("Voulez vous faire une nouvelle partie ? \n[ TAPEZ 1 POUR REESSAYER ET 0 POUR ARRETER ] : ");
                                    scanf ("%d",&reponse);            
                                }
                            } while (reponse==1);
                        
                            return 0;
                        }
                        
                        char lireCaractere()
                        {
                            char c = 0;
                        
                            c = getchar();
                            c = toupper(c); // Mettre le caractère en majuscule 
                        
                            while(getchar() != '\n'); // Le ';' est là pour remplacer les {}
                            
                            return c;
                        }
                        
                        void miseAetoile(char motCache[],char motChoisi[])
                        {
                            int i=0;
                        
                            strcpy(motCache,motChoisi);
                        
                            for (i=0;i<(strlen(motCache));i++)
                            {
                                motCache[i]='*';
                            }
                        }
                        int nombreMots()
                        {
                            FILE *pendu = NULL;
                            char temp[TAILLE_MAX]="";
                            int cpt=0;
                        
                            pendu=fopen("pendu.txt","r");
                        
                            rewind(pendu);
                            if (pendu==NULL)
                            {
                                printf ("Une erreur s'est produite ! \n");
                                return 0;
                            }
                        
                            while (fgets(temp,TAILLE_MAX,pendu)!=NULL)
                            {
                                cpt++;
                            } 
                            
                            fclose(pendu);
                        
                            return cpt;
                        }
                        
                        int choisirMot(int position,char motChoisi[])
                        {
                            FILE *pendu = NULL;
                            int i=0;
                            char *clean=NULL;
                        
                            pendu=fopen("pendu.txt","r+");
                            if (pendu!=NULL)
                            {
                                rewind(pendu);
                        
                                    for (i=0;i<position;i++) // Boucle qui permet de se placer sur le bon mot 
                                    {
                                        fgets(motChoisi,TAILLE_MAX,pendu); 
                                    }
                                
                                fclose(pendu);
                        
                                clean = strchr(motChoisi,'\n'); 
                                if (clean != NULL)
                                {
                                    *clean=0;
                                }
                        
                                return 1;
                            }
                            else 
                            {
                                return 0;
                            }
                        }
                        
                        int verif_Replace(char motChoisi[],char caractereSaisi,char motChoisiCache[])
                        {
                            int i=0;
                        
                            if ((strchr(motChoisi,caractereSaisi)!=NULL))
                            {
                                for (i=0;i<strlen(motChoisi);i++)
                                {
                                    if (motChoisi[i]==caractereSaisi)
                                    {
                                        motChoisiCache[i]=caractereSaisi;
                                    }
                                }
                                
                                return 1;
                            }
                            
                            return 0;
                        }



                        -
                        Edité par Rol45 5 août 2021 à 20:17:14

                        • Partager sur Facebook
                        • Partager sur Twitter
                          5 août 2021 à 22:52:55

                          Une piste: en C, 'A' et 'a' sont deux caractères différents :diable: 

                          Tu devrais pouvoir trouver d'où vient le problème....

                          -
                          Edité par edgarjacobs 5 août 2021 à 22:55:33

                          • Partager sur Facebook
                          • Partager sur Twitter

                          On écrit "j'ai tort", pas "tord" qui est le verbe "tordre" à la 3ème personne de l'indicatif présent

                            6 août 2021 à 0:21:49

                            edgarjacobs a écrit:

                            Une piste: en C, 'A' et 'a' sont deux caractères différents :diable: 

                            Tu devrais pouvoir trouver d'où vient le problème....

                            -
                            Edité par edgarjacobs il y a environ 1 heure

                            HAHA je viens de comprendre ( en vrai je connaissaient déjà le code ascii on l'a fait cette année en dut )

                            La fonction lireCaractere, je l'avait prise sur le cours de langage C j'avais remarqué que ça mettait les lettres en maj sans y prêter plus grande attention ^^

                            En tout cas merci infiniment pour le temps que t'as consacré à m'aider !!! ( Pour te remercier, je reviendrais bientôt sur un autre programme avec de nouveaux problèmes rencontrés...:ange: ) 

                             EDIT : ça fonctionne très bien maintenant merci encore

                            -
                            Edité par Rol45 6 août 2021 à 0:27:40

                            • Partager sur Facebook
                            • Partager sur Twitter
                              11 août 2021 à 4:08:01

                              Je reprend cette ligne:
                               for (i=0;i<position;i++)
                              Si la première ligne est désignée par 0, c'est correct.
                              Sinon, si la première ligne est désigné par 1, il faut faire:
                               for (i=1;i<position;i++)
                              • Partager sur Facebook
                              • Partager sur Twitter

                              Le Tout est souvent plus grand que la somme de ses parties.

                              Lire ligne par ligne un fichier

                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                              • Editeur
                              • Markdown