Partage
  • Partager sur Facebook
  • Partager sur Twitter

C - getnextline

Sujet résolu
    20 octobre 2019 à 21:35:22

    #include <unistd.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define BUFF_SIZE 10
    
    size_t  findN(char **s1)
    {
            size_t  size = strlen(*s1);
            size_t  i;
    
            for (i = 0; i < size; i++)
            {
                    if ((*s1)[i] == '\n')
                    {
                            (*s1)[i] = '\0';
                            return (i+1);
                    }
            }
            return (0);
    }
    
    int     get_next_line(int const fd, char **line)
    {
            char buf[BUFF_SIZE + 1] = {0};
            char *bufcopy;
            char *strfn;
            char *strtmp;
            if (fd < 0)
                    return (-1);
    
            int boucle = 0;
            if (!*line)
                    *line = strdup("");
            strfn = strdup("");
            bufcopy = strdup("");
            while (boucle == 0)
            {
                    read(fd, buf, BUFF_SIZE);
                    strcat(bufcopy, buf);
                    if (strchr(bufcopy, '\n'))
                    {
                            strfn = malloc(BUFF_SIZE);
                            strcpy(strfn, buf);
                            size_t pos = findN(&strfn);
                            *line = strdup(strfn);
                            for (size_t i = 0; pos < strlen(buf); i++)
                            {
                                    bufcopy[i] = buf[pos];
                                    pos++;
                            }
                            boucle++;
                    }
    
            }
            return 0;
    }

    Bonjour, comme vous pouvez le voir j'ai quelque probleme avec mon getnextline. Au fait rien va ..
    Avec un fichier test comme ça: 'test\ntest2\ntest3\n'
    Le programme me renvoie seulement test si BUFF SIZE est superieur aux nombres de caracteres lu dans la premiere ligne.
    Si BUFF SIZE est egal à 1 par exemple, le programme me renvoie rien si c'n'est une string vide.
    Si quelqu'un pourrait m'eclairer svp, j'ai vraiment du mal là..
    Merci !
    • Partager sur Facebook
    • Partager sur Twitter
      21 octobre 2019 à 8:41:28

      En effet, avec 4 chaines de caractères

      char buf[BUFF_SIZE + 1] = {0};
      char *bufcopy;
      char *strfn;
      char *strtmp;

      avec des noms aussi peu parlants, une vache n'y retrouverait pas ses veaux.

      Premier point, tu devrais expliquer ce que ta fonction est censée faire exactement. 

      Le char ** line  laisse penser qu'on l'appelle avec l'adresse d'un pointeur de caractères. Ce pointeur est-il supposé être initialisé, ou pas ?

      PS : il me semble que quand on lit "par blocs" dans un fichier, la lecture ne s'arrête pas (contrairement à la console) forcément sur le délimiteur de fin de ligne.

      PS2: De la manière dont tu t'y prends, avec deux appels consécutifs à get_next_line, tu risques de perdre de données. Il faut conserver ce qui a été lu mais pas encore retourné comme réponse, avec un buffer statique ça devrait être possible d'éviter ça.

      -
      Edité par michelbillaud 21 octobre 2019 à 8:54:02

      • Partager sur Facebook
      • Partager sur Twitter
        23 octobre 2019 à 21:26:15

        Merci d'avoir répondu.

        J'ai essayé de tout reprendre à 0 mais, étrangement *line vaut NULL, pourquoi ?

        int     get_next_line(int const fd, char **line)
        {
                char buf[BUFF_SIZE];
                static char *bufjoin;
                char *tmp;
                char *endl;
        
                int ret = 1;
                while (ret > 0)
                {
                        ret = read(fd, buf, BUFF_SIZE);
                        buf[ret] = '\0';
                        if (bufjoin == NULL)
                                bufjoin = ft_strnew(0);
        
                        if (! (endl = ft_strchr(bufjoin, '\n')) )
                        {
                                tmp = ft_strdup(bufjoin);
                                bufjoin = ft_strjoin(tmp, buf);
                        }
                        else
                        {
                                tmp = ft_strdup(bufjoin);
        
                                bufjoin = ft_strsub(tmp, endl - bufjoin, ft_strlen(tmp));
                                *line = ft_strsub(tmp, 0, endl - bufjoin);
                                return 1;
                        }
                }
                *line = bufjoin;
                return 0;
        }


        Merci encore !

        (les fonctions ft_* sont toutes conformes)

        • Partager sur Facebook
        • Partager sur Twitter
          24 octobre 2019 à 18:38:29

          Et pourquoi ne vaudrait-il pas NULL?
          • Partager sur Facebook
          • Partager sur Twitter
            25 octobre 2019 à 19:06:56

            michelbillaud a écrit:

            Et pourquoi ne vaudrait-il pas NULL?


            Avec un printf en dessous cette ligne, *line contient bien la string alors pourquoi pas au retour de la fonction ?
            *line = ft_strsub(tmp, 0, endl - bufjoin);
            • Partager sur Facebook
            • Partager sur Twitter
              25 octobre 2019 à 20:58:01

              Parce que

                 *line = bufjoin;
                  return 0;
              

              avec bufjoin qui est resté à 0 ?





              -
              Edité par michelbillaud 25 octobre 2019 à 21:00:43

              • Partager sur Facebook
              • Partager sur Twitter
                25 octobre 2019 à 22:52:58

                michelbillaud a écrit:

                Parce que

                   *line = bufjoin;
                    return 0;
                

                avec bufjoin qui est resté à 0 ?

                Je veux bien mais de ce cas, encore une fois, pourquoi *line vaut NULL ?
                int     get_next_line(int const fd, char **line)
                {
                        char buf[BUFF_SIZE];
                        static char *bufjoin;
                        char *endl;
                
                        int ret = 1;
                        if (!bufjoin && !(bufjoin = ft_strnew(BUFF_SIZE)))
                                return -1;
                        while (ret > 0)
                        {
                                if ( (ret = read(fd, buf, BUFF_SIZE) ) < 0)
                                        return -1;
                                buf[ret] = '\0';
                                endl = ft_strchr(bufjoin, '\n');
                                bufjoin = ft_strjoin(bufjoin, buf);
                                if (endl)
                                {
                                        *line = ft_strndup(bufjoin, endl - bufjoin);
                                        bufjoin = endl + 1;
                                        return 1;
                                }
                                if (ret == 0 && bufjoin[0] != '\0')
                                {
                                        *line = ft_strndup(bufjoin, endl - bufjoin);
                                        bufjoin = endl + 1;
                                        return 1;
                                }
                        }
                        return 0;
                }
                • Partager sur Facebook
                • Partager sur Twitter
                  25 octobre 2019 à 23:07:15

                  Ou à cause du return -1.

                  Il y a 5 return dans ton code. Je n'ai pas d'opposition de principe à l'usage à la présence de plusieurs return dans une même fonction, mais là  il y a trop de fils d'exécution possibles  pour que j'aie envie d'analyser ce qui peut se passer,.

                  D'autant qu'il n'y a pas un poil de commentaire pour expliquer. Et que tu ne donnes pas un exemple précis d'anomalie.

                  -
                  Edité par michelbillaud 25 octobre 2019 à 23:12:48

                  • Partager sur Facebook
                  • Partager sur Twitter
                    25 octobre 2019 à 23:16:08

                    Aucun rapport.. l'exemple précis avec un fichier test qui contient seulement trois lignes, la fonction me tourne NULL.
                    • Partager sur Facebook
                    • Partager sur Twitter
                      26 octobre 2019 à 6:52:59

                      On voit que tu fais de gros efforts pour ne pas montrer tout ton code, au cas où on y trouverait une erreur.

                      Mais bon, puisque tu as le code et que tu sais sûrement utiliser un débugger, alors tu peux mettre un point d'arrêt sur chacun des return, et tu vois ce qui se passe.

                      -
                      Edité par michelbillaud 26 octobre 2019 à 6:56:33

                      • Partager sur Facebook
                      • Partager sur Twitter
                        1 novembre 2019 à 19:09:50

                        Non mais qu'est-ce que tu racontes????Tout l'code est là.. T'es sur de t'y connaitre reellement ??

                        Sinon à part ça, j'ai réussi. J'avais juste attribuer endl avant de mettre qqchose dans bufjoin.

                        • Partager sur Facebook
                        • Partager sur Twitter
                          1 novembre 2019 à 19:13:07

                          Tout le code ? et la fonction main ou plutôt l'appel des fonctions !
                          • Partager sur Facebook
                          • Partager sur Twitter
                            1 novembre 2019 à 19:22:08

                            Ca doit faire 40 ans que j'y connais rien en programmation, et je compte pas arrêter maintenant :-)

                            (Le main et les fonctions ft_)

                            -
                            Edité par michelbillaud 1 novembre 2019 à 19:23:10

                            • Partager sur Facebook
                            • Partager sur Twitter
                              1 novembre 2019 à 19:43:01

                              Quel est le rapport, j'ai pourtant dit que tout était conforme et que l'erreur venait de cette fonction.

                              char    *ft_strnew(size_t size)
                              {
                                      char    *strnew;
                              
                                      if (!(strnew = (char *)ft_memalloc(sizeof(char) * (size + 1))))
                                              return (NULL);
                                      return (strnew);
                              }
                              
                              void    *ft_memalloc(size_t size)
                              {
                                      char    *ptr;
                              
                                      if (!(ptr = (char *)malloc(size)))
                                              return (NULL);
                                      ft_bzero(ptr, size);
                                      return ((void *)ptr);
                              }
                              
                              void    ft_bzero(void *s, size_t n)
                              {
                                      if (n > 0)
                                              ft_memset(s, '\0', n);
                              }
                              
                              char    *ft_strjoin(char const *s1, char const *s2)
                              {
                                      size_t  size_s1;
                                      size_t  size_s2;
                                      char    *strjoin;
                              
                                      size_s1 = ft_strlen(s1);
                                      size_s2 = ft_strlen(s2);
                                      strjoin = (char *)malloc(sizeof(char) * (size_s1 + size_s2 + 1));
                                      if (strjoin == NULL)
                                              return (NULL);
                                      ft_strcpy(strjoin, s1);
                                      ft_strcpy(&strjoin[size_s1], s2);
                                      strjoin[size_s1 + size_s2] = '\0';
                                      return (strjoin);
                              }
                              
                              char    *ft_strchr(const char *s, int c)
                              {
                                      unsigned char   *s1;
                                      unsigned char   c1;
                                      int                             i;
                              
                                      s1 = (unsigned char *)s;
                                      c1 = (unsigned char)c;
                                      i = 0;
                                      if (c1 == '\0')
                                              return ((char *)&s[ft_strlen(s)]);
                                      while (s1[i])
                                      {
                                              if (s1[i] == c1)
                                                      return ((char *)&s[i]);
                                              i++;
                                      }
                                      return (NULL);
                              }
                              
                              static char             *ft_strndup(char const *s1, size_t len)
                              {
                                      char *nstring;
                              
                                      nstring = ft_memalloc(len + 1);
                                      if (!nstring)
                                              return (NULL);
                                      return (ft_memcpy(nstring, s1, len));
                              }
                              
                              void    *ft_memcpy(void *dst, const void *src, size_t n)
                              {
                                      size_t  i;
                                      char    *s1;
                                      char    *s2;
                              
                                      s1 = (char *)dst;
                                      s2 = (char *)src;
                                      i = 0;
                                      while (i < n)
                                      {
                                              s1[i] = s2[i];
                                              i++;
                                      }
                                      return (dst);
                              }
                              
                              int     main(int ac, char **av)
                              {
                                      int fd = open(av[1], O_RDONLY);
                                      char *line;
                              
                                      while (get_next_line(fd, &line) > 0)
                                              printf("%s\n", line);
                                      return (0);
                              }
                              • Partager sur Facebook
                              • Partager sur Twitter
                                1 novembre 2019 à 23:57:28

                                Dans le main, la variable line n'est pas initialisée.

                                Or elle est passée (son adresse) à la fonction get_next_line,  qui teste son contenu ligne 34 du premier message.

                                Mais on dit ça, on n'y connaît rien, en fait.

                                Ps qu'est ce que tu fabriques avec des char* dans ft_memalloc ? Les void*, ils sentent le pâté ?

                                -
                                Edité par michelbillaud 2 novembre 2019 à 0:00:39

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  2 novembre 2019 à 1:45:15

                                  michelbillaud a écrit:

                                  Dans le main, la variable line n'est pas initialisée.

                                  Or elle est passée (son adresse) à la fonction get_next_line,  qui teste son contenu ligne 34 du premier message.

                                  Mais on dit ça, on n'y connaît rien, en fait.

                                  Ps qu'est ce que tu fabriques avec des char* dans ft_memalloc ? Les void*, ils sentent le pâté ?

                                  -
                                  Edité par michelbillaud il y a environ 1 heure

                                  Si la variable *line n'est pas initialisée c'est volontaire. Le 1er date.. et donc le code a forcement evoluer. Et bienvu pour memalloc j'ai pas fait attention.

                                  • Partager sur Facebook
                                  • Partager sur Twitter

                                  C - getnextline

                                  × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                  × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                  • Editeur
                                  • Markdown