项目:从文件描述符中检索下一行

时间:2018-12-13 02:17:21

标签: c

我有学校功课。我必须创建一个函数,该函数将从文件描述符中检索下一行。我唯一可以使用的功能是malloc,并读取(unistd.h)以及我必须为学校编写的自定义lib中的所有功能(我将发布所有原型)。我只能有一个标头(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标准库。最重要的部分是Bonus部分。它包含我的链表的原型。我的lib已经过测试,并且功能齐全):

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);
}

我知道代码不容易阅读,但是正如我告诉你的,我的空间非常有限。 祝你晚上愉快。

0 个答案:

没有答案