//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);
}
我知道代码不容易阅读,但是正如我告诉你的,我的空间非常有限。 祝你晚上愉快。