首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用静态节点读取每个文件描述符1行

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

Stack Overflow用户
提问于 2016-11-15 09:40:02
回答 1查看 276关注 0票数 0

我正在尝试读取一个文件,每次一行,使用不同的缓冲区长度。我将一个desc文件传递给get_next_line函数,并将该行赋值给一个指针。问题是,当缓冲区长度很长时,有时它会打印文件的其余部分,而当我传递两个不同的文件描述符时,我会得到一个段错误。我认为这与将字符串保存在节点中并在fd相同的情况下找到相同的节点有关。我看不出我哪里做错了。

get_next_line.c

代码语言:javascript
运行
复制
#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

代码语言:javascript
运行
复制
#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‘之前的行。

EN

回答 1

Stack Overflow用户

发布于 2016-11-15 17:36:09

代码语言:javascript
运行
复制
new->str = malloc(sizeof(char *));
...
new->str[i] = (char)malloc(sizeof(char));

我不确定你在这里想要做什么。可以使用malloc(N * sizeof(char*))创建一个指向“字符数组”的指针数组,大小为N。基本上就是“字符串数组”或“二维字符数组”。

malloc(sizeof(char))就是简单的malloc(1),或者说只有一个字节。如果new->str是字符数组,则str[i]已经是一个字节,不应使用malloc设置它

改为执行此操作以分配给字符数组:

代码语言:javascript
运行
复制
new->str = malloc(5);
strcpy(new->str, "1234");

这将为str分配5个字节,然后将"1234“复制到其中,并在末尾添加一个零,总共5个字节。

你的链表也没有头。请尝试以下代码。

代码语言:javascript
运行
复制
#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或最大值,并确保处理所有警告和错误。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40600700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档