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 :

Compréhension de fseek()


Sujet :

C

  1. #1
    Membre averti Avatar de SPACHFR
    Profil pro
    Paaaaaa
    Inscrit en
    Février 2004
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paaaaaa

    Informations forums :
    Inscription : Février 2004
    Messages : 557
    Points : 400
    Points
    400
    Par défaut Compréhension de fseek()
    Bonjour,

    J'essai de comprendre comment lire un fichier et me déplacer dans celui-ci afin de récupérer des données.
    Je voudrai utiliser la fonction fseek() afin de gérer mes déplacement, mais je bloque sur un voir plusieurs point(s).
    Mon fichier à la structure suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    AAABBBBBBCCDD\n
    AAABBBBBBCCDD\n
    Je lis le fichier via ce code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    pf = fopen(p,"rb");    
    if (pf!=NULL) {    
      while (fgets(record,sizeof record,pf) !=NULL) {
              /* traitements */
            }
    }
    Connaisant la structure du fichier, je fesais des subtring du record afin de stocker les differentes données d'un enregistrement dans une structure.
    Je pense que je pourrais me passer d'une fonction réalisant les substring en utilisant fseek().
    J'ai trouvé le prototype de fseek()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    int fseek ( FILE * stream, long int offset, int origin );
    Ce que je ne comprend pas c'est comment faire pour lire ma variable record à l'aide de fseek(), ou mon fichier. J'ai lu et relu des tutaux et exemples mais c'est toujours avec un seul enregistrement.
    Quelle est la technique lorsque le fichier à n enregistrements ?
    Comment récupérer ce qui est lu par fseek() ?
    Qu'est ce que j'ai loupé ?

    Merci
    S'il n'y a pas de solution c'est qu'il n'y a pas de problème.

  2. #2
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Il semblerait que ton fichier soit un fichier texte (fgets) et je ne comprend pas pourquoi tu l'ouvres en mode binaire (fopen(p,"rb"))
    Si c'est effectivement une lecture de fichier texte, l'utilisation de fseek() est à éviter car très restreinte dans ses possibilités.

    Comment récupérer ce qui est lu par fseek() ?
    fseek() ne lit rien, il détermine la position d'accès dans le fichier. La lecture sera faite ensuite à partir de cette position par une fonction de lecture standard.

    Quelle est la technique lorsque le fichier à n enregistrements ?
    Tout dépend de la nature, du format,... des enregistrements et de ce qu'on veut en faire. Il faudrait en savoir plus sur leur structure.
    Qu'est-ce qu'il y a dans le fichier ? Que veux-tu en faire ?
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  3. #3
    Membre averti Avatar de SPACHFR
    Profil pro
    Paaaaaa
    Inscrit en
    Février 2004
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paaaaaa

    Informations forums :
    Inscription : Février 2004
    Messages : 557
    Points : 400
    Points
    400
    Par défaut
    En fait le fichier est au format text.
    L'ojectif est de recupérer l'ensemble des enregistrements puis de découper chaqu'un d'entre eux afin d'alimenter une liste chainée.
    ex.
    fichier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    AAAABBBBBCCDD\n
    AAAABBBBBCCDD\n
    la Liste chainée
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    typedef struct CPC sCPC;         
    struct CPC {                     
      char status[TCPC_STATUS+1];    
      char id[TCPC_ID+1];            
      char name[TCPC_NAME+1];        
      char family[TCPC_FAMILY+1];    
      char model[TCPC_MODEL+1];      
      char capacity[TCPC_CAPACITY+1];
      char cp[TCPC_PROCESSOR+1];     
      struct CPC *pnext;             
    };                               
    typedef sCPC *ListCPC;
    J'arrive déjà à réaliser ce que je veux, mais je pensais quand utilisant fseek(), cela m'aurait éviter de faire appel à une fonction de substring afin de découper chaque enregistrement.
    Car actuellement je fais comme cela:
    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
     
    pf = fopen(p,"rb");                       /*     open fichier cpc */
    if (pf!=NULL) {                           /*              open OK */
      while (fgets(record,sizeof record,pf) !=NULL) {                   
        status   = substr(record,PCPC_STATUS,TCPC_STATUS);              
        cpcid    = substr(record,PCPC_ID,TCPC_ID);                      
        cpcname  = substr(record,PCPC_NAME,TCPC_NAME);                  
        family   = substr(record,PCPC_FAMILY,TCPC_FAMILY);              
        model    = substr(record,PCPC_MODEL,TCPC_MODEL);                
        capacity = substr(record,PCPC_CAPACITY,TCPC_CAPACITY);          
        cp       = substr(record,PCPC_PROCESSOR,TCPC_PROCESSOR);        
        List = AddCPC(List,status,cpcid,cpcname,family,model,           
                      capacity,cp);                                     
        memset(record,'\0',sizeof(record));   /*        init memoire  */
      }                                       /*                      */
    }                                         /*                      */
    L'objectif est de déclarer via des "#define" la structure du fichier (longueur et positions. Ce que j'ai fais pour mes subtring) et ensuite pour chaque enregistrement accèder via fseek() à la donnée voulue.
    Je pense que ce serait plus éfficace et moins consommateur.
    S'il n'y a pas de solution c'est qu'il n'y a pas de problème.

  4. #4
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    mais la fonction substr() peut être extrèmement simple, alors que l'utilisation de fseek() sur un fichier texte, bien utilisée, va complexifié le code.

    Là où je verrais plutôt à gagner, c'est en changeant l'endroit où le code est placé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    pf = fopen(p,"r");                       /*     open fichier cpc */
    if (pf!=NULL) {                           /*              open OK */
      while (fgets(record,sizeof record,pf) !=NULL) {                   
        status   = substr(record,PCPC_STATUS,TCPC_STATUS);  
    ....     
        List = AddCPC(List,status,cpcid,cpcname,family,model,           
                      capacity,cp);                                     
       //  memset(record,'\0',sizeof(record));   inutile
      }                                     
    }
    Je suppose, d'après ce code, que substr() fait de l'allocation dynamique pour status (qui fait le free() ?), puis copie la chaine adéquate dans le tableau alloué. Le tout est transmis à AddCPC. La fonction doit recopier status dans le champ de la structure (allouée sans doute dans la fonction) et sans doute faire le free() de status.

    - Pourquoi ne pas copier directement dans le bon champ (ce qui permet d'éviter des allocations/free/copie et simplifierait les fonctions substr() et AddCPC()) ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    while (fgets(record,sizeof record,pf) !=NULL)
        List = AddCPC(List,record);
     
    // et dans la fonction AddCPC, si x pointe la structure allouée
    substr(x->status, record, PCPC_STATUS, TCPC_STATUS);
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  5. #5
    Membre averti Avatar de SPACHFR
    Profil pro
    Paaaaaa
    Inscrit en
    Février 2004
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paaaaaa

    Informations forums :
    Inscription : Février 2004
    Messages : 557
    Points : 400
    Points
    400
    Par défaut
    "Je suppose, d'après ce code, que substr() fait de l'allocation dynamique "
    Exact.

    "Pourquoi ne pas copier directement dans le bon champ (ce qui permet d'éviter des allocations/free/copie et simplifierait les fonctions substr() et AddCPC()) ?
    "

    La solution et très bonne
    Vendue...

    Merci pour cette suggestion.

    Cependant cela veut-il dire que l'utilisation de fseek() est uniquement utile pour le cas de fichiers binaire.
    Et dans le cas d'un fichier ouvert en binaire comment et vue le contenu de celui-ci ?
    Comme un seul et unique enregistrement ?
    S'il n'y a pas de solution c'est qu'il n'y a pas de problème.

  6. #6
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    Cependant cela veut-il dire que l'utilisation de fseek() est uniquement utile pour le cas de fichiers binaire.
    Non, mais son utilisation est très contrainte dans le cas de fichiers texte ce qui le rend difficilement utilisable. De plus, la structure interne du fichier étant considérée par l'utilisateur comme une suite de lignes, les fonctions d'accès ligne par ligne sont naturelles dans ce cas.
    Pour info, pour un fichier texte, il faut que l'origine soit SEEK_SET et le déplacement 0 ou une valeur précédemment retournée par ftell()

    Et dans le cas d'un fichier ouvert en binaire comment et vue le contenu de celui-ci ?
    Comme un seul et unique enregistrement ?
    En fait la structure matérielle du fichier est toujours une suite de bytes. C'est l'utilisateur qui lui donne une structure logique.

    Par contre, le traitement de lecture/écriture est différent dans le cas d'un fichier binaire et dans celui d'un fichier texte.
    Dans le second cas, le codage de la fin de ligne sur le fichier dépend du sytème d'exploitation et les fonctions de lecture transforment ce codage en '\n' et celles d'écriture transforment '\n' en le codage "fin de ligne" sur le fichier.
    Dans le cas d'un fichier binaire, le transfert est direct sans modifications et ce pour tous les bytes.
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  7. #7
    Membre averti Avatar de SPACHFR
    Profil pro
    Paaaaaa
    Inscrit en
    Février 2004
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paaaaaa

    Informations forums :
    Inscription : Février 2004
    Messages : 557
    Points : 400
    Points
    400
    Par défaut
    Donc si j'ai bien compris......
    Dans le cas d'un fichier binaire, la lecture totale de celui-ci pourrait ce faire de la façon suivante :
    TCPC_AA représentant la longueur de la donnée voulue.
    TCPC_BB représentant la longueur de la donnée voulue.

    format du fichier :
    [code]
    AABB
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    pf = fopen(p,"r");                       /*     open fichier cpc */
    if (pf!=NULL) {  
    fseek ( pf , TCPC_AA , SEEK_SET );
    fseek ( pf , TCPC_BB , SEEK_CUR );
    }
    Pas besoin de boucler sur les enregistrements et pas besoin de délimiteur type '\n', le pointeur pf est suffisant, il suffit de se deplacer à l'aide de fseek et ftell() jusqu'a la fin du contenu pointé par pf ?
    S'il n'y a pas de solution c'est qu'il n'y a pas de problème.

  8. #8
    Expert éminent sénior
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Points : 13 926
    Points
    13 926
    Par défaut
    - L'ouverture devrait être alors en "rb"
    - Si je comprend bien, tu évoques le cas où le fichier n'est plus un fichier texte (donc n'est plus structuré en lignes : absence de(s) caractère(s) de fin de ligne) mais une liste de bytes (accessoirement des caractères)
    Publication : Concepts en C

    Mon avatar : Glenn Gould

    --------------------------------------------------------------------------
    Une réponse vous a été utile ? Remerciez son auteur en cliquant le pouce vert !

  9. #9
    Membre averti Avatar de SPACHFR
    Profil pro
    Paaaaaa
    Inscrit en
    Février 2004
    Messages
    557
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Paaaaaa

    Informations forums :
    Inscription : Février 2004
    Messages : 557
    Points : 400
    Points
    400
    Par défaut
    Oui c'est exactement ça
    (désole pour le "rb")
    S'il n'y a pas de solution c'est qu'il n'y a pas de problème.

Discussions similaires

  1. Compréhension de fseek
    Par Argonz dans le forum C
    Réponses: 9
    Dernier message: 12/01/2004, 15h01
  2. [FLASH MX] Prob de compréhension des bouttons
    Par WriteLN dans le forum Flash
    Réponses: 13
    Dernier message: 16/10/2003, 17h01
  3. onclipevent (problème de compréhension)
    Par stephane eyskens dans le forum Flash
    Réponses: 8
    Dernier message: 24/09/2003, 15h09
  4. Problème de compréhension des ensembles
    Par Cornell dans le forum Langage
    Réponses: 6
    Dernier message: 07/02/2003, 22h07
  5. Probleme avec fseek
    Par Bjorn dans le forum C
    Réponses: 5
    Dernier message: 04/08/2002, 07h17

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