簡體   English   中英

使用靜態節點每個文件描述符讀取1行

[英]Read 1 line per file descriptor using static nodes

我正在嘗試一次讀取一行具有不同緩沖區長度的文件。 我正在將文件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'之前的行。

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進行設置

改為分配一個字符數組:

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

這將為str分配5個字節,然后向其分配“ 1234”,並在末尾添加一個零,共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或最大,並確保您處理所有警告和錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM