关于链接列表和从 C 中读取多个文件的问题

Question about linked lists and reading from multiple files in C

这是我正在尝试解决的问题。我的任务是创建一个函数,该函数必须 return 从文件换行(使用 fd 访问)。它必须只使用函数 readmallocfree 和我写的函数。

我使用链表从文件中添加和保存数据。 1个节点代表1个特定文件。

请帮我看看这个案例是什么问题。它在所有情况下都运行良好,除非 BUFFER_SIZE1 并且我们给了他超过 2 个文件描述符。

get_next_line 函数的第一次调用中,它读取前 2 个文件描述符并且 return 正确地读取了该行。对于第三个 fd,它 returns 第二个文件描述符数据。在第二次调用它 returns 每个 fd(第一个和第二个)的第二行和 returns 第三个文件的第一行。

这是我必须编译我的文件以使用此功能的方式。

gcc -Wall -Wextra -Werror -D BUFFER_SIZE=1 get_next_line_bonus.c get_next_line_utils_bonus.c get_next_line.h main.c 

./a.out

get_next_line.h

# define GET_NEXT_LINE_H
# include <unistd.h>
# include <stdlib.h>

typedef struct  s_info
{

    int             fd;
    char            *info;
    int             check;
    struct s_info   *next;
}               t_info;

int             get_next_line(int fd, char **line);

t_info          *ft_lstnew(int fd);

char            *get_line(char *str);

int             ncheck(char *str);

unsigned long   ft_strlen(const char *s);

char            *get_save(char *save);

void            *ft_memmove(void *dest, const void *src, size_t len);

char            *ft_strjoin(char const *s1, char const *s2);

t_info          *ft_find(int fd, t_info **start);

int             ft_lstdelone(t_info **start, int fd);

#endif

get_next_line.c


size_t  ft_strlen(const char *s)
{
    int i;

    i = 0;
    if (!s)
        return (0);
    while (s[i] != '[=12=]')
        i++;
    return (i);
}

char    *ft_strjoin(char const *s1, char const *s2)
{
    size_t  s1_len;
    size_t  s2_len;
    size_t  stot_len;
    char    *rtn;

    if (!s1 && !s2)
        return (0);
    s1_len = ft_strlen((char *)s1);
    s2_len = ft_strlen((char *)s2);
    stot_len = s1_len + s2_len + 1;
    rtn = malloc(sizeof(char) * stot_len);
    if (!rtn)
        return (0);
    ft_memmove(rtn, s1, s1_len);
    ft_memmove(rtn + s1_len, s2, s2_len);
    rtn[stot_len - 1] = '[=12=]';
    free((char *)s1);
    return (rtn);
}

t_info  *ft_lstnew(int fd)
{
    t_info  *i;

    if ((i = (t_info*)malloc(sizeof(t_info))) == 0)
        return (0);
    i->fd = fd;
    if ((i->info = malloc(sizeof(char*) * (1 + BUFFER_SIZE))) == 0)
        return (0);
    i->check = 1;
    i->next = NULL;
    return (i);
}

t_info  *ft_find(int fd, t_info **start)
{
    t_info *finder;
    t_info *new;

    finder = *start;
    while (finder)
    {
        if (finder->fd == fd)
            return (finder);
        finder = finder->next;
    }
    if ((new = ft_lstnew(fd)) == 0)
        return (0);
    if (!(*start))
    {
        *start = new;
        return (new);
    }
    new->next = *start;
    *start = new;
    return (new);
}

int     get_next_line(int fd, char **line)
{
    static t_info   *start = NULL;
    t_info          *tmp;
    char            *buff;

    if (fd < 0 || !line || BUFFER_SIZE <= 0 ||
    ((tmp = ft_find(fd, &start)) == 0) ||
    !(buff = malloc(sizeof(char) * (BUFFER_SIZE + 1))))
        return (-1);
    while (!ncheck(tmp->info) && tmp->check != 0)
    {
        if ((tmp->check = read(fd, buff, BUFFER_SIZE)) == -1)
        {
            free(buff);
            return (-1);
        }
        buff[tmp->check] = '[=12=]';
        tmp->info = ft_strjoin(tmp->info, buff);
    }
    free(buff);
    *line = get_line(tmp->info);
    tmp->info = get_save(tmp->info);
    if (tmp->check == 0)
        return (ft_lstdelone(&start, fd));
    return (1);
}

get_next_line_utils.c


char        *get_save(char *save)
{
    char    *rtn;
    int     i;
    int     j;

    i = 0;
    j = 0;
    if (!save)
        return (0);
    while (save[i] && save[i] != '\n')
        i++;
    if (!save[i])
    {
        free(save);
        return (0);
    }
    if (!(rtn = malloc(sizeof(char) * ((ft_strlen(save) - i) + 1))))
        return (0);
    i++;
    while (save[i])
        rtn[j++] = save[i++];
    rtn[j] = '[=13=]';
    free(save);
    return (rtn);
}

char        *get_line(char *str)
{
    int     i;
    char    *rtn;

    i = 0;
    if (!str)
        return (0);
    while (str[i] && str[i] != '\n')
        i++;
    if (!(rtn = malloc(sizeof(char) * (i + 1))))
        return (0);
    i = 0;
    while (str[i] && str[i] != '\n')
    {
        rtn[i] = str[i];
        i++;
    }
    rtn[i] = '[=13=]';
    return (rtn);
}

void        *ft_memmove(void *dst, const void *src, size_t len)
{
    char *d;
    char *s;

    d = (char *)dst;
    s = (char *)src;
    if (dst == src)
        return (dst);
    if (s < d)
    {
        while (len--)
            *(d + len) = *(s + len);
        return (dst);
    }
    while (len--)
        *d++ = *s++;
    return (dst);
}

int         ncheck(char *str)
{
    int i;

    i = 0;
    if (!str)
        return (0);
    while (str[i])
    {
        if (str[i] == '\n')
            return (1);
        i++;
    }
    return (0);
}

int         ft_lstdelone(t_info **start, int fd)
{
    t_info *finder;
    t_info *tmp;

    finder = *start;
    if (finder->fd == fd)
    {
        free(finder->info);
        *start = (*start)->next;
        free(finder);
    }
    else
    {
        while (finder->next->fd != fd && finder->next)
            finder = finder->next;
        free(finder->next->info);
        tmp = finder->next;
        finder->next = tmp->next;
        free(tmp);
    }
    return (0);
}

这是我使用的测试主程序的行为。

c1r6s3% gcc -Wall -Wextra -Werror -D BUFFER_SIZE=1 get_next_line_bonus.c get_next_line_utils_bonus.c get_next_line.h main.c && ./a.out

第一次通话

buffer1=t 早上;本应到达6:46,但火车w

buffer2=1.Aasdasndmbc 这是第二个文件的第一行

buffer3=1.Aasdasndmbc 这不是应该在第三个文件中的内容

第二次通话

buffer1=晚了一个小时。 Buda-Pesth 似乎是个很棒的地方,从我在火车上看到的一瞥

缓冲区 2=2.Dcccsadkajskldjaskld

buffer3=1.Abc 第三个文件的第一行

buffer1=还有我能穿过街道的那一点点。我害怕离车站很远,因为我们已经到达

缓冲区 2=3.Saksadklasjdlkasjd

buffer3=2.Dccc

buffer1=ivedlate 并且会尽可能接近正确的时间开始。我的印象是我们正在离开西方进入东方;多瑙河上最西部的壮丽桥梁,

缓冲区 2=4.Sakdljlkasjdlkasjsadlkasjdklasjd

buffer3=3.Sak

在调试过程中,我发现我的节点获取了前一个节点的信息。 我在 get_next_line 函数中写了一个小支票。 如果(fd > 3 && BUFFER_SIZE == 1) // 表示这不是第一个要读取的文件 && BUFFER_SIZE 的特定情况 tmp->信息=空;它不会查看与之前相同的值,因此我们可以在调用中给他另一个值。