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 :

votre avis sur une fonction qui copie un fichier dans un buffer


Sujet :

C

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2008
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 24
    Points : 18
    Points
    18
    Par défaut votre avis sur une fonction qui copie un fichier dans un buffer
    Bonjour

    Voila je suis apres m' entrainer un peu, donc j ai fait un programme qui prend un fichier en argument , puis (dans la fonction ci-dessous) il recopie tout le fichier dans un buffer pour ensuite l afficher, donc pour etre sur de pas avoir de probleme, je realloue le buffer tous le a chaque fois , mais je voudrais savoir ce que vous en pensez, si vous voyez des erreurs ou si il y a mieux et plus simple enfin bref votre avis quoi, pour l instant ca marche tres bien mais j ai quand meme des doute. voila le fichier en question :

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include "header.h"
    #define BUF_SIZE 1024
     
    char *lire_fichier(FILE* fd, char *buffer)
    {
     
    	int taille = BUF_SIZE;
     
    	buffer = malloc(sizeof(char) * BUF_SIZE);
     
    	if(!buffer)
    	{
    		erreur("Allocation de la memoire echoue\n");
    		exit(EXIT_FAILURE);
    	}
     
    	int c, i = 0;	
     
    	while((c = fgetc(fd)) && (c != EOF))
    	{
    			if(c == '\n')
    			{
    				ligne++;
    			}
    			if(caractere >= taille)
    			{
    				buffer = realloc(buffer, taille*2);
    				taille *= 2;
    			}
     
    			buffer[i++] = c;	
     
    			caractere++;		
    	}
     
    	buffer[i++] = '\0';
     
    	return buffer;
    }
    Merrci a vous.

  2. #2
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par julio.t Voir le message
    je voudrais savoir ce que vous en pensez, si vous voyez des erreurs
    Mon compilateur en voit...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
     
    -------------- Build: Debug in hello ---------------
     
    Compiling: main.c
    C:\dev\hello\main.c:3:20: header.h: No such file or directory
    C:\dev\hello\main.c: In function `lire_fichier':
    C:\dev\hello\main.c:15: warning: implicit declaration of function `erreur'
    C:\dev\hello\main.c:25: error: `ligne' undeclared (first use in this function)
    C:\dev\hello\main.c:25: error: (Each undeclared identifier is reported only once
    C:\dev\hello\main.c:25: error: for each function it appears in.)
    C:\dev\hello\main.c:27: error: `caractere' undeclared (first use in this function)
    Process terminated with status 1 (0 minutes, 0 seconds)
    5 errors, 1 warnings
    Le paramètre 'buffer' est inutile. une variable locale suffit.

    'ligne', 'caractere' ne sont pas définis. Poste un code compilable. On ne peut pas deviner ce que tu as fais.

    Eviter ce genre de code obscur...
    préférer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
            buffer[i] = c;
            i++;
    qui est plus clair pour tout le monde.

    La fonction devrait gérer elle-même l'ouverture/fermeture du fichier. C'est beaucoup plus simple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    char *lire_fichier (char const *fname)
    J'ai mis une petite taille
    pour solliciter le realloc(). Explosion !

    ligne (que j'aurais appelé cpt_lignes) ne sert à rien.
    caractere (que j'aurais appelé cpt_caracteres) ne sert à rien. i fait le boulot...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
           while ((c = fgetc (fp)) && (c != EOF))
    Pas clair. Tu penses trouver un 0 dans un fichier texte ?

    Je supose que tu veux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
           while ((c = fgetc (fp)) != EOF)
    Ceci fonctionne :
    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
     
    #include <stdio.h>
    #include <stdlib.h>
     
    char *lire_fichier (char const *fname)
    {
       char *buffer = NULL;
       FILE *fp = fopen (fname, "r");
       if (fp != NULL)
       {
          int taille = 2;
     
          buffer = malloc (taille);
          if (buffer != NULL)
          {
             int c, i = 0;
     
              while ((c = fgetc (fp))!= EOF)
             {
                if (i == taille - 1)
                {
                   buffer = realloc (buffer, taille * 2);
                   taille *= 2;
                }
     
                buffer[i] = c;
                i++;
             }
     
             buffer[i] = '\0';
          }
       }
       else
       {
          perror (fname);
       }
       return buffer;
    }
     
    void test (char const *fname)
    {
       printf ("lecture de '%s'\n", fname);
     
       char *s = lire_fichier (fname);
       if (s != NULL)
       {
          printf ("'%s'\n", s);
          free (s);
       }
    }
     
    int main (void)
    {
       test ("");
       test ("../hello/dico.txt");
       return 0;
    }
    Pas de Wi-Fi à la maison : CPL

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2008
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    oupsss voila.

    main.c

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include "header.h"
     
    extern int ligne;
    extern int caractere;
     
    int main(int argc, char **argv)
    {
    	if(argc != 2)
    	{
    		usage(argv[0]);
    	}
     
    	char *buf;
     
    	FILE* fd;
     
    	if((fd = fopen(argv[1], "r")) == NULL)
    	{
    		erreur("Impossible d' ouvrir le fichier en ecriture");
    	}
     
    	printf("%s", lire_fichier(fd,buf));
    	printf("nombre de ligne :%d \t nombre de caracteres: %d\n\n", ligne, caractere);
     
     
    	fclose(fd);
    	return EXIT_SUCCESS;
    }
    lire_fichier.c :

    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
    #include <stdio.h>
    #include <stdlib.h>
    #include "header.h"
    #define BUF_SIZE 1024
     
     
    int caractere = 0, ligne = 0;
     
    char *lire_fichier(FILE* fd, char *buffer)
    {
     
    	int taille = BUF_SIZE;
     
    	buffer = malloc(sizeof(char) * BUF_SIZE);
     
    	if(!buffer)
    	{
    		erreur("Allocation de la memoire echoue\n");
    		exit(EXIT_SUCCESS);
    	}
     
    	int c, i = 0;	
     
    	while((c = fgetc(fd)) && (c != EOF))
    	{
    			if(c == '\n')
    			{
    				ligne++;
    			}
    			if(caractere >= taille)
    			{
    				buffer = realloc(buffer, taille*2);
    				taille *= 2;
    			}
     
    			buffer[i++] = c;	
     
    			caractere++;		
    	}
     
    	buffer[i++] = '\0';
     
    	return buffer;
    }
    header.h

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #ifndef HEADER_H
    #define HEADER_H
     
    void usage(char *prog_name);
    void erreur(char *chaine);
     
    char *lire_fichier(FILE* fd, char *buffer);
     
    #endif
    fonction.c

    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
    #include <stdio.h>
    #include <stdlib.h>
     
     
    void usage(char *prog_name)
    {
    	fprintf(stderr ,"Usage : %s <fichier> \n", prog_name);
    	exit(EXIT_FAILURE);
    }
     
    void erreur(char *chaine)
    {
    	fprintf(stderr, "%s", chaine);
    	exit(EXIT_FAILURE);
    }
    makefile:
    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
     
    CFLAGS= -g -W -Wall 
    CC=gcc
     
    essai: main.o fonction.o lire_fichier.o
    	$(CC) -o $@ $^
     
    main.o: main.c
    	$(CC) -c $(CFLAGS) $<
     
    fonction.o: fonction.c
    	$(CC) -c $(CFLAGS) $<
     
    lire_fichier.o: lire_fichier.c
    	$(CC) -c $(CFLAGS) $<
     
    clean: 
    	rm -f *.o
    	rm -f essai
    Voila le code complet, j' avais effacer certain truc pour éclaircir ma fonction .

  4. #4
    Expert éminent sénior
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Points : 20 985
    Points
    20 985
    Par défaut
    Citation Envoyé par julio.t Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    extern int ligne;
    extern int caractere;
    Pas besoin de ces globales[1]. J'ai donné une correction. Si tu veux que la fonction compte les caractères et les lignes, il faut ajouter le contexte adéquate : par exemple, un pointeur sur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    struct compteurs
    {
       int caracteres; 
       int lignes;
    };
    -------------------
    [1] de plus, mauvais usage. Comme pour les fonctions, les déclarations se mettent dans des headers...

    http://emmanuel-delahaye.developpez....s.htm#globales
    Pas de Wi-Fi à la maison : CPL

  5. #5
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2008
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    ok merci bien .

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    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 287
    Points : 36 776
    Points
    36 776
    Par défaut
    Ok ca marche mais... pour recopier le contenu du fichier dans un buffer mémoire pourquoi ne pas:
    1. allouer un buffer à la taille du fichier à lire? (fstats)
    2. lire son contenu d'un seul coup (read/fread)?

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Membre à l'essai
    Profil pro
    Inscrit en
    Août 2008
    Messages
    24
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 24
    Points : 18
    Points
    18
    Par défaut
    allouer un buffer à la taille du fichier à lire? (fstats)
    Je pensais justement que la struct stat pourrais me servir mais je ne savais pas comment . merci tu ma éclairé la d' un coup .

    Donc je vais essayer de le refaire pour qu il fasse a peu pres la meme chose :

    Je map le fichier (mmap et donc j aurais besoin de la struct stat) en memoire

    et je lis normalement avec modification possible .

    Merci de ton intervention et merci a Emmanuel Delahaye aussi qui ma bien eclairer.

    je vous donne des nouvelles quand je fini.

  8. #8
    Membre régulier
    Inscrit en
    Mars 2006
    Messages
    117
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 117
    Points : 109
    Points
    109
    Par défaut
    utiliser un buffer de taille 'n', permettrai d'eviter de faire des appels systemes (les plus couteux) pour chaque caractere, et serai donc bcp plus rapide. (read/fread).

    tu peux soit utiliser fstat, mais imaginons que tu veuilles lire la bible en entiere, tu as de forte chance de faire exploser la memoire si tu alloues l'espace entier.

    Enfin ca depend de ce que tu veux faire apres. Imaginons que tu veuilles faire un traitement particulier sur ce fichier apres, il serait plus judicieux de recoder une fonction du type getln(int fd) (fonction qui bufferise, et qui renvoie la prochaine ligne ou NULL sinon).

    c99eusement

  9. #9
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Jue,
    Citation Envoyé par oniric Voir le message
    utiliser un buffer de taille 'n', permettrai d'eviter de faire des appels systemes (les plus couteux) pour chaque caractere, et serai donc bcp plus rapide. (read/fread).

    tu peux soit utiliser fstat, mais imaginons que tu veuilles lire la bible en entiere, tu as de forte chance de faire exploser la memoire si tu alloues l'espace entier.

    Enfin ca depend de ce que tu veux faire apres. Imaginons que tu veuilles faire un traitement particulier sur ce fichier apres, il serait plus judicieux de recoder une fonction du type getln(int fd) (fonction qui bufferise, et qui renvoie la prochaine ligne ou NULL sinon).

    c99eusement
    Il n'est précisé nulle part qu'on travaille avec un fichier texte.
    Si les cons volaient, il ferait nuit à midi.

  10. #10
    Membre régulier
    Inscrit en
    Mars 2006
    Messages
    117
    Détails du profil
    Informations personnelles :
    Âge : 41

    Informations forums :
    Inscription : Mars 2006
    Messages : 117
    Points : 109
    Points
    109
    Par défaut
    non mais je vois qu'il check les '\n' donc si ce n'est pas un fichier texte qu'est ce donc ? un fichier binaire separer par des '\n' ? pas grave, ca marchera quand meme du coup

    trolleusement

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

Discussions similaires

  1. Votre avis sur une proposition de job
    Par plex dans le forum Emploi
    Réponses: 7
    Dernier message: 18/01/2007, 10h11
  2. Votre avis sur une proposition de CDI!
    Par wapit dans le forum Emploi
    Réponses: 13
    Dernier message: 22/07/2005, 13h41
  3. [Programmation distribuée] Votre avis sur une archi
    Par Acarp47 dans le forum Plateformes (Java EE, Jakarta EE, Spring) et Serveurs
    Réponses: 7
    Dernier message: 29/06/2005, 14h01
  4. Votre avis sur une bannière animée developpez.com
    Par Marc Lussac dans le forum Evolutions du club
    Réponses: 14
    Dernier message: 02/02/2005, 07h52

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