Choisissez votre style : colorisé, impression

Série 11  (Niveau 0):
Flots

Pas à pas 1 : Reprise de l'exemple du cours (lecture et écriture sur fichier, niveau 0)

Cet exercice est disponible en page 68 de l'ouvrage C++ par la pratique

On veut écrire un programme fichiers.cc qui permet de lire le contenu d'un fichier et de le copier dans un autre.

Cet exercice reprend pas à pas les différentes étapes pour y parvenir.

  1. Comme d'habitude, créez la « coquille » de base de votre programme dans un fichier fichiers.cc :
    #include <iostream>
    using namespace std;
    
    int main()
    {
    
    	return 0;
    }
    
  2. Pour utiliser les fichiers, il faut inclure les fichiers de définitions correspondant : fstream.
    #include <iostream>
    #include <fstream>
    using namespace std;
    
    int main ()
    {
    	return 0;
    }
    
  3. Prototypez la fonction demande_noms qui va demander deux noms de fichier à l'utilisateur (un pour l'entrée et un pour la sortie).
    Essayez de le faire sans regarder la solution ci-dessous. Essayez également de ne rien oublier.


    Solution :

    On veut demander 2 noms de fichiers... Dans quel type de données allons-nous les mettre ?
    Dans des strings tout naturellement.
    Donc première chose à faire : inclure la bibliothèque des strings :

    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    ...
    

    Ensuite, quel doit être le prototype demandé ?
    La question est : comment cette fonction doit-elle retourner ces 2 informations au reste du programme.

    2 solutions sont envisageables : la plus naturelle serait justement de retourner les deux strings via la valeur de retour. Mais une fonction en C++ en peut retourner qu'un seul élément. On peut donc penser ici à créer une structure qui contiendrait 2 strings et retourner cette structure.

    Cette solution est tout à fait possible et correcte, mais peut être un peu lourde ici (car cette structure ne servirait plus ensuite).

    Une autre solution offerte en C++ est d'utiliser le passage par référence qui permet à une fonction de modifier ses arguments.

    Avec cette solution, il faut donc passer 2 strings par référence comme arguments à la fonction ; ce qui nous conduit au prototype suivant :

    void demande_noms(string& fichier_entree, string& fichier_sortie);

    On a donc à ce stade le code suivant :

    #include <iostream>
    #include <string>
    using namespace std;
    
    void demande_noms(string& fichier_entree, string& fichier_sortie);
    
    int main()
    {
    	return 0;
    }
    


  4. Définissez maintenant cette fonction.

    Solution :

    #include <iostream>
    #include <fstream>
    #include <string>
    using namespace std;
    
    void demande_noms(string& fichier_entree, string& fichier_sortie);
    
    int main()
    {
    	return 0;
    }
    // DEFINITION
    // Demande les noms des fichiers a l'utilisateur
    void demande_noms(string& fichier_entree, string& fichier_sortie) {
      cout << "Saisie des nom de fichiers." << endl;
      cout << "    Entrez le nom du fichier de lecture:  " << flush;
      cin >> fichier_entree;
      cout << "    Entrez le nom du fichier de sortie:  " << flush;
      cin >> fichier_sortie;
    }
    
    
  5. Définissez (prototype et définition) une autre fonction transfert_fichier qui va copier, ligne par ligne, le contenu du fichier dont le nom est contenu dans 'fichier_entree' dans le fichier dont le nom est contenu dans 'fichier_sortie'.
    • Ouvrez les flots d'entrée et de sortie avec les noms de fichier passés en arguments. (N'oubliez pas d'utiliser la fonction c_str()).
    • Testez l'état du flot avec la fonction fail().
    • Il faut ensuite lire le flot d'entrée ligne par ligne (en utilisant la fonction getline(). Notez que cette fonction renvoie la valeur 0 si aucune ligne n'a pu être lue.) et le recopier dans le flot de sortie. L'extraction s'arrête lorsque l'on atteint la fin du fichier (entree.eof() est true)
    • À la fin, il ne reste plus qu'a fermer les flots avec la fonction close().

    Solution :

    #include <iostream>
    #include <fstream> 
    #include <string>
    using namespace std;
    
    ...
    void transfert_fichier(string fichier_entree, string fichier_sortie);
    
    int main()
    {
    	return 0;
    }
    
    ...
    
     // transfère les données du fichier 'fichier_entree' au fichier 'fichier_sortie'
    void transfert_fichier(string fichier_entree, string fichier_sortie) {
      
      // ouvre le flot d'entrée
      ifstream entree(fichier_entree.c_str());
    
      // vérifie que le fichier existe
      if (entree.fail()){
        cerr << "Erreur : impossible d'ouvrir le fichier " << fichier_entree
             << " en lecture." << endl;
        return;
      }
    
      // ouvre le flot de sortie
      ofstream sortie(fichier_sortie.c_str());
      
      if (sortie.fail()){
        cerr << "Erreur : impossible d'ouvrir le fichier " << fichier_sortie
             << "en écriture." << endl;
        return;
      }
    
      string ligne;
    
      // lit le fichier ligne par ligne jusqu'à la fin de celui-ci
      while (!entree.eof()){
         sortie << ligne << endl; // copie la ligne dans le flot de sortie
      } 
      
      // ferme les flots
      entree.close();
      sortie.close();
    
      cout << "Transfert terminé !"<< endl;
    }
    
  6. Il ne reste plus qu'à compléter le main pour copier les données  :
    #include <iostream>
    #include <fstream> 
    #include <string>
    using namespace std;
    
    ...
    
    int main()
    {
      string fichier_entree, fichier_sortie;
    
      // demande les noms des fichiers
      demande_noms(fichier_entree, fichier_sortie);
    
      // transfère les données du fichier 'fichier_entree' au fichier
      // fichier_sortie'
      transfert_fichier(fichier_entree, fichier_sortie);
    
      return 0;
    }
    
    ...
    

    Cliquez ici pour revenir à la série.

    Programme complet :

    #include <iostream>
    #include <fstream> 
    #include <string>
    using namespace std;
    
    void demande_noms(string& fichier_entree, string& fichier_sortie);
    void transfert_fichier(string fichier_entree, string fichier_sortie);
    
    int main()
    {
      string fichier_entree, fichier_sortie;
    
      // demande les noms des fichiers
      demande_noms(fichier_entree, fichier_sortie);
    
      // transfère les données du fichier 'fichier_entree' au fichier
      // fichier_sortie'
      transfert_fichier(fichier_entree, fichier_sortie);
    
      return 0;
    }
    
    // demande les noms des fichiers à l'utilisateur
    void demande_noms(string& fichier_entree, string& fichier_sortie){
      cout << "Saisie des nom de fichiers" << endl;
      cout << "    Entrez le nom du fichier de lecture:  " << flush;
      cin >> fichier_entree;
      cout << "    Entrez le nom du fichier de sortie:  " << flush;
      cin >> fichier_sortie;
    }
    
    // transfère les données du fichier 'fichier_entree' au fichier 'fichier_sortie'
    void transfert_fichier(string fichier_entree, string fichier_sortie) {
      
      // ouvre le flot d'entrée
      ifstream entree(fichier_entree.c_str());
    
      // vérifie que le fichier a bien été ouvert
      if (entree.fail()){
        cerr << "Erreur : impossible d'ouvrir le fichier " << fichier_entree
             << " en lecture." << endl;
        return;
      }
    
      // ouvre le flot de sortie
      ofstream sortie(fichier_sortie.c_str());
      if (sortie.fail()){
        cerr << "Erreur : impossible d'ouvrir le fichier " << fichier_sortie
             << " en écriture " << endl;
        return;
      }
    
      string ligne;
    
      // lit le fichier ligne par ligne jusqu'à la fin de celui-ci
      while (!entree.eof()){
    	  if (getline(entree, ligne))
           sortie << ligne << endl; // copie la ligne dans le flot de sortie
      } 
      
      // ferme les flots
      entree.close();
      sortie.close();
    
      cout << "Transfert terminé !"<< endl;
    }
    

Pas à pas 2 : Reprise de l'exemple du cours (Manipulateurs, niveau 0)

Cet exercice est disponible en page 72 de l'ouvrage C++ par la pratique

On veut écrire un programme manipulateurs.cc qui permet d'écrire une matrice identité (avec que des 1 sur la diagonale et des 0 ailleurs) dans un fichier, en utilisant les manipulateurs de flot.

Cet exercice reprend pas à pas les différentes étapes pour y parvenir.

  1. Ouvrez le fichier (vide) manipulateurs.cc dans votre éditeur favori.
  2. Préparez la « coquille » vide de base accueillant votre programme. Pour utiliser les fichiers, il faut inclure le fichier de définitions correspondant , fstream.
    #include <iostream>
    #include <fstream> 
    using namespace std;
    
    int main()
    {
    	return 0;
    }
    
  3. Définissez (prototype et définition) une fonction ecrit_matrice_identite qui aura pour but d'écrire la matrice désirée (indiquée par sa taille, passée en argument) dans un fichier (dont le nom est passé en argument).
    • Ouvrez le flot de sortie et testez l'ouverture avec la fonction fail() ;
    • Écrivez la matrice dans le fichier ouvert, en utilisant les manipulateurs setw() et setfill(). Ces fonctions nécessitent d'inclure le fichier de définitions iomanip
    • À la fin, il ne reste plus qu'à fermer le flot avec la fonction close().

    Solution :

    #include <iostream>
    #include <iomanip>
    #include <fstream> 
    #include <string>
    using namespace std;
    
    ...
    void ecrit_matrice_identite(string fichier_sortie, int taille);
    
    int main()
    {
    	return 0;
    }
    
    // écrit la matrice identité dans un fichier
    void ecrit_matrice_identite(string fichier_sortie, int taille){
     
      // ouvre le flot
      ofstream sortie(fichier_sortie.c_str());
      
      if (sortie.fail()){
        cerr << "Erreur : impossible d'ouvrir le fichier " << fichier_sortie
    	 << "en écriture." << endl;
        return;
      }
    
      sortie << setfill('0') ;
      for (int i(1); i < taille; ++i)
        sortie << setw(i) << '1' << setw(taille-i) << '0' << endl;
      sortie << setw(taille) << '1' << endl;
        
      // ferme le flot
      sortie.close();
      cout << "Matrice sauvegardée dans le fichier " << fichier_sortie << "." 
           <<  endl;
    } 
    
    
  4. Il ne reste plus qu'à compléter le main pour créer la matrice, par exemple comme ici (d'autres variantes sont possibles) :
    ...
    
    int main()
    {
      int taille(0);
      string fichier_sortie;
    
      cout << "Taille de la matrice :" << endl;
      cin >> taille;
      if (taille > 25) taille = 25;
      else if (taille < 2) taille = 2;
    
      cout << "Nom du fichier de sortie :" << flush;
      cin >> fichier_sortie;
    
      // écrit la matrice identité dans le fichier
      ecrit_matrice_identite(fichier_sortie, taille);
    }
     
    ...
    
  5. Cliquez ici pour revenir à la série.

    Programme complet :

    #include <iostream>
    #include <fstream> 
    #include <iomanip>
    #include <string>
    using namespace std;
    
    void demande_taille(string fichier_sortie, int taille);
    void ecrit_matrice_identite(string fichier_sortie, int taille); 
    
    int main()
    {
      int taille(0);
      string fichier_sortie;
    
      cout << "Taille de la matrice :" << endl;
      cin >> taille;
      if (taille > 25) taille = 25;
      else if (taille < 2) taille = 2;
    
      cout << "Nom du fichier de sortie :" << flush;
      cin >> fichier_sortie;
    
      // écrit la matrice identité dans le fichier
      ecrit_matrice_identite(fichier_sortie, taille);
    
      return 0;
    }
    
    
    // écrit la matrice identité dans un fichier
    void ecrit_matrice_identite(string fichier_sortie, int taille){
     
      // ouvre le flot
      ofstream sortie(fichier_sortie.c_str());
      
      if (sortie.fail()){
        cerr << "Erreur : impossible d'ouvrir le fichier " << fichier_sortie
    	 << "en écriture." << endl;
        return;
      }
    
      sortie << setfill('0') ;
      for (int i(1); i < taille; ++i)
        sortie << setw(i) << '1' << setw(taille-i) << '0' << endl;
      sortie << setw(taille) << '1' << endl;
        
      // ferme le flot
      sortie.close();
      cout << "Matrice sauvegardée dans le fichier " << fichier_sortie << "." 
           <<  endl;
    } 
    
    

Dernière mise à jour : $Date: 2024/12/02 14:34 $