简体   繁体   English

C中的链表和读取多个文件的问题

[英]Question about linked lists and reading from multiple files in C

Here is a problem I am trying to solve.这是我试图解决的一个问题。 I have a task to create a function, which has to return newline from the file(accessing with fd).我的任务是创建一个 function,它必须从文件中返回换行符(使用 fd 访问)。 It has to use only functions read , malloc , free and the functions I wrote.它只能使用readmallocfree和我写的函数。

I used linked lists to add and save the data from the files.我使用链表来添加和保存文件中的数据。 1 node represents 1 specific file. 1 个节点代表 1 个特定文件。

Please help me find out what is the problem in this case.请帮我找出在这种情况下有什么问题。 It works well in all cases except when BUFFER_SIZE is 1 and we gave him more than 2 file descriptors.它在所有情况下都运行良好,除非BUFFER_SIZE1并且我们给了他超过2 个文件描述符。

In the firs call of get_next_line function it reads well for first 2 file descriptors and returns the line properly.get_next_line function 的第一次调用中,它可以很好地读取前 2 个文件描述符并正确返回该行。 For the 3rd fd it returns 2nd file descriptors data.对于第三个 fd,它返回第二个文件描述符数据。 At the second call it returns 2nd line of each fd(1st and 2nd) and returns 1st line of 3rd file.在第二次调用时,它返回每个 fd(1st 和 2nd) 的第 2 行并返回第 3 个文件的第 1 行。

Here is the way I have to compile my files for using this function.这是我必须编译文件以使用此 function 的方式。

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 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 get_next_line.c


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

    i = 0;
    if (!s)
        return (0);
    while (s[i] != '\0')
        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] = '\0';
    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] = '\0';
        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 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] = '\0';
    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] = '\0';
    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);
}

Here is the behaviour of my test main I used.这是我使用的测试主程序的行为。

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 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

1st call第一次通话

buffer1=t morning; buffer1=t 早上; should have arrived at 6:46, but train w应该在 6 点 46 分到达,但火车 w

buffer2=1.Aasdasndmbc this is 1st line of 2nd file buffer2=1.Aasdasndmbc这是第二个文件的第一行

buffer3=1.Aasdasndmbc this is not what supposed to be in 3rd file buffer3=1.Aasdasndmbc这不是第三个文件中的内容

2nd call第二次通话

buffer1=as anhour late. buffer1=迟到一小时。 Buda-Pesth seems a wonderful place, from the glimpse which Igot of it from the train布达佩斯似乎是一个美妙的地方,从我从火车上得到的一瞥

buffer2=2.Dcccsadkajskldjaskld buffer2=2.Dcccsadkajskldjaskld

buffer3=1.Abc 1st line of 3rd file buffer3=1.Abc第三个文件的第一行

buffer1=and the little I could walk through thestreets. buffer1=还有我可以穿过街道的那一点点。 I feared to go very far from the station, as we had arr我担心 go 离车站很远,因为我们有 arr

buffer2=3.Saksadklasjdlkasjd缓冲区2=3.Saksadklasjdlkasjd

buffer3=2.Dccc缓冲区3=2.Dccc

buffer1=ivedlate and would start as near the correct time as possible. buffer1=ivedlate 并且会在尽可能接近正确的时间开始。 Theimpression I had was that we were leaving the West and entering theEast;我的印象是我们正在离开西方并进入东方。 the most western of splendid bridges over the Danube, which ish多瑙河上最西部的壮丽桥梁

buffer2=4.Sakdljlkasjdlkasjsadlkasjdklasjd buffer2=4.Sakdljlkasjdlkasjsadlkasjdklasjd

buffer3=3.Sak缓冲区3=3.Sak

During debug process I found out my nodes took the previous node's info.在调试过程中,我发现我的节点获取了前一个节点的信息。 I wrote a small check in my get_next_line function.我在我的 get_next_line function 中写了一个小支票。 if(fd > 3 && BUFFER_SIZE == 1) // means this is not the first file to read && the specific case for BUFFER_SIZE tmp->info = NULL; if(fd > 3 && BUFFER_SIZE == 1) // 表示这不是第一个读取的文件 && BUFFER_SIZE tmp->info = NULL 的具体情况; It will not look at the same value as the previous so we can give him another value in our calls.它不会看到与前一个相同的值,因此我们可以在调用中给他另一个值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM