Проект: получить следующую строку из файлового дескриптора - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть домашнее задание для школы.Мне нужно создать функцию, которая будет извлекать следующую строку из файлового дескриптора.Единственные функции, которые мне разрешено использовать, это malloc и read (unistd.h), а также все функции из пользовательской библиотеки, которые мне пришлось написать для школы (я опубликую все прототипы).У меня может быть только один заголовок (get_next_line.h) и один исходный файл (get_next_line.c).исходный файл может содержать не более 5 функций (максимум не более 25 строк).Исходный файл должен содержать функцию, которая соответствует этому прототипу

//will return -1 if there's an error, 
//1 if a line has been found 
//and 0 if there is no more to read
int get_next_line(int const fd, char ** line);

У меня может быть только одна статическая переменная внутри функции.У меня должен быть макрос BUFF_SIZE, который определит размер моего буфера.Пока что все работает, кроме одного случая: если я прочитал символы BUFF_SIZE и не нашел символа новой строки, а это последние символы, он возвращает 0. Я не знаю, что изменить, чтобы исправить эту проблему, не создавая другие.Это все функции в моей пользовательской библиотеке (функции части 1 взяты из стандартной библиотеки C. Самая важная часть - это бонусная часть. Она содержит прототипы для моих связанных списков. Моя библиотека была протестирована и она полностью функциональна):

libft.h:

#ifndef LIBFT_H
# define LIBFT_H

# include <stdlib.h>
# include <string.h>
# include <unistd.h>

typedef unsigned char   t_byte;

/*
** PART 1
*/

void                    *ft_memset(void *s, int c, size_t n);
void                    ft_bzero(void *s, size_t n);
void                    *ft_memcpy(void *dest, const void *src, size_t n);
void                    *ft_memccpy(void *dest,
                            const void *src, int c, size_t n);
void                    *ft_memmove(void *dest, const void *src, size_t n);
void                    *ft_memchr(const void *s, int c, size_t n);
int                     ft_memcmp(const void *s1, const void *s2, size_t n);
size_t                  ft_strlen(const char *s);
char                    *ft_strdup(const char *s);
char                    *ft_strcpy(char *dest, const char *src);
char                    *ft_strncpy(char *dest, const char *src, size_t n);
char                    *ft_strcat(char *dest, const char *src);
char                    *ft_strncat(char *dest, const char *src, size_t n);
size_t                  ft_strlcat(char *dst, const char *src, size_t size);
char                    *ft_strchr(const char *s, int c);
char                    *ft_strrchr(const char *s, int c);
char                    *ft_strstr(const char *haystack, const char *needle);
char                    *ft_strnstr(const char *big,
                            const char *little, size_t len);
int                     ft_strcmp(const char *s1, const char *s2);
int                     ft_strncmp(const char *s1, const char *s2, size_t n);
int                     ft_atoi(const char *nptr);
int                     ft_isalpha(int c);
int                     ft_isdigit(int c);
int                     ft_isalnum(int c);
int                     ft_isascii(int c);
int                     ft_isprint(int c);
int                     ft_toupper(int c);
int                     ft_tolower(int c);

/*
** PART 2
*/

void                    *ft_memalloc(size_t size);
void                    ft_memdel(void **ap);
char                    *ft_strnew(size_t size);
void                    ft_strdel(char **as);
void                    ft_strclr(char *s);
void                    ft_striter(char *s, void (*f)(char *));
void                    ft_striteri(char *s, void (*f)(unsigned int, char *));
char                    *ft_strmap(char const *s, char (*f)(char));
char                    *ft_strmapi(char const *s,
                            char (*f)(unsigned int, char));
int                     ft_strequ(char const *s1, char const *s2);
int                     ft_strnequ(char const *s1, char const *s2, size_t n);
char                    *ft_strsub(char const *s,
                            unsigned int start, size_t len);
char                    *ft_strjoin(char const *s1, char const *s2);
char                    *ft_strtrim(char const *s);
char                    **ft_strsplit(char const *s, char c);
char                    *ft_itoa(int n);
void                    ft_putchar(char c);
void                    ft_putstr(char const *s);
void                    ft_putendl(char const *s);
void                    ft_putnbr(int n);
void                    ft_putchar_fd(char c, int fd);
void                    ft_putstr_fd(char const *s, int fd);
void                    ft_putendl_fd(char const *s, int fd);
void                    ft_putnbr_fd(int n, int fd);

/*
** BONUS PART
*/

typedef struct          s_list
{
    void                *content;
    size_t              content_size;
    struct s_list       *next;
}                       t_list;

t_list                  *ft_lstnew(void const *content, size_t content_size);
void                    ft_lstdelone(t_list **alst, void (*del)(void*, size_t));
void                    ft_lstdel(t_list **alst, void (*del)(void *, size_t));
void                    ft_lstadd(t_list **alst, t_list *new);
void                    ft_lstiter(t_list *lst, void (*f)(t_list*elem));
t_list                  *ft_lstmap(t_list *lst, t_list *(*f)(t_list *elem));

/*
** UTILS
*/

void                    ft_lst_push_back(t_list **alst, t_list *elem);

#endif

get_next_line.h:

#ifndef GET_NET_LINE_H
# define BUFF_SIZE 32

# include <unistd.h>
# include <stdlib.h>
# include "libft.h"

typedef struct  s_seeker
{
    int         fd;
    char        buffer[BUFF_SIZE + 1];
    char        *offset;
}               t_seeker;

int             get_next_line(int const fd, char ** line);
t_seeker        *get_seeker(t_list **lst, int fd);
int             get_line(t_seeker *buffer, ssize_t r, char **ln, char **lft);

#endif

get_next_line.c

# include "get_next_line.h"

//will try to find the seeker associated to the file descriptor
//will create a new one if not found
t_seeker            *get_seeker(t_list **lst, int fd)
{
    t_seeker        *seeker;
    t_list          *node;
    t_list          *tmp;

    tmp = *lst;
    while(tmp)
    {
        seeker = (t_seeker*) tmp->content;
        if (seeker->fd == fd)
            return (seeker);
        tmp = tmp->next;
    }
    if ((seeker = malloc(sizeof(t_seeker))) == NULL)
        return (NULL);
    //ft_lstnew will make a copy of seeker that's why i free it afterward
    node = ft_lstnew(seeker, sizeof(t_seeker));
    free(seeker);
    if (node == NULL)
        return (NULL);
    seeker = node->content;
    seeker->fd = fd;
    ft_bzero(seeker->buffer, BUFF_SIZE + 1);
    seeker->offset = seeker->buffer;
    ft_lstadd(lst, node);
    return ((t_seeker*) node->content);
}

// fd : our file descriptor
// line : is poining to the pointer that should point to the next line (if there is)
int                 get_next_line(int const fd, char ** line)
{
    static t_list   *lst;
    t_seeker        *seeker;
    ssize_t         r;
    char            *lft;
    int             sgn;

    if (!line || fd <= -1 || (seeker = get_seeker(&lst, fd)) == NULL)
        return(-1);
    lft = NULL;
    if ((sgn = get_line(seeker, ft_strlen(seeker->buffer), line, &lft)) == 1 
        || sgn == -1)
            return (sgn);
    while((r = read(fd, seeker->buffer, BUFF_SIZE)) > 0) 
    {
        seeker->buffer[r] = '\0';
        if ((sgn = get_line(seeker, r, line, &lft)) != 0)
            return (sgn);
        if ((size_t)r < BUFF_SIZE)
            return (1);
    }
    if (r < 0)
        return (-1);
    return (0);
}

// seeker : our seeker struct from which we copy the line
// r : how much character have been read and put inside the buffer
// ln : this is the same pointer  as line insinde get_next_line
// lft : i need to keep a copy of what's left from the previous call
int                 get_line(t_seeker *seeker, ssize_t r, char **ln, char **lft)
{
    char            *occ;
    char            *tmp;
    size_t          len;

    // find first occurrence of '\n' starting at the offset
    occ = ft_strchr(seeker->offset, '\n');
    len = occ ? (size_t) (occ - seeker->offset) : (size_t) r;
    //ft_strnew will create a new empty string of the specified size
    tmp = ft_strnew(len + ft_strlen(*lft ? *lft : ""));
    tmp = tmp ? ft_strcat(tmp, *lft ? *lft : "") : tmp;
    tmp = tmp ? ft_strncat(tmp, seeker->offset, len) : tmp;
    *lft ? ft_strdel(lft) : (void) 1;
    *lft = tmp;
    *ln = (occ || (size_t) r < BUFF_SIZE) && tmp ? *lft : *ln;
    // most important part : set the offset
    // either after the newline or at the beginning of our buffer
    seeker->offset = occ ? occ + 1 : seeker->buffer;
    if (!tmp)
        return (-1); 
    return (occ  ? 1 : 0);
}

Я знаю код isn 'это легко читать, но, как я уже говорил, у меня очень ограниченное пространство.Хорошего вечера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...