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

C++ Discussion :

Gérer les espace vide dans un fichier texte


Sujet :

C++

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2008
    Messages : 77
    Points : 39
    Points
    39
    Par défaut Gérer les espace vide dans un fichier texte
    Salut,

    Alors voilà j'ai un fichier texte de cette forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    AncienneIP                NouvelleIP                MASK                        Passerelle
     
     
    192.6.6.89                255.255.255.255                255.255.255.0                192.6.6.10
    220.23.23.1                25.21.20.10                255.255.255.0                192.6.6.10
    223.1.0.212                192.6.6.89                 255.255.255.0                192.6.6.10
    123.21.20.5                23.25.65.47                255.255.255.0                192.6.6.10
    Voici mon algorithme de lecture du 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
     
    bool lireFichierConfig()
    {
    	ifstream fichier("config.txt",ios_base::in);
    	if(fichier)
    	{
    		string ligne;
    		while(!fichier.eof())
    		{
    			getline(fichier,ligne);
    			fichier >> ::ancienneIP >> ::nouvelleIP >> ::mask >> ::passerelle;
    			if(::ancienneIP==::ip)
    				break;
    		}
    		Color(10,0);
    		cout << "OK : IP trouve dans le fichier config.txt." << endl;
    		Color(15,0);
    		cout << "---------------------------------------------------------" << endl;
    		cout << "Ancienne IP de la machine : ";
    		Color(12,0);
    		cout << ::ancienneIP << endl;
    		Color(15,0);
    		cout << "Nouvelle IP de la machine : ";
    		Color(10,0);
    		cout << ::nouvelleIP << endl;
    		Color(15,0);
    		cout << "Mask de la machine : ";
    		Color(10,0);
    		cout << ::mask << endl;
    		Color(15,0);
    		cout << "Passerelle de la machine : ";
    		Color(10,0);
    		cout << ::passerelle << endl;
    		Color(15,0);
    		cout << "---------------------------------------------------------" << endl << endl;
    		return true;
    	}
    	else
    	{
    		Color(12,0);
    		cout << "Erreur : Impossible de trouver le fichier config.txt." << endl;
    		Color(15,0);
    		return false;
    	}
    }
    Or lorsque j'aqquiert les valeurs il me faut obligatoirement les 4 dans une ligne sinon toutes le données se retrouve décalées car le programme enleves les espaces vides.
    Ce programme a pour but de changer l'ip de la machine dont le nom "ancienneIP" se trouve dans le fichier texte par l'ip "nouvelleIP" ainsi que le MASK et la passerelle via la commande netsh.

    Imaginons qu'une machine n'est pas de passerelle ?
    Comment peut on faire pour que le programme gerre ligne par ligne et qu'il range juste un "espace" dans la variable ::passerelle si celle ci n'est pas mentionné dans le fichier ?

    J'aimerais aussi que le programme puisse gérer les lignes de commentaires. (Comme dans les fichiers hosts de windows a peut près) Si l'on met un #devant le programme ne prend pas en compte la ligne.

    Merci d'avance pour votre aide,
    ++

    Barbuslex.

  2. #2
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    309
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 309
    Points : 148
    Points
    148
    Par défaut
    Salut,

    Commencons par le plus facile. Pour gerer tes commentaires, tu mets un # devant la ligne en question et tu teste le premier caractere de ta ligne (juste apres le getline()). Tu fais le traitement seulement si le caractere # n'est pas present.

    Pour traiter ton fichier, selon moi, le plus propre serait de creer une structure 'config' avec 4 string (un pour chaque adresse). Ensuite, tu remplis un 'vector<config>' avec ton fichier. Cela te donnerais plus de liberte dans la gestion de tes adresses.

    Mais le probleme reste entier : il faut extraire les donnees. Le plus simple c'est de placer un caractere reconnaissable entre chaque adresse, disons un pipe (dsl j'ai un clavier arabe et je sais pas ou il est).
    Apres, tu desindente ton texte (suppression de tout les espaces) et tu recupere ce qu'il y a entre les pipes.

    Ensuite, tu peux rechercher dans ton vector toutes les 'config' ou des donnees sont maquantes.

    Ca repond a tes questions ?

  3. #3
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 629
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 629
    Points : 30 692
    Points
    30 692
    Par défaut
    Salut,

    Le plus facile est toujours de réfléchir un tout petit peu, mais de réfléchir bien (dans le bon ordre)...

    Ainsi, on pourrait estimer que le plus souvent, il faut répondre à quatre questions:
    1. Que veut on faire
    2. quelles sont les spécifications
    3. Comment les appliquer
    4. De quelles possibilités dispose-t-on pour se faciliter la tache

    Et, une fois que l'on dispose des réponses correctes, tu te rendra compte que la mis en oeuvre en devient presque un jeu d'enfant

    Ainsi, essayons de répondre à ces quatre questions pour résoudre ton problème:
    Que veux-tu faire
    Tu veux pouvoir lire et écrire quatre informations distinctes dans un fichier de telle manière qu'elles apparaissent alignées lors de l'affichage du fichier.
    quelles sont les spécifications
    chaque information tient sur minimum 7 caractères ( 0.0.0.0) et sur maximum 15 (255.255.255.255)

    L'ordre dans lequel on lit ou écrit les informations est le suivant:
    1. Ancienne adresse IP
    2. nouvelle adresse IP
    3. masque sous réseau
    4. paserelle

    tout ce qui suit le symbole "#" ne doit pas être pris en compte

    Le symbole "#" est susceptible de prendre place:
    • en début de ligne (impliquant alors de ne pas prendre les informations en compte)
    • après les informations concernant la passerelle (permettant alors de fournir des informations supplémentaire au lecteur du fichier)

    La lecture d'informations doit permettre de ne pas prendre les espaces permettant la mise en forme
    Comment appliquer ces spécifications
    Si l'on veut que les informations restent représentées sous forme de colonnes, il s'agira de formater la sortie du fichier de telle manière à ce que:
    • Les informations relative à l''ancienne adresse IP soient toujours écrite sur minimum 17 caractères (15 pour la valeur, 1 pour le symbole "#" éventuel, et un pour l'espace permettant de séparer l'information de la suite)
    • les informations relatives à la nouvelle adresse IP, au masque sous réseau et ) la paserelle soient toujours écrites sur minimum 16 caractères (15 pour l'information et 1 d'espace permettant de séparer l'information de la suivante)
    • le nombre de caractères doit rester identique pour tout le fichier afin d'assurer l'alignement correct

    La lecture dans le fichier se fait ligne par ligne

    Un espace peut être représenté par un " " ou par un caractères '\t'
    De quelles possibilités dispose-t-on pour se faciliter la tache
    L'inclusion du fichier <iomanip> va nous fournir l'ensemble des possibliités suivantes:
    • Indiquer combien de caractères doivent au minimum être affichés, même si la taille de ce qui doit être affiché est plus petite que ce nombre minimum avec setw, qui est une commande non persistante (à répéter à chaque fois)
    • fournir le caractère de remplissage, qui ne sera pas utile ici, l'espace " " étant défini par défaut avec setfill, qui est une commande persistante (qui reste jusqu'à instruction contraire)

    D'autres possibilités intéressantes, même si elle ne seront pas utilisées ici (mais pourraient bien l'être):
    • déterminer si un caractères est considérable comme une lettre avec isalpha
    • déterminer si un caractère est considérable comme un chiffre avec isdigit
    • déterminer si un caractère est considérable comme un chiffre ou une lettre avec isalnum
    • déterminer si un caractère est considérable comme un espace ( ' ' ou '\t' ou tout autre caractère équivalent à un espace) avec isspace
    • D'autres encore, moins intéressantes pour ce qui nous intéresse


    Le fichier <sstream> fournit les classes de flux de conversions, ce qui nous sera surement utile

    le fichier <string> fournit la classe permettant de gérer facilement les chaines de caractères

    La classe string permet en outre d'obtenir un caractère dans la chaine avec l'opérateur []

    le fichier <fstream> fournit les classes permettant de gérer facilement les fichiers.

    Une des classes de conteneurs sera sans doute bien utile, étant donné qu'il s'agit de gérer une collection d'informations.

    Et, cerise sur le gateau, il pourrait être cohérent de pouvoir gérer les exceptions... le fichier <stdexcept> fournit tout ce qu'il faut

    A partir de là, "YAPUKA" s'amuser un peu avec tout cela

    Etant donné que les quatre données sont strictement dépendantes les unes des autres, il semble de bon ton de les regrouper dans une structure unique sous une forme proche de
    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
    struct Data
    {
        std::string oldIP;
        std::string newIP;
        std::string mask;
        std::string passerelle;
        /* comme on va typiquement travailler sur les flux avec cette
         * structure, autant fournir les opérateurs de flux qui s'accordent ;)
         */
        friend std::ostream& operator <<(std::ostream& ofs, const Data& d)
        {
            ofs<<setw(19)<<d.oldIP
                <<setw(19)<<d.newIP
                <<setw(19)<<d.mask
                <<setw(19)<<d.passerelle;
            return ofs;
        }
        friend std::istream& operator>>(std::istream& ifs, Data& d)
        {
            ifs>>d.oldIP
               >>d.newIP
               >>d.mask
               >>d.passerelle;
            return ifs;
        }
    };
    Je la laisse délibérément simpliste ici, mais on pourrait, par exemple, prévoir un "flag" permettant de représenter le fait que les informations représentées soient valides ou non

    Et pour la suite, il ne nous reste plus qu'à créer quelques fonctions qui vont bien

    Ainsi, nous pourrions envisager une fonction de lecture proche de
    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
    void readFromFile(const std::string& filename, std::list<Data>& dl)
    {
        /* tentons d'ouvrir le fichier en lecture */
        std::ifstream ifs(filename.c_str());
        /* si l'ouverture échoue, lançons une exception */
        if(!(ifs))
            throw std::runtime_error("file not found");
        /*arrivés ici, nous sommes sur que le fichier existe, nous allons donc
         * lire toutes les lignes une à une (il nous faut une chaine temporaire 
         * pour ce faire), et nous en servir pour créer
         * nos éléments data que nous insérerons dans la liste ;)
         */
        std::string temp;
        while(std::getline(ifs,temp))
        {
           /* Si le premier caractère est un "#", il ne sert à rien d'aller plus loin:
            * nous sommes face à une ligne de commentaire ;) 
            */
           if(temp[0]!='#')
           {
                Data toadd;
                std::stringstream ss(temp);
                ss>>toadd;
                dl.push_back(toadd);
            }
        }
    }
    et une autre fonction d'écriture proche de
    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
    void writeToFile(const std::string& filename, const std::list<Data>& dl)
    {
        /* tentons d'ouvrir le fichier en écriture*/
        std::ofstream ofs(filename.c_str());
        if(! ofs)
            throw std::runtime_error("Erreur lors de la tentative d'ouverture du fichier");
        /*arrivés ici, nous sommes sur que le fichier est ouvert en écriture, 
         * nous allons donc écrire chaque donnée que l'on trouve dans notre
         * liste sur une ligne du fichier ;)
         * nous pourrions très bien ajouter un tas de commentaires dans le fichier
         * avant de ce faire :D
         */
        ofs<<"#ce fichier a ete genere automatiquement a partir de l'aplication"
           <<" <nom application>"<<std::endl
           <<"#veuillez ne pas le modifier sous peine de voir la configuration du"
           <<"programme echouer"<<std::endl
           <<"#Les informations sont représentees sous la forme de"<<std::endl
           <<setw(19)<<"#ancienne IP"
           <<setw(19)<<"nouvelle IP"
           <<setw(19)<<"masque sous reseau"
           <<setw(19)<<"passerelle"<<std::endl;
        for(std::list<Data>::iterator it=dl.begin();it!=dl.end();++it)
            ofs<<(*it)<<std::endl;
    }
    Et, bien sur, il faudrait une fonction main pour gérer tout cela... Elle prendrait la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
    int main()
    {
        std::list<Data> datalist;
        /*quand on veut lire dans un fichier dont le nom  est représenté
         * par str
         */
        readFromFile(str,datalist);
        /* quand on veut écrire dans un fichier dont le nom est représenté
         * par str
         */
        writeToFile(str,datalist);
        return 0;
    }
    Et voilà... le tour est joué

Discussions similaires

  1. [LV2009] Supprimer les lignes vides dans un fichier texte
    Par Super2006 dans le forum LabVIEW
    Réponses: 3
    Dernier message: 11/11/2011, 14h32
  2. Réponses: 2
    Dernier message: 28/11/2010, 15h15
  3. [PHP 5.0] Passer une variable vide dans un fichier texte
    Par tarmo57 dans le forum Langage
    Réponses: 2
    Dernier message: 22/02/2009, 14h45
  4. Probleme ligne vide dans un fichier texte ?
    Par liocifer dans le forum VBScript
    Réponses: 3
    Dernier message: 05/06/2008, 09h45
  5. Récuperer les saisies clavier dans un fichier texte?
    Par UnSofteuxAmateur dans le forum Delphi
    Réponses: 8
    Dernier message: 25/05/2007, 14h13

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