Partage
  • Partager sur Facebook
  • Partager sur Twitter

Anomalie dans la lecture d'un fichier .txt

Lettre manquante dans l'affichage de la console

Sujet résolu
    6 juin 2023 à 0:45:07

    Bonjour

    Je dispose d'un fichier .txt contenant le texte suivant : 

    23.4

    Bonjour, je suis une phrase ecrite dans un fichier.

    42.1337

    J'ai 36 ans.

    Je souhaiterais écrire un programme qui lit brièvement une partie de ce texte en changeant de mode de lecture en cours de route :

    -La première fois lire une ligne avec getline(), afficher "23.4" puis revenir à la ligne 

    -La deuxième fois lire un mot avec des >> et afficher "Bonjour," puis revenir à nouveau à la ligne

    -La dernière fois lire une lettre à l'aide d'un char et afficher "j"

    Ce qui devrait théoriquement donner :

    23.4

    Bonjour,

    j

    Le problème est que le programme que j'ai écris affiche tout cela sauf le "B" de "Bonjour" et que je ne vois pas l'erreur dans mon programme :

    23.4

    onjour,

    j

    Ou l'erreur dans mon programme se trouve-t-elle ?

    #include <iostream>
    #include <fstream>
    #include <string>
    
    using namespace std;
     
    int main()
    {
        //Ouverture d'un fichier en lecture
        ifstream monFlux("C:/Users/User/Documents/programme code blocks/programme en C++/modification_et_lecture_de_fichiers/scores.txt");
                                                                                                                                                                                                                               
     
        if(monFlux)//vérifie si le fichier est ouvert avec succès
        {
            string ligne;
            getline(monFlux, ligne);
            cout << ligne << endl;
     
     
            monFlux.ignore();        //On change de mode
     
            string mot;//la première lettre est manquante apparemment à partir de là
            monFlux >> mot;
            cout << mot << endl;
     
            monFlux.ignore();        //On change de mode
     
            char a;
            monFlux.get(a);
            cout << a;
        }
        else
        {
            cout << "ERREUR: Impossible d'ouvrir le fichier en lecture." << endl;
        }
        return 0;
    }


    Cordialement



    -
    Edité par 1Stark 6 juin 2023 à 23:52:43

    • Partager sur Facebook
    • Partager sur Twitter
      6 juin 2023 à 7:10:53

      Salut,

      Le mieux, quand on a des erreurs de compilation, c'est encore de lire (et surtout, d'essayer de comprendre) les erreurs transmises par le compilateur, puis d'essayer de les résoudre, en commencant par la toute première erreur relative à ton propre code (car les suivantes ne sont souvent que la conséquence de cette première erreur).

      Alors, bien sur, il est possible que ces erreurs soient fournies en anglais, cependant, il s'agit d'un anglais "assez simple" et, de plus, le compilateur te donnera un tas d'éléments permettant de la corriger.

      Dans le cas présent, les erreurs données par le compilateur commencent par

      <source>: In function 'int main()':
      <source>:8:5: error: 'ifstream' was not declared in this scope; did you mean 'std::ifstream'?
          8 |     ifstream monFlux("C:/Users/User/Documents/programme code blocks/programme en C++/modification_et_lecture_de_fichiers/scores.txt");
            |     ^~~~~~~~
            |     std::ifstream

      (chez toi, ce <source> serait sans doute remplacé par main.cpp>

      Autrement dit, le compilateur se plaint que, dans le fichier <source>, à la ligne 8, colonne 5, il a trouvé le terme "ifstream" qu'il ne connait pas, et il te demande si tu ne voulais pas dire "std::ifstream"

      Puis, il te montre la ligne 8 complete, en souslignant le terme incompris, et en te proposant quelque chose à mettre à la place de celui-ci.

      Et tu sais quoi? Il a tout à fait raison, car absolument toutes les fonctionnalités de la bibliothèque standard (dont fait partie la classe ifstream) se trouvent dans l'espace de noms (on pourrait comparer cela à une boite de rangement qu'il faut absolument ouvrir -- dont il faut donner le nom -- pour voir ce qu'il y a à l'intérieur) std.

      Il en va donc de même pour la classe string , pour le flux de sortie commun cout , pour la fonctions getline et le modificateur de flux endl (il faut utiliser respectivement std::string, std::cout, std::getline et std::endl)

      Il existe bien une alternative à de tels changements, qui est sans doute utilisée par le cours que tu utilise, mais je t'avouerai que je n'en suis pas fan du tout.

      Et puis, je ne vais quand meme pas tout faire à ta place ;)

      Au lieu de t'en parler, je vais donc te conseiller de relir attentivement le code sur lequel tu t'es basé pour essayer d'écrire le tien, en t'assurant que toutes les lignes importantes présentes dans ton exemple soient également présentes dans le tien.

      Je peux te garantir qu'il en manque au moins une.  Trouve la, ajoute la à ton code et viens me dire de laquelle il s'agit lorsque tu l'auras trouvée. je te dirai alors pourquoi je ne suis pas fan de cette solution ;)

      EDIT: D'ailleurs, tu utilisais effectivement cette ligne dans ton code dans ==>cette discussions <== où a-t-elle disparu ?

      -
      Edité par koala01 6 juin 2023 à 7:14:27

      • Partager sur Facebook
      • Partager sur Twitter
      Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
        6 juin 2023 à 10:09:53

        Il semblerait que ton code ai compilé, alors soit tu n'as pas restitué ton code correctement sur le forum ou alors tu utilise un très très vieux compilateur.

        (j'ai réussi à le compiler avec MinGW de l'année 2000)

        Pour ton problème c'est le monFlux.ignore() qui te mange le 'B'

        • Partager sur Facebook
        • Partager sur Twitter
        ...
          6 juin 2023 à 12:38:34

          rouIoude a écrit:

          Pour ton problème c'est le monFlux.ignore() qui te mange le 'B'


          Conformément à la documentation, qu'on ne lit jamais assez

          std::istream::ignore

          istream& ignore (streamsize n = 1, int delim = EOF);
          Extract and discard characters
          Extracts characters from the input sequence and discards them, until either <var>n</var> characters have been extracted, or one compares equal to <var>delim</var>.

          The function also stops extracting characters if the end-of-file is reached. If this is reached prematurely (before either extracting <var>n</var> characters or finding <var>delim</var>), the function sets the<samp>eofbit</samp>flag.
          donc
          • monFlux.ignore() sans paramètres extrait et balance 1 caractère, sauf si on est à la fin.
          pourquoi faire cet ignore() si tu ne veux pas perdre un caractère ? Getline a déjà mangé le caractère de fin de la ligne précédente

          std::getline (string)

          (1)
          istream& getline (istream&  is, string& str, char delim);
          istream& getline (istream&& is, string& str, char delim);
          (2)
          istream& getline (istream&  is, string& str);
          istream& getline (istream&& is, string& str);
          Get line from stream into string
          Extracts characters from is and stores them into str until the delimitation character delim is found (or the newline character, <tt>'\n'</tt>, for (2)).

          The extraction also stops if the end of file is reached in is or if some other error occurs during the input operation.

          If the delimiter is found, it is extracted and discarded (i.e. it is not stored and the next input operation will begin after it).

          -
          Edité par michelbillaud 6 juin 2023 à 12:44:02

          • Partager sur Facebook
          • Partager sur Twitter
            7 juin 2023 à 0:05:14

            Bonjour

            @rouIoude @koala01 Effectivement mon code compile, j'avais simplement oublié de copier la ligne "using namespace std;" dans le forum. Désormais le programme tout en haut est corrigé.

            Je ne comprend pas ce qu'il se passe, mais le message s'affiche en console comme voulu maintenant, alors que je n'ai rien modifié, et qu'il ne cessait pas de s'afficher sans le "B" à plusieurs reprises :

            Cordialement

            -
            Edité par 1Stark 7 juin 2023 à 2:09:37

            • Partager sur Facebook
            • Partager sur Twitter
              7 juin 2023 à 0:23:12

              Le code que tu as posté, n'affiche pas le 'B' ! Et tu bien sur que c'est celui la que tu exécutes ?

              • Partager sur Facebook
              • Partager sur Twitter
              ...
                7 juin 2023 à 1:40:53

                Bonsoir,

                C'est bien celui-ci mais il n'affiche étrangement plus le "B" à nouveau :

                Le voici à nouveau au cas ou :

                #include <iostream>
                #include <fstream>
                #include <string>
                
                using namespace std;
                
                int main()
                {
                    //Ouverture d'un fichier en lecture
                    ifstream monFlux("C:/Users/User/Documents/programme code blocks/programme en C++/modification_et_lecture_de_fichiers/scores.txt");
                
                    if(monFlux)//vérifie si le fichier est ouvert avec succès
                    {
                        string ligne;
                        getline(monFlux, ligne);
                        cout << ligne << endl;
                
                        monFlux.ignore();        //On change de mode
                
                        string mot;//la première lettre est manquante apparemment à partir de là
                        monFlux >> mot;
                        cout << mot << endl;
                
                        monFlux.ignore();        //On change de mode
                
                        char a;
                        monFlux.get(a);
                        cout << a;
                    }
                    else
                    {
                        cout << "ERREUR: Impossible d'ouvrir le fichier en lecture." << endl;
                    }
                    return 0;
                }

                @michelbillaud Y'aurait-il une instruction plus adaptée que getline() pour laisser apparaître le 'B' de "Bonjour" ? 

                Cordialement

                -
                Edité par 1Stark 7 juin 2023 à 2:08:15

                • Partager sur Facebook
                • Partager sur Twitter
                  7 juin 2023 à 8:30:35

                  >  instruction plus adaptée que getline ?

                  Non.

                  Vire ton ignore ligne 18,  qui ne sert pas à "changer de mode", mais à bouffer des caractères. Et il bouffe ton B, donc c'est clairement lui le coupable. C'est tout.

                  Ps: si tu veux découvrir de nouvelles fonctionnalités, lis la documentation.

                  Ps2 pour le genre de truc que tu fais, c'est plus sain

                  -
                  Edité par michelbillaud 7 juin 2023 à 8:55:07

                  • Partager sur Facebook
                  • Partager sur Twitter
                    7 juin 2023 à 10:25:15

                    rouIoude a écrit:

                    Pour ton problème c'est le monFlux.ignore() qui te mange le 'B'



                    • Partager sur Facebook
                    • Partager sur Twitter
                    ...
                      7 juin 2023 à 15:14:31

                      Ainsi que

                      • monFlux.ignore() sans paramètres extrait et balance 1 caractère, sauf si on est à la fin.

                      C'est ce qu'on se tue à lui dire.

                      PS

                      Un code source

                      #include <iostream>
                      #include <fstream>
                      #include <string>
                      #include <sstream>
                      
                      using namespace std;
                      
                      int main()
                      {
                          ifstream monFlux("texte.txt");
                      
                          if (monFlux) {
                              string ligne;
                      
                              getline(monFlux, ligne);
                              cout << "- lecture d'un double sur la ligne 1: " << ligne << endl;
                      
                              double d;
                              {
                                  istringstream str(ligne);
                                  str >> d;
                              }
                              cout << "=> le double = " << d << endl;
                      
                              getline(monFlux, ligne);
                              cout << "- lecture d'une ligne entière sur la ligne 2: " << ligne << endl;
                              cout << "=> la ligne = " << ligne << endl;
                      
                      
                              getline(monFlux, ligne);
                              cout << "- lecture d'un double sur la ligne 3: " << ligne << endl;
                              // double d;
                              {
                                  istringstream str(ligne);
                                  str >> d;
                              }
                              cout << "=> le double = " << d << endl;
                      
                              getline(monFlux, ligne);
                              cout << "- lecture d'un caractère sur la ligne 4: " << ligne << endl;
                              char c = ligne[0];
                              cout << "=> le caractère = " << c << endl;
                      
                              monFlux.close();
                          } else {
                              cout << "ERREUR: Impossible d'ouvrir le fichier en lecture." << endl;
                          }
                          return 0;
                      }
                      
                      
                      


                      Compilation et exécution

                      $ g++ -std=c++20 -Wall -Wextra -pedantic -Werror -Wno-unused -g    prog.cc   -o prog
                      
                      $ ./prog
                      - lecture d'un double sur la ligne 1: 3.4
                      => le double = 3.4
                      - lecture d'une ligne entière sur la ligne 2: Bonjour, je suis une phrase écrite dans un fichier.
                      => la ligne = Bonjour, je suis une phrase écrite dans un fichier.
                      - lecture d'un double sur la ligne 3: 42.1337
                      => le double = 42.1337
                      - lecture d'un caractère sur la ligne 4: J'ai 36 ans.
                      => le caractère = J



                      -
                      Edité par michelbillaud 7 juin 2023 à 15:36:01

                      • Partager sur Facebook
                      • Partager sur Twitter
                        7 juin 2023 à 23:58:08

                        Bonsoir

                        Le programme originel fonctionne bien sans le .ignore() à l'endroit indiqué. Je n'avais pas compris si je devais le remplacer par une autre instruction ou lui ajouter des paramètres.

                        @michelbillaud

                        L'exemple ci-dessus fonctionne bien de mon coté :

                        Comment se fait-il que des accolades avec aucune condition, boucle, ou paramètre de fonction devant tel que 

                        {

                                 istringstream str(ligne);

                                 str >> d;

                        }

                        arrivent à compiler ? Y'aurait-il une documentation sur ce genre de manipulation ?

                        Cordialement

                        • Partager sur Facebook
                        • Partager sur Twitter
                          8 juin 2023 à 7:37:05

                          Évidemment que ça fonctionne, on n'est pas là pour rigoler. Je copie-colle des résultats d'exécution, je vais pas m'amuser à les bidonner.

                          Les accolades, ca regroupe plusieurs instructions en une seule, ce qu'on appelle un bloc. Ça limite la portée des déclarations qui s'y trouvent. Le bloc, c'est une notion de base des langages de programmation depuis algol 60.

                          Il se trouve qu'on met souvent des blocs comme corps d'un if, d'un for etc, mais on peut en mettre où on veut, quand on en a besoin (ici pour avoir une variable str temporaire initialisée à partir de la valeur de ligne)

                          C'est pas une "manipulation", c'est l'utilisation des principes de base des langages de type C.

                          Tu devrais lire un vrai cours de c++, pas seulement  suivre des vidéos ou tutoriels qui n'expliquent pas les choses.

                          -
                          Edité par michelbillaud 8 juin 2023 à 10:13:41

                          • Partager sur Facebook
                          • Partager sur Twitter

                          Anomalie dans la lecture d'un fichier .txt

                          × 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