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 :

seekg ne recule pas


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé

    Homme Profil pro
    développeur à la maison
    Inscrit en
    Septembre 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : développeur à la maison

    Informations forums :
    Inscription : Septembre 2006
    Messages : 416
    Billets dans le blog
    16
    Par défaut seekg ne recule pas
    Bonjour,

    lorsque on est arrivé à la fin du fichier, seekg devrait repositionner de deux tampons en arrière et source.read devait charger le tampon précédent. Dans le débogueur, le tampon reste le même dans le tableau tampon. Pourquoi seekg ne recule pas?
    quelqu'un a une idée?

    scanneur.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
    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
    #include <string>
    #include <fstream>
    #include <iostream>
     
    #include "scanneur.hpp"
     
    scanneur::scanneur(std::string nomfichier):enavant(0),nbtampons(0){
      char c;
      source.open(nomfichier.c_str(),std::ifstream::binary);
      if( ! source.is_open()){
        std::cerr<<"impossible d'ouvrir "<<nomfichier<<std::endl;
        exit(1);
      }
      source.seekg(0,source.end);
      taillefichier = source.tellg();
      source.seekg (0, source.beg);
      source.read(tampon,tailletampon);
      nbtampons++;
      tampon[tailletampon]=EOF;//sentinelle
      lus=source.gcount();
      if(lus<tailletampon)
        tampon[lus]=EOF;
      for(c=carsuiv();c!=EOF;c=carsuiv())
        if(c=='\n')
          std::cout<<std::endl;
        else
          std::cout << c;
      for(int i=0;i<taillefichier;i++){
        reculer(2);
        c=carsuiv();
        if(c=='\n')
          std::cout<<std::endl;
        else
          std::cout<<c;
      }
    }
     
    char scanneur::carsuiv(){
      char c=tampon[enavant++];
      if(c==EOF){
        if(enavant==tailletampon+1){//+1 car enavant a été incrémenté
          source.read(tampon,tailletampon);
          nbtampons++;
          tampon[tailletampon]=EOF;//sentinelle
          lus=source.gcount();
          tampon[lus]=EOF;//dernier caractère du tampon chargé
          enavant=0;
          c=tampon[enavant++];
        }
      }
      return c;
    }
     
    void scanneur::reculer(int n){
      for(int i=0;i<n;i++)
        if(enavant>0)
          enavant--;
        else{
          if(nbtampons>1){
    	nbtampons-=2;
    	source.seekg(nbtampons*tailletampon,std::ios::beg);
    	nbtampons++;
    	source.read(tampon,tailletampon);
    	enavant=source.gcount();
          }
        }
    }
    scanneur.hpp
    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
    #ifndef SCANNEUR_HPP
    #define SCANNEUR_HPP
    #include <fstream>
     
    constexpr int tailletampon=7;
     
    class scanneur{
    public:
      scanneur(std::string nomfichier);
      char carsuiv();
      void reculer(int n);
    private:
      char tampon[tailletampon+1];//+1 pour la sentinelle
      int enavant,taillefichier,lus,nbtampons;
      std::ifstream source;
    };
    #endif
    main.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
    #include <iostream>
    #include <string>
    #include "scanneur.hpp"
     
     
    int main(int argc,char *argv[]){
      if(argc==1){
        std::cerr<<"indiquez le fichier source"<<std::endl;
        exit(2);
      }
      std::string in=argv[1];
      scanneur scan(in);
      return 0;
    }

  2. #2
    Membre éclairé

    Homme Profil pro
    développeur à la maison
    Inscrit en
    Septembre 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : développeur à la maison

    Informations forums :
    Inscription : Septembre 2006
    Messages : 416
    Billets dans le blog
    16
    Par défaut
    j'ai changé reculer(int n):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void scanneur::reculer(int n){
      for(int i=0;i<n;i++)
        if(enavant>0)
          enavant--;
        else{
          if(nbtampons>1){
    	source.seekg((nbtampons-2)*tailletampon,std::ios::beg);
    	nbtampons--;
    	source.read(tampon,tailletampon);
    	enavant=source.gcount();
          }
        }
    }
    mais ça ne change pas d'effet.

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 153
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 153
    Billets dans le blog
    4
    Par défaut
    Est-ce que tu compiles encore en C++98 ?
    Citation Envoyé par c++98
    If the eofbit flag is set before the call, the function fails (sets failbit and returns).
    Citation Envoyé par c++11
    The function clears the eofbit flag, if set before the call.
    https://cplusplus.com/reference/istream/istream/seekg/
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  4. #4
    Membre éclairé

    Homme Profil pro
    développeur à la maison
    Inscrit en
    Septembre 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : développeur à la maison

    Informations forums :
    Inscription : Septembre 2006
    Messages : 416
    Billets dans le blog
    16
    Par défaut
    Merci pour la réponse. J'ai déjà vu cette page. En utilisant l'option -std=c++11 ou -std=gnu++11 j'ai le même problème.
    Mais c'est vrai que eof est activé:
    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
    void scanneur::reculer(int n){
      for(int i=0;i<n;i++)
        if(enavant>0)
          enavant--;
        else{
          if(nbtampons>1){
    	if(source.eof())
    	  std::cout<<"\neof"<<std::endl;
    	else
    	  std::cout<<"\npas eof"<<std::endl;
    	source.seekg((nbtampons-2)*tailletampon,std::ios::beg);
    	nbtampons--;
    	source.read(tampon,tailletampon);
    	enavant=source.gcount();
          }
        }
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    123456789
     
    98
    eof
    8888888
    une idée?

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 508
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 508
    Par défaut
    Salut,

    Ne te fait pas chier à écrire une micro-gestion du fichier: Monte toutes les données en mémoire, fait tes opérations, et redescend tout sur le disque quand tu as terminé.
    Des structures / classes sont autrement plus simple à gérer que les données brut sur le disque.

  6. #6
    Membre éclairé

    Homme Profil pro
    développeur à la maison
    Inscrit en
    Septembre 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : développeur à la maison

    Informations forums :
    Inscription : Septembre 2006
    Messages : 416
    Billets dans le blog
    16
    Par défaut
    Merci pour le hors-sujet. le fichier peut-être très volumineux. Je fais un scanneur car j'en ai besoin d'un. J'ai trouvé cette méthode dans un livre sur les compilateurs, le purple dragon book.
    voici comment j'ai résolu le problème (j'ai trouvé ça dans un de mes anciens projets):
    scanneur.hpp
    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
    #ifndef SCANNEUR_HPP
    #define SCANNEUR_HPP
     
    #include <fstream>
    #include <string>
     
    constexpr int taille=1000;
     
    class scanneur{
    public:
      scanneur(std::string const& nomFichier);
      char carsuiv();
      void reculer(int const &n);
      int getTailleFichier();
    private:
      std::ifstream fichier;
      char tampon[taille+1];// +1 car sentinelle
      int Ntampon;
      int enavant;
      int derniers;
      int tailleFichier;
    };
     
    #endif
    scanneur.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
    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
    #include <fstream>
    #include <iostream>
    #include "scanneur.hpp"
     
    scanneur::scanneur(std::string const& nomFichier):Ntampon(1),enavant(0),
    						  derniers(0){
      fichier.open(nomFichier.c_str(),std::ios::binary|std::ios::in);
      fichier.seekg(0,std::ios_base::end);
      tailleFichier=fichier.tellg();
      fichier.seekg(0,std::ios_base::beg);
      if(taille<=tailleFichier){
        fichier.read(tampon,taille);
        tampon[taille]=EOF;//sentinelle
      }
      else{
        derniers=tailleFichier;
        fichier.read(tampon,derniers);
        Ntampon=1;
        tampon[derniers]=EOF;//fin de fichier (pas sentinelle)
        enavant=0;
      }
    }
     
    char scanneur::carsuiv(){
      if(tampon[enavant]==EOF)
        if(enavant!=taille)
          return tampon[enavant++];//+1 car doit pointer sur le suivant
        else if((Ntampon+1)*taille<=tailleFichier){
          fichier.read(tampon,taille);
          Ntampon++;
          enavant=0;
          derniers=0;
          return tampon[enavant++];
        }
        else{
          derniers=tailleFichier%(Ntampon*taille);
          fichier.read(tampon,derniers);
          Ntampon++;
          tampon[derniers]=EOF;
          enavant=0;
          return tampon[enavant++];
        }
      else
        return tampon[enavant++];
    }
     
    void scanneur::reculer(int const &n){
      for(int i=0;i<n;i++){
        if(enavant==0){
          if(Ntampon>1){
    	fichier.seekg((Ntampon-2)*taille,std::ios_base::beg);
       	fichier.read(tampon,taille);
    	enavant=taille-1;
          }
          else if(derniers!=0)
    	enavant=derniers-1;
          else
    	enavant=taille-1;
          Ntampon--;
        }
        else
          enavant--;
      }
    }
     
    int scanneur::getTailleFichier(){
      return tailleFichier;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ ./a.out toto.txt 
    123456789
     
     
    987654321

  7. #7
    Membre éclairé

    Homme Profil pro
    développeur à la maison
    Inscrit en
    Septembre 2006
    Messages
    416
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Tarn et Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : développeur à la maison

    Informations forums :
    Inscription : Septembre 2006
    Messages : 416
    Billets dans le blog
    16
    Par défaut
    Citation Envoyé par deedolith Voir le message
    Des structures / classes sont autrement plus simple à gérer que les données brut sur le disque.
    c'est pour ça que je fais une classe scanneur. Je l'utilise dans le reste du programme.

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

Discussions similaires

  1. Réponses: 90
    Dernier message: 25/11/2019, 21h40
  2. Programmer encore en VB 6 c'est pas bien ? Pourquoi ?
    Par Nektanebos dans le forum Débats sur le développement - Le Best Of
    Réponses: 85
    Dernier message: 10/03/2009, 14h43
  3. Pas de fork sous Windows?
    Par chezjm dans le forum POSIX
    Réponses: 8
    Dernier message: 11/06/2002, 12h15

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