C:使用FGETS建设焦炭的链表*(C: fgets usage for building a li

2019-09-28 12:13发布

我使用fgets()不正确?

我想建立一个字符串的链表( char *添加每个新行LL的结束)。 我读从一个文件中的这些线路,但由于某种原因,每行获取当前行覆盖正在处理中,只使用时fgets()while循环,但附加功能似乎被正确接收的每一行。

如果我单独添加行main()不存在任何问题。

下面是一个示例输入文件:

input.txt中:

This life, which had been the
tomb of his virtue and of his
honour, is but a walking
shadow; a poor player, that
struts and frets his hour upon
the stage, and then is heard
no more: it is a tale told by an
idiot, full of sound and fury,
signifying nothing.
    --William Shakespeare

编码:

#include <stdio.h> //printf, fopen
#include <stdlib.h> //exit, EXIT_FAILURE
#include <string.h> //strlen

struct node {
    char *line;
    struct node *next;
};

void print(struct node *node);

void add(struct node **head, char *newLine) {
    //printf("%s", newLine);

    struct node *new_node = (struct node *)malloc(sizeof(struct node));
    struct node *curr = *head;

    new_node->line = newLine;
    new_node->next = NULL;

    if (*head == NULL) {
        *head = new_node;
    } else {
        while (curr->next != NULL) {
            curr = curr->next;
        }
        curr->next = new_node;
    }
    print(*head);
}

void print(struct node *node) {
    printf("\n");

    while (node != NULL) {
        printf("%s\n", node->line);
        node = node->next;
    }
}

int main(int argc, char *argv[16]) {
    char newLine[81];
    struct node *head = NULL;
    FILE *fp = fopen(argv[1], "r");

    if (fp == NULL) {
        printf("ERROR: file open failed");
        exit(EXIT_FAILURE);
    }

    while (fgets(newLine, 81, fp)) {
        add(&head, newLine);
    }

    add(&head, "why");
    add(&head, "does");
    add(&head, "this");
    add(&head, "work??");

    fclose(fp);

    print(head);

    return 0;
}

可能有人请向我解释发生了什么? 我一直在敲打我的头靠在墙上太久。 目前已经有一些评论打印语句我一直在尝试使用,未成功进行调试。

Answer 1:

你的问题是在add()方法。 它使添加相同的缓冲区指针到列表中。 您需要将缓冲区列表复制到新分配的空间,即。 节点 - >线需要被malloced,也和换行复制到其中。 不要忘记的malloc(strlen的(新行)+ 1)。



Answer 2:

您有您存储输入一个缓冲区。 和你添加节点时将指针传递给该单个缓冲器的第一元素。 这意味着所有节点中的字符串指针将指向同一个缓冲区。 这将最终包含你读的最后一个字符串。

最简单的解决方案是使在节点结构的阵列的字符串,字符串复制到它。

另一种解决方案是为字符串动态地分配存储器(记住终止空字符),并再次将字符串复制到该存储器中。

使用恒定字符串文字时不同的是,每个串的将是一个不同的阵列。



Answer 3:

你必须为每个行分配内存。 作为当前编码的,所有的节点指向在局部阵列main()其内容是由每个呼叫重写到fgets()

还要注意的是每一行添加到列表中包含了终止换行符,你或许应该得到呼叫前摆脱。

这里是一个修正版本:

#include <stdio.h>  // printf, fopen
#include <stdlib.h> // exit, EXIT_FAILURE
#include <string.h> // strlen, strdup

struct node {
    char *line;
    struct node *next;
};

void print(struct node *node);

void add(struct node **head, char *newLine) {
    //printf("%s", newLine);

    struct node *new_node = malloc(sizeof(struct node));
    struct node *curr = *head;

    new_node->line = strdup(newLine);
    new_node->next = NULL;

    if (*head == NULL) {
        *head = new_node;
        return;
    }

    while (curr->next != NULL) {
        curr = curr->next;
    }

    curr->next = new_node;
    print(*head);
}

void print(const struct node *node) {
    printf("\n");

    while (node != NULL) {
        printf("%s\n", node->line);
        node = node->next;
    }
}

int main(int argc, char *argv[16]) {
    char newLine[81];
    struct node *head = NULL;
    FILE *fp = fopen(argv[1], "r");

    if (fp == NULL) {
        printf("ERROR: file open failed");
        exit(EXIT_FAILURE);
    }

    while (fgets(newLine, sizeof newLine, fp)) {
        newLine[strcspn(newLine, "\n")] = '\0'; // strip the newline if present
        add(&head, newLine);
    }

    add(&head, "why");
    add(&head, "does");
    add(&head, "this");
    add(&head, "work??");

    fclose(fp);

    print(head);

    return 0;
}


文章来源: C: fgets usage for building a linked list of char*