Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
971 connectés 

  FORUM HardWare.fr
  Programmation
  C

  récuperer un caractère dans un fichier avec read

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

récuperer un caractère dans un fichier avec read

n°2165345
Benh_31
Posté le 24-11-2012 à 18:16:40  profilanswer
 

Bonjour à tous,
 
alors voila j'ai fais une fonction permettant de renvoyer la première ligne d'un fichier.
Le problème c'est que dès la ligne 10, quand j'essaie d'afficher le caractère lu dans la variable courant, ben ça marche pas ^^
quelqu'un saurait m'expliquer ?  
 

Code :
  1. char* read_line(int fd)
  2. {
  3.         int i=0;
  4.         char *line;
  5.         char courant;
  6.         line=malloc(sizeof(char*));
  7.         read(fd,&courant,1);
  8.        
  9.         printf("%c\n",courant);
  10.         while(courant!='\n')
  11.         {
  12.                 line[i]=courant;
  13.                 i++;
  14.                 realloc(line,(1+i)*sizeof(char*));
  15.                 read(fd,&courant,1);
  16.         }
  17.         line[i]='\0';
  18.         return line;
  19. }


 
avec son main :  
 

Code :
  1. int main()
  2. {
  3.         int f=open("ff",O_WRONLY | O_CREAT, 0644);
  4.         printf("%s",read_line(f));
  5. return 0;
  6. }


 
le fichier ff contient bien des caractères, des retours à la ligne...
 
 
merci d'avance :)

mood
Publicité
Posté le 24-11-2012 à 18:16:40  profilanswer
 

n°2165346
Farian
Posté le 24-11-2012 à 18:39:18  profilanswer
 

Bonjour !
Vous ouvrez le fichier en mode "write only" (O_WRONLY), en demandant au système de le créer si nécessaire, ce qui n'est pas des plus astucieux pour lire le contenu du fichier ! :)
 
Vous devriez tenter :
 
int f = open("ff", O_RDONLY);
 
Puis tester (éventuellement dans la fonction "read_line" qui pourrait dans ce cas-là renvoyer NULL), que f n'est pas égal à -1 (que le fichier a donc bien été ouvert).
 
Par ailleurs, votre gestion de la mémoire comporte plusieurs erreurs :  
   * ligne 6 : line = (char *) malloc (sizeof(char)); [Note : la norme impose sizeof(char) = 1, donc on peut ne pas le préciser, mais ce n'est pas une faute de le mettre], car vous voulez stocker dans line 1 caractère, pas un pointeur sur un caractère.
   * ligne 16 : line = (char *)realloc(line, (1+i)*sizeof(char));
   * Au vu des faibles tailles de mémoire qui sont demandées, les fonctions malloc et realloc se déroulement correctement, mais, en théorie, vous devriez tester qu'elles ne renvoient pas NULL, ce qui indiquerait que la mémoire demandée ne peut être allouée.
 
De plus, vous ne vérifiez pas que la fonction read se déroule correctement (code de retour = nombre d'octets lus, soit 1 dans le cas présent).
 
Pour terminer, n'oubliez pas de libérer la mémoire allouée par la fonction "read_line"
 
Bonne continuation à vous !

Message cité 1 fois
Message édité par Farian le 24-11-2012 à 18:47:38
n°2165347
Benh_31
Posté le 24-11-2012 à 18:49:38  profilanswer
 

Farian a écrit :

Bonjour !
Vous ouvrez le fichier en mode "write only" (O_WRONLY), en demandant au système de le créer si nécessaire, ce qui n'est pas des plus astucieux pour lire le contenu du fichier !
 
Vous devriez tenter :
 
int f = open("ff", O_RDONLY);
 
Puis tester (éventuellement dans la fonction "read_line" qui pourrait dans ce cas-là renvoyer NULL), que f n'est pas égal à -1 (que le fichier a donc bien été ouvert).
 
Par ailleurs, votre gestion de la mémoire comporte plusieurs erreurs :  
   * ligne 6 : line = (char *) malloc (sizeof(char)); [Note : la norme impose sizeof(char) = 1, donc on peut ne pas le préciser, mais ce n'est pas une faute de le mettre], car vous voulez stocker dans line 1 caractère, pas un pointeur sur un caractère,
   * ligne 16 : line = (char *)realloc(line, (1+i)*sizeof(char)); (Idem)
 
De plus, vous ne vérifiez pas que la fonction read se déroule correctement (code de retour = nombre d'octets lus, soit 1 dans le cas présent).
 
Bonne continuation à vous !


 
 
Merci pour votre réponse, par contre, à l’exécution :

Code :
  1. printf("%c\n",courant);

n'affiche pas le bon caractère qui est sensé se trouver dans mon fichier mais un autre
 
et puis juste après l'avoir affiché, l’exécution plante même après vos modifications :/

n°2165348
Farian
Posté le 24-11-2012 à 18:54:38  profilanswer
 

Re-bonjour !
 
Comme je le dis souvent : "CMCM" ! (Chez Moi, Ça Marche :) ), et valgrind ne trouve rien à redire lors de l'exécution ...
 
Il doit y avoir une autre petite erreur dans votre code, postez-le, cela ne doit pas être grand chose.


Message édité par Farian le 24-11-2012 à 18:56:52
n°2165349
Benh_31
Posté le 24-11-2012 à 19:00:51  profilanswer
 

Je suis trop bête !!!!! j'avais oublié de mettre mon fichier dans le même dossier que mon main ^^  
 
problème résolu :) merci encore


Message édité par Benh_31 le 24-11-2012 à 19:14:21
n°2165351
Farian
Posté le 24-11-2012 à 19:15:21  profilanswer
 

Je ne vois pas de faute, si ce n'est que j'aurais remplacé le code "if (errno)" par "if (f < 0)", qui est quand même plus propre, mais qui doit revenir au même ...
 
Chez moi, votre code s'exécute sans problème (valgrind ok)
 
Que ce soit sous windows ne devrait, en théorie, pas poser de problème ... la seule chose que je vois est que si votre fichier ne contient qu'une seule ligne et donc pas de retour chariot, le comportement sera sans doute étrange ...)
 
Ma version du code, qui ajoute simplement la gestion du code de retour de la fonction "read" :  
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. char* read_line(int fd)
  8. {
  9.     if (fd < 0)
  10.     {
  11.         return NULL;
  12.     }
  13.    
  14.     int i=0;
  15.     char *line;
  16.     char courant;
  17.     line=(char *)malloc(sizeof(char*));
  18.     int res = read(fd,&courant,1);
  19.     if (res == 1)
  20.     {
  21. //      printf("%c\n",courant);
  22.         while(courant!='\n' && res == 1)
  23.         {
  24.             line[i]=courant;
  25.                 i++;
  26.                 line = (char *)realloc(line,(1+i)*sizeof(char*));
  27.                 res = read(fd,&courant,1);
  28.         } 
  29.     }
  30.     line[i]='\0';
  31.     return line;
  32. }
  33. int main()
  34. {
  35.     int f=open("ff",O_RDONLY, 0644);
  36.     char *retour = read_line(f);
  37.     if (retour != NULL)
  38.     {
  39.         printf("%s\n",retour);
  40.         free(retour);
  41.     }
  42.     return 0;
  43. }

n°2165352
Farian
Posté le 24-11-2012 à 19:16:06  profilanswer
 

Hé hé ! J'étais trop occupé à mettre en forme ma version du code et j'avais raté votre dernier message :)
 
Tout est bien qui finit bien, donc !  
 
Bonne continuation à vous !

n°2165386
Benh_31
Posté le 25-11-2012 à 00:32:34  profilanswer
 

j'ai toujours un problème :( j'arrive bien à récupérer ma ligne, mais après mon return line; je récupère NULL :/ je comprends pas...

n°2165391
Farian
Posté le 25-11-2012 à 09:19:22  profilanswer
 

Précisez votre problème ...  
 
Le code que j'ai posté, moyennant quelques petites adaptations, cf. ci-dessous, fonctionne correctement, pour plusieurs lignes :  
 

Code :
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <sys/types.h>
  5. #include <sys/stat.h>
  6. #include <fcntl.h>
  7. char* read_line(int fd)
  8. {
  9.     if (fd < 0)
  10.     {
  11.             return NULL;
  12.     }
  13.     int i=0;
  14.     char *line = NULL;
  15.     char courant;
  16.     int res = read(fd,&courant,1);
  17.     if (res == 1)
  18.     {
  19.         line=(char *)malloc(sizeof(char*));
  20.         while(courant!='\n' && res == 1)
  21.         {
  22.             line[i]=courant;
  23.             i++;
  24.             line = (char *)realloc(line,(1+i)*sizeof(char*));
  25.             res = read(fd,&courant,1);
  26.         }
  27.         line[i]='\0';
  28.     }
  29.     return line;
  30. }
  31. int main()
  32. {
  33.     int f=open("ff",O_RDONLY, 0644);
  34.     char *retour;
  35.     int numeroLigne = 1;
  36.     while ((retour  = read_line(f)) != NULL)
  37.     {
  38.         printf("Ligne %d : %s\n", numeroLigne, retour);
  39.         free(retour);
  40.         numeroLigne++;
  41.     }
  42.     return 0;
  43. }

Message cité 2 fois
Message édité par Farian le 25-11-2012 à 09:22:21
n°2165397
Benh_31
Posté le 25-11-2012 à 12:10:01  profilanswer
 

je viens de reregarder mon code et j'avais oublié de faire un free, maintenant ça marche ( pour de bon cette fois ^^ )
 
merci encore :)

mood
Publicité
Posté le 25-11-2012 à 12:10:01  profilanswer
 

n°2165401
Sve@r
Posté le 25-11-2012 à 12:38:32  profilanswer
 

Farian a écrit :

Le code que j'ai posté, moyennant quelques petites adaptations, cf. ci-dessous, fonctionne correctement, pour plusieurs lignes


Bonjour
Oui il fonctionne. Mais faire des realloc de 1 en 1 c'est pas super super optimisé vitesse. De plus, mettre le mode 0644 dans open() ne se justifie que si le fichier est créé donc si on passe le flag "O_CREATE" (ce qui s'adapte mal avec le flag O_RDONLY)
Et tant qu'à mettre un mode, autant utiliser les constantes appropriées S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH...

Message cité 1 fois
Message édité par Sve@r le 25-11-2012 à 12:43:07

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°2165414
Benh_31
Posté le 25-11-2012 à 17:55:23  profilanswer
 

Sve@r a écrit :


Bonjour
Oui il fonctionne. Mais faire des realloc de 1 en 1 c'est pas super super optimisé vitesse. De plus, mettre le mode 0644 dans open() ne se justifie que si le fichier est créé donc si on passe le flag "O_CREATE" (ce qui s'adapte mal avec le flag O_RDONLY)
Et tant qu'à mettre un mode, autant utiliser les constantes appropriées S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH...


 
 
Pour le realloc de 1 en 1 c'est ce qui m'est demandé : ça permet de pas avoir de problèmes si la chaine dépasse le buffer et aussi de pas gaspiller de l'espace pour rien.

n°2165426
Sve@r
Posté le 25-11-2012 à 22:35:30  profilanswer
 

Benh_31 a écrit :

Pour le realloc de 1 en 1 c'est ce qui m'est demandé : ça permet de pas avoir de problèmes si la chaine dépasse le buffer et aussi de pas gaspiller de l'espace pour rien.


Il est bien évident qu'il faut réallouer pour éviter un dépassement. Mais de 1 en 1...
En fait, le gaspillage d'espace est bien évidemment un problème à prendre en compte mais c'est là qu'on peut faire des compromis entre ce problème et les autres. Par exemple allouer de 100 en 100 permettra une certaine souplesse (surtout qu'on lit une ligne et que les lignes de plus de 100 caractères ne sont pas courantes) et le gaspillage n'est pas énorme.
 
Bien entendu s'il est demandé spécifiquement une allocation de 1 en 1 tu le fais mais rien ne t'empêche d'aller au-delà de ce qui est demandé. Par exemple la taille d'allocation pourrait être une macro ce qui permettrait à ton code d'évoluer facilement si besoin était. C'est ce qu'on nomme "évolutivité"...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
n°2165527
Benh_31
Posté le 26-11-2012 à 19:07:36  profilanswer
 

c'est sur je suis tout à fait d'accord avec toi, dans mon cas c'est ce qui m'est demandé :)

n°2165549
gilou
Modérateur
Modzilla
Posté le 26-11-2012 à 22:50:37  profilanswer
 

Farian a écrit :

Précisez votre problème ...

 

Le code que j'ai posté, moyennant quelques petites adaptations, cf. ci-dessous, fonctionne correctement, pour plusieurs lignes :

 


 

Il marche, mais il n'est néanmoins pas parfait: c'est malloc(sizeof(char)) que l'on devrait avoir, et non malloc(sizeof(char*)) et idem pour le réalloc.

 

A+,


Message édité par gilou le 26-11-2012 à 22:51:01

---------------
There's more than what can be linked! --    Iyashikei Anime Forever!    --  AngularJS c'est un framework d'engulé!  --

Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  C

  récuperer un caractère dans un fichier avec read

 

Sujets relatifs
Déclenchement Macro à l'ouverture du fichierlecture d'un istringstream , recuperer l'erreur
Récupérer une URL en PHP contenue dans une pageenvoi direct de fichier postcript a une imprimante reseau sans drivers
Accès fichier sur réseau local netbiosRécupérer index des éléments différents de 0
executer un JDK avec un fichier .batRemplacer une partie de texte par une autre dans un fichier texte
Uploader un fichier dans tous les dossiers de mon ftp ?Recupérer le code lang locale iso 639 (fr_FR) avec std::locale
Plus de sujets relatifs à : récuperer un caractère dans un fichier avec read


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR