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 :

string Buffer = "";


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Inscrit en
    Juillet 2008
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Juillet 2008
    Messages : 20
    Par défaut string Buffer = "";
    salut
    j'ai un fichier .csv qui contient 27000 ligne et je veux suprrimer les ligne 4,5,6
    ça fonction avec le code que j'ai mais ça prend presque 2min pour s'exécuté
    y'a t'il unmoyenne pour minimiser le temps de l'execution

    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
     
    #include <string> 
    #include <fstream> 
     
    void Erase_Line1(char* z, int Line_to_Erase) 
    { 
    std::string Buffer = ""; //Variable contenant le texte à réécrire dans le fichier 
    std::ifstream ReadFile( z); 
    if (ReadFile) //Si le fichier est trouvé 
    { 
    std::string line; 
    int Line = 0; 
    while ( std::getline( ReadFile, line ) ) //on parcours le fichier et on initialise line à la ligne actuelle 
    { 
    Line++; 
    if(Line != Line_to_Erase) //Si la ligne atteinte est différente de la ligne à supprimer... 
    Buffer += line + "\n"; //On ajoute le contenu de la ligne dans le contenu à réécrire 
    } 
    } 
    ReadFile.close(); //On ferme le fichier en lecture 
     
    std::ofstream WriteFile( z); //On ouvre ce même fichier en écriture 
    WriteFile << Buffer; //On écris le texte dedans 
    WriteFile.close(); //et on ferme le fichier 
    } 
     
    int main() 
    { 
    Erase_Line1("z.txt", 4); 
    Erase_Line1("z.txt", 4); 
    Erase_Line1("z.txt", 4); 
     
    return 0; 
    }

  2. #2
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Selon la taille réelle du fichier (parce que, 27000 lignes, ca fait beaucoup, mais, encore faut il voir combien de caractères cela représente ), tu pourrais envisager de te baser sur l'entrée de la FAQ qui présente comment lire l'intégralité d'un fichier dans un buffer...

    Une fois cette opération effectuée, il deviendra relativement facile de faire le tri de ce que tu veux garder et de ce que tu veux virer à coup de find_first_of, ingore et autres substr
    L'idée pouvant se baser sur un algorithme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    POUR chaque ligne précédent celle que je veux retirer
       écrire la ligne dans le fichier de destination
    FIN POUR
    supprimer la ligne que je veux retirer
    SI Fin exécution
        ecrire ce qui reste du fichier
    FIN SI
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre éprouvé Avatar de BainE
    Inscrit en
    Mai 2004
    Messages
    1 327
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 1 327
    Par défaut
    Oui,

    ecrire a la volée chaque ligne lue qui doit etre dans le fichier destination/final.
    De mémoire quand tu fais un append sur string (ou un +=) il y a creation d une nouvelle string et recopie ce qui prend beaucoup de temps.

    sinon il doit exister la classe stringbuffer qui peut aussi reduire le temps d execution.

    [edit] bon y a pas stringbuffer en cpp, mais la concatenation de 27000 string me semble etre tres optimisable.

  4. #4
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 395
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 395
    Par défaut
    La classe std::string possède une fonction membre reserve.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  5. #5
    Membre éprouvé Avatar de BainE
    Inscrit en
    Mai 2004
    Messages
    1 327
    Détails du profil
    Informations forums :
    Inscription : Mai 2004
    Messages : 1 327
    Par défaut
    ca se fait de reserver, disons des lignes de 50 car en moyennes soit 1.35 Mega Windowsien

    [edit] d autant que après test ça ne fait rien gagner en temps. Ce serait la recopie de caractère qui prendrait tout ce temps

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Déjà, il serait peut être sage de ne pas relire 3 fois le fichier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    int main() 
    { 
         Erase_Line1("z.txt", 4); // 1 fois
         Erase_Line1("z.txt", 4); // 2 fois
         Erase_Line1("z.txt", 4); // 3 fois
     
          return 0; 
    }
    => plutôt que de passer un numéro de ligne, passer un vecteur de lignes rangées dans l'ordre croissant
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main() 
    { 
         int lines[] = { 4, 5, 6, 0 };
         Erase_Line1("z.txt", lines);
         return 0; 
    }
    Puis on modifie le code de Erase_Line1
    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
    void Erase_Line1(char* z, int* lines_to_erase)
    { 
          std::ifstream ReadFile(z); 
     
          if (ReadFile) //Si le fichier est trouvé 
          { 
               std::ofstream WriteFile (z+qqc);
     
               std::string line;
                int linenb = 0; 
                int erasing_line = *lines_to_erase;
    
                while (erasing_line != 0) {
                     while ( std::getline( ReadFile, line ) ) //on parcours le fichier et on initialise line à la ligne actuelle 
                     { 
                           linenb++;
                           if (linenb == erasing_line)
                                 break;
                           WriteFile << line << endl; // *fix* nl?
    
                     }
                lines_to_erase++;
                erasing_line = *lines_to_erase;
                } 
                // recopier la fin du fichier ? Ajouter un test sur eof?
                while ( std::getline( ReadFile, line ) ) //on parcours le fichier et on initialise line à la ligne actuelle 
                { 
                           WriteFile << line << endl; // *fix* nl?
                 } 
                ReadFile.close(); //On ferme le fichier en lecture  
                WriteFile.close(); //et on ferme le fichier 
           }
    }
    Je n'ai pas testé, mais ca donne l'idée.
    - W
    edit: j'avais oublié de "coller" la fin du fichier
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Ceci dit, je me rend compte que tu va lire l'intégralité du fichier... à chaque fois que tu voudra supprimer une ligne...

    Au final, en voulant supprimer trois lignes, tu en arrive à devoir en lire ... 3*27000 = 78000 ...

    Dés lors, tu pourrais surement diviser le temps nécessaire par trois, simplement en lisant le fichier une bonne fois pour toute et en mettant les lignes lues dans un conteneur "qui va bien"

    Ainsi, bien que la suppression d'élément ne soit pas "forcément" le point fort de la classe vector, tu pourrais envisager un code 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
    28
    29
    30
    31
    32
    int main()
    {
        /* un conteneur pour les lignes du fichiers */
        std::vector<std::string> tab;
        /* ouvrons le fichier en lecture */
        std::ifstream ifs("lefichier.csv");
        /*une chaine de caractères temporaire pour la lecture */
        std::string str;
        /* tant que l'on arrive à lire une ligne, ajoutons la dans le tableau
         * prévu à cet effet 
         */
        while(std::getline(ifs, str))
            tab.push_back(str);
        /* comme nous voudrons réouvrir le fichier en écriture
         * autant le fermer correctement 
         */
        ifs.close();
        /* créons deux itérateur: le premier sur la première chaine à supprimer
         * le second sur la derniere
         */
        std::vector<std::string>::iterator beg=tab.begin()+3 ;// (1+3= ...4 ;) )
        std::vector<std::string>::iterator end= tab.begin()+5;//(1+5 = ...6 ;) )
        /* et supprimons supprimons les, ainsi que ce qui se trouve entre les deux
         */
        tab.erase(beg, end);
        /* il n'y a plus qu'à réécrire le fichier */
        std::ofstream ofs("lefichier.csv");
        for(size_t i=0;i<tab.size();++i)
            ofs<<tab[i];
        /* merci d'être passé */
        return 0;
    }
    A adapter éventuellement pour apporter plus de flexibilité et ou plus de sécurité

    [EDIT]grilled sur la remarque
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  8. #8
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 738
    Par défaut
    Désolé

    Pourquoi vouloir charger le contenu du fichier en mémoire alors qu'il "suffit" (a mon sens) de le ré-écrire sans les lignes que l'on souhaite supprimer?
    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Erreur character string buffer too small
    Par uriel khaan dans le forum SQL
    Réponses: 2
    Dernier message: 21/03/2007, 17h24

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