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

Autres �diteurs Discussion :

ifstream, d�rivation ou encapsulation ?


Sujet :

Autres �diteurs

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    27
    D�tails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2006
    Messages : 27
    Par d�faut ifstream, d�rivation ou encapsulation ?
    Salut � tous et bonne ann�e !

    Voila, j'ai un petit probl�me, petit car je pourrai passer par des moyens d�tourn�. Je vous explique, j'ai un fichier configuration � charger, simple fichier texte listant un certain nombre de donn�es dans un certain ordre. J'aimerais y ajouter des commentaires, pr�c�d� d'un '#' par exemple. Jusque l�, il n'y a pas de soucis.

    Oui, mais voila, je voudrai que �a soit compl�tement transparent � l'utilisation, je souhaiterai pouvoir faire des "file>>value" qui ignorerai automatiquement les commentaires. Pour cela, deux solutions me sont venus � l'esprit, l'encapsulation tout d'abord ou la d�rivation ensuite.

    la d�rivation par exemple :
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class CFileConfig : public std::ifstream
    {
    public:
    	CFileConfig(const char * filename):std::ifstream(filename){};
    	~CFileConfig();
    };
     
    /* plus loin */
    CFileConfig file("file.txt");
    int var1,var2;
    file>>var1>>var2;

    Mon probl�me est donc surd�finir l'op�rateur >> afin qu'il garde la capacit� d'�crire dans n'importe quel type de donn�e tout en ignorant les lignes commencant par un #...


    Merci d'avance pour vos pistes

    Edit: Oula, je viens de me rendre compte que ce message risque de ne pas �tre au bon endroit�

  2. #2
    Membre �m�rite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    865
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 865
    Par d�faut
    Tu dois composer. En effet, un ifstream est un basic_ifstream<char> et basic_ifstream d�rive de basic_istream. Dans ces deux classes, aucune m�thode n'est virtuelle en particulier les op�rateurs >> (sauf le destructeur de basic_istream).
    Tu ne pourras donc pas profiter des m�canismes de virtualit�.
    Tu dois donc composer et non d�river.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    27
    D�tails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2006
    Messages : 27
    Par d�faut
    J'avais constat� effectivement, mais qu'entend tu par "composer", je r��cris tout les op�rateurs >> ?

    Sinon, j'avais peut �tre pens� �, � l'ouverture du fichier, lire et recr�er un flux sans les commentaires et donc finalement ouvrir ce dernier, une voie � explorer? Je vais essayer...

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    27
    D�tails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2006
    Messages : 27
    Par d�faut
    Donc voila, en d�finitive je suis pass� par un fichier temporaire

    FileConfig.h
    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    #define TEMP_EXT ".temp"
    class CFileConfig : public std::ifstream
    {
    public:
    	CFileConfig(const char * filename);
    	~CFileConfig();
    private:
    	char * m_tempFileName;
     
    };
    FileConfig.cpp
    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
    CFileConfig::CFileConfig(const char * filename):std::ifstream(filename)
    {
    	/* save temporary file name */
    	m_tempFileName = new char[strlen(filename) + strlen(TEMP_EXT)];
    	strcpy(m_tempFileName,STR.sprintf_rs("%s"TEMP_EXT"",filename));
     
    	std::ofstream tempFile(m_tempFileName);
    	ASSERT(tempFile);
     
    	/* copy the file in new file */
    	std::string line;
    	while(std::getline(*this, line))
    	{
    		if(line.length()>0)
    			if(line[0]!='#')
    				tempFile<<line<<std::endl;
    	}
     
    	/* close previous file, open temparary file */
    	this->close();
    	this->clear();
    	tempFile.close();
    	this->open(m_tempFileName);
    }
     
    CFileConfig::~CFileConfig()
    {
    	this->close();
    	this->clear();
    	/* delete temporary file */
    	std::remove(m_tempFileName);
    }

    Petite note : mon "STR.sprintf_rs" est en fait un sprintf sur des chaines de caract�res temporaires.

    Qu'en pensez vous ? C'est vrai que �a fait une ecriture de fichier, mais c'est une op�ration r�alis� uniquement au chargement... D'ailleurs, je n'ai pas trouv� un type ofstream qui n'ecrirai pas dans un fichier mais seulement en memoire...

  5. #5
    Membre �m�rite
    Profil pro
    Inscrit en
    Mars 2005
    Messages
    865
    D�tails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2005
    Messages : 865
    Par d�faut
    J'ai retravaill� ton code ainsi pour composer avec un ifstream. Vu ce que tu en fait, il est inutile de le d�river (en plus des raisons que j'ai dit hier).
    Par contre, je ne suis pas pourquoi tu rouvres ton fichier en lecture seul � la fin. Tu ne peux plus rien �crire dedans... J'aurais plut�t compos� avec un ofstream. A vrai dire, je ne vois pas ce que tu veux faire, pourquoi tu parles d'un ofstream qui n'�crirait qu'en m�moire...

    Autrement,
    • �viter les char * en C++, alors qu'on dispose des strings, �a �vite d'utililiser les strcpy, de se planter dans les tailles de chaines et d'�crire un STR.sprintf_rs inutile
    • �viter les macros en C++, pr�f�rer d�clarer des constantes
    • pas de macro ASSERT sur une erreur qui peut toujours appara�tre � l'ex�cution, en effet, une fois que ton assert sera d�sactiv� (par NDEBUG), tu ne pourras plus d�tecter une erreur d'ouverture de fichier


    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
     
    #include <cassert>
    #include <fstream>
    #include <iostream>
    #include <stdexcept>
    #include <string>
     
    const std::string TEMP_EXT = ".temp";
     
    class invalid_file : public std::runtime_error {
    public:
      explicit invalid_file (const std::string & args);
    };
     
    invalid_file::invalid_file (const std::string & args) 
      : std::runtime_error (args) {}
     
    class CFileConfig {
    public:
      CFileConfig(const std::string &);
      ~CFileConfig();
    private:
      std::ifstream m_configFile;
      std::string   m_tempFilename;
    };
     
    CFileConfig::CFileConfig(const std::string & filename) 
      : m_configFile (filename.c_str()),
        m_tempFilename (filename + TEMP_EXT) {
     
      if ( ! m_configFile ) throw invalid_file ("Can't open " + filename);
     
      std::ofstream tempFile(m_tempFilename.c_str());
     
      if ( ! tempFile ) {
        m_configFile.close ();
        throw invalid_file ("Can't open " + m_tempFilename);
      }
     
      /* copy the file in new file */
      std::string line;
      while(std::getline(m_configFile, line)) {
        if(line.length() > 0) {
          if(line[0] != '#') {
    	tempFile << line << std::endl;
          }
        }
      }
     
      /* close previous file, open temporary file */
      m_configFile.close ();
      tempFile.close ();
      m_configFile.open (m_tempFilename.c_str());
     
    }
     
    CFileConfig::~CFileConfig() {
      m_configFile.close();
      /* delete temporary file */
      std::remove(m_tempFilename.c_str());
    }
     
    int main () {
      try {
        CFileConfig config ("if.txt");
      } catch (std::exception & ex) {
        std::cerr << ex.what () << std::endl;
      }
      return 0;
    }

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Avril 2006
    Messages
    27
    D�tails du profil
    Informations personnelles :
    Localisation : Canada

    Informations forums :
    Inscription : Avril 2006
    Messages : 27
    Par d�faut
    Merci pour cette correction, � vrai dire, � propos de l'utilisation des char * pr�alou�, je les utilise car je tourne sur un syst�me tr�s limit� (une esp�ce de console portable) o� les std::string sont assez lent.

    De la m�me mani�re, les exceptions me paraissent plus s�re mais encore une fois, pour un soucis d'optimisation, je me suis r�duit aux asserts (d'autant plus que c'est impos� par mon cahier des charges)...

    Sinon, j'ouvre en lecture seule car je n'ai justement pas besoin de r��crire dans le fichier. Enfin, je parlais d' "ofstream en memoire" en esperant trouver un �quivalent de ofstream qui n'�crirai pas sur le disque dur, je ne sais pas vraiment si cela existe...

    En tout cas, merci beaucoup pour ces indications! �a me lib�re du flou dans lequel je navigue parfois en utilisant std...

    EDIT : Deux petites erreures dans mon code d'origine qui est loin d'�tre une r�f�rence d'ailleurs :


    Code : S�lectionner tout - Visualiser dans une fen�tre � part
    1
    2
    3
    m_tempFileName = new char[strlen(filename) + strlen(TEMP_EXT) + 1];
    /* in the destuctor */
    delete [] m_tempFileName;

+ R�pondre � la discussion
Cette discussion est r�solue.

Discussions similaires

  1. R�ponses: 31
    Dernier message: 30/03/2006, 17h57
  2. Probleme avec ifstream
    Par maitre hibou dans le forum SL & STL
    R�ponses: 12
    Dernier message: 12/05/2004, 14h33
  3. Encapsulation graphique d'un outil en ligne de commande
    Par Leishmaniose dans le forum Composants VCL
    R�ponses: 3
    Dernier message: 12/11/2003, 12h59
  4. D�rivation dune fonction
    Par srvremi dans le forum C++Builder
    R�ponses: 2
    Dernier message: 27/07/2002, 15h21
  5. [MFC](encapsulation ADO) ou placer le code
    Par philippe V dans le forum MFC
    R�ponses: 2
    Dernier message: 13/06/2002, 15h58

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