使用静态节点读取每个文件描述符1行

时间:2016-11-15 01:40:02

标签: c pointers linked-list file-descriptor

我试图一次读取一行文件,缓冲区长度不同。我将文件desc传递给get_next_line函数并将该行分配给指针。问题是当缓冲区长度很长时,有时它打印文件的其余部分,当我传递2个不同的文件描述符时,我得到一个段错误。我认为这与在节点中保存字符串并在fd相同时查找相同节点有关。 我没有看到我在这里做错了什么。

get_next_line.c

#include "get_next_line.h"
#include <fcntl.h>
#include <stdio.h>

/*
 ** CREATE THE NEXT NODE TO ADD TO THE LINKEDLIST.
 **
 */
t_node *create_node(char *buffer, int fd)
{
    int i;
    t_node *new;

    i = 0;
    while (*buffer != '\n')
        buffer++;
    if (*buffer == EOF)
        return 0;
    ++buffer;
    new = malloc(sizeof(t_node));
    new->fd = fd;
    new->next = NULL;
    new->str = malloc(sizeof(char *));
    while (buffer[i] != '\n')
    {
        new->str[i] = (char)malloc(sizeof(char));
        new->str[i] = buffer[i];
        i++;
    }
    return (new);
}

/*
 ** SEARCH THE LIST FOR FD AND GET THE OVERFLAP STRING FROM
 ** LAST READ.
 */
char *get_overlap(t_node **root, int fd)
{
    t_node *conductor;

    if (*root == NULL)
        return (NULL);

    conductor = *root;
    while (conductor->fd != fd && conductor != 0)
        conductor = conductor->next;
    if (conductor == NULL)
        return (NULL);
    return (conductor->str);
}

/*
 ** CALL THE CREATE NODE FUNCTION AND ADD IT TO THE  LINKEDLIST.
 **
 */
void save_overlap(char buffer[], t_node **root, int fd)
{
    t_node **conductor;
    t_node *new;

    new = create_node(buffer, fd);
    if (*root == NULL)
        *root = new;
    else
    {
        conductor = root;
        while (*conductor != NULL)
        {
            if ((*conductor)->fd == fd)
            {
                (*conductor)->str = new->str;
                break;
            }
            if ((*conductor)->next == NULL)
            {
                (*conductor)->next = new;
                break;
            }
            *conductor = (*conductor)->next;
        }
    }
}

/*
 ** PREPEND THE PREVIOUS OVERLAP IN BUFFER TO LINE STRING.
 **
 */
void prepend_overlap(char *str, char ***line, int *i)
{
    int b = *i;
    while (str[b])
    {
        (**line)[b] = (char)malloc(sizeof(char));
        (**line)[b] = str[b];
        b++;
    }
    *i = b;
}


/*
 ** GET A SINGLE LINE AT A TIME FROM A FILE
 ** WHILE ALSO KEEPING TRACK OF THE FD.
 */
int get_next_line(const int fd, char **line)
{
    char buffer[BUFF_SIZE + 1];
    int i;
    int j;
    char *overlap_str;
    static t_node *root;

    i = 0;
    j = 0;
    overlap_str = get_overlap(&root, fd);
    if(overlap_str != NULL)
        prepend_overlap(overlap_str, &line, &i);
    read(fd, buffer, BUFF_SIZE);
    while (buffer[j] != '\n')
    {
        if (j == BUFF_SIZE)
        {
            (*line)[i] = (char)malloc(sizeof(char));
            (*line)[i] = buffer[j];
            j = 0;
            read(fd, buffer, BUFF_SIZE);
            continue;
        }
        (*line)[i] = (char)malloc(sizeof(char));
        (*line)[i] = buffer[j];
        i++;
        j++;
    }
    (*line)[i] = '\0';
    printf("%s\n", *line);
    save_overlap(buffer, &root, fd);
    return (0);
}

int main()
{
    int fd = open("test", O_RDONLY);
    //int fdt = open("test2", O_RDONLY);
    char *line;

    get_next_line(fd, &line);
    get_next_line(fd, &line);

}

get_next_line.h

#ifndef GET_NEXT_LINE_H
# define GET_NEXT_LINE_H

# define BUFF_SIZE 32
#include <fcntl.h>

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

typedef struct s_node
{
    int fd;
    char *str;
    struct s_node *next;
}t_node;

#endif

它适用于单个文件描述符,例如我只能传递fd而不是fdt它会起作用,除非我将缓冲区大小设置为120或更高,例如,它将打印超出我想要的内容。我只想要'\ n'之前的那一行。

1 个答案:

答案 0 :(得分:0)

new->str = malloc(sizeof(char *));
...
new->str[i] = (char)malloc(sizeof(char));

我不确定你在这里要做什么。 malloc(N * sizeof(char*))可用于创建一个指向&#34;字符数组&#34;的指针数组,其大小为N。基本上&#34;字符串数组&#34;或者&#34;二维字符数组&#34;。

malloc(sizeof(char))只是malloc(1),或只是一个字节。如果new->str是字符数组,那么str[i]已经是一个字节,不应该使用malloc设置

这样做是为了分配字符数组:

new->str = malloc(5);
strcpy(new->str, "1234");

这将为str分配5个字节,然后复制&#34; 1234&#34;它,并在最后添加一个零,总共5个字节。

此外,您的链接列表也没有头脑。请尝试以下代码。

#include <stdlib.h>//*** don't forget the right header files
#include <stdio.h>
#include <string.h>

typedef struct s_node
{
    char *str;
    struct s_node *next;
}t_node;

void insert_node(t_node** head, char* buf)
{
    t_node *node = malloc(sizeof(t_node));
    node->next = 0;

    //allocate memory for string and copy
    node->str = malloc(strlen(buf) + 1); //+1 for nul-terminator
    strcpy(node->str, buf);

    if (*head == 0)
    {
        *head = node;
    }
    else
    {
        //find the end of the linked list
        t_node *tail = *head;
        while (tail->next)
            tail = tail->next;

        //make the end element point to new node
        tail->next = node;
    }
}

int main()
{
    FILE *fd = fopen("test.txt", "r");
    if (!fd)
    {
        printf("file error\n");
        return 0;
    }

    //linked list identifier:
    t_node *head = 0;

    char buf[1000];

    //read the file line by line
    while(fscanf(fd, "%999s", buf) > 0)
    {
        //insert line in to linked list
        insert_node(&head, buf);
    }

    //show the result of the linked list:
    t_node *walk = head;
    while (walk)
    {
        printf("[%s]\n", walk->str);
        walk = walk->next;
    }

    return 0;
}

请注意,如果一行或多行超过1000个字符,则上述代码将失败。你可以增加缓冲区长度,或者有办法解决这个问题,但我保留原样以使示例变得简单。

确保编译器警告级别为4或最大值,并确保处理所有警告和错误。