【问题标题】:get line from text and put into a linked list从文本中获取行并放入链表
【发布时间】:2021-05-12 01:18:18
【问题描述】:

我最近开始使用 C 进行编码,并且正在关注 OSTEP 的优秀项目。其中一项任务是反转文本文件中的行,以便:

这个/是/一个/行

变成

行/a/是/this

我决定将每一行放在一个链接列表中的一个节点上,然后反转这个列表。我的问题是为什么当我打电话给print_list 结果是空的? 经过一些调试,看起来head 节点一开始没有设置为current。

另外,如果您在我的代码中有通用的 cmets,我将不胜感激,以便我可以学习。谢谢!

#include <stdio.h>
#include <stdlib.h>

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

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

int main(int argc, char** argv) {
    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL) {
        printf("cannot open file\n");
    }

    node_t *head = malloc(sizeof(node_t));
    head->line = NULL;
    head->next = NULL;

    char *line = NULL;
    size_t linecap = 0;
    ssize_t linelen;
    node_t *current = head;
    while ((linelen = getline(&line, &linecap, fp)) > 0) {
        current->line = line;
        current->next = (node_t *) malloc(sizeof(node_t));
        current = current->next;
    }
    current->next = NULL;
    print_list(head);
    fclose(fp);
    return 0;
}

【问题讨论】:

  • “我决定将每一行放在一个链表中的一个节点上,然后反转这个列表” - 这将如何反转一行的内容,如你展示的例子?似乎您希望每行一个链表,然后链表的每个节点一个 word。
  • 这是一种方式。出于练习的目的,我只希望每个节点有一条线
  • OT:始终检查argc,以确保用户在访问argv[0]之外之前实际输入了命令行参数
  • 关于:if (fp == NULL) { printf("cannot open file\n"); } 1) 错误消息应该输出到stderr,而不是stdout。 2) 当错误指示来自 C 库函数时,还将系统认为发生错误的文本原因输出到stderr。函数:perror() 就是为此而生的。建议:perror( "fopen failed" ); 注意:这是一个不可恢复的错误。发生此错误时,不要像调用fopen() 成功一样继续执行程序。而是致电:exit( EXIT_FAILURE );
  • 关于:``node_t *current = head; while ((linelen = getline(&line, &linecap, fp)) > 0) { current->line = line; current->next = (node_t *) malloc(sizeof(node_node_t *current = head; while ((linelen = getline(&line, &linecap, fp)) > 0) { current->line = line; current->next = ( node_t *) malloc(sizeof(node_t)); current = current->next; }t));当前=当前->下一个; }` 1) 在 C 中,不要从 malloc() 转换返回值 cont:

标签: c data-structures linked-list


【解决方案1】:
  • 您分配了一个缓冲区,但未初始化其成员 line。这将在print_list 中使用时导致未定义的行为。
  • 您应该将指针设置为NULL,并将大小设置为0,以便getline() 分配缓冲区。目前,第一个输入的缓冲区已被重用。
  • printf_list(head)l 应该是 print_list(head);。

试试这个:

int main(int argc, char** argv) {
    FILE *fp = fopen(argv[1], "r");
    if (fp == NULL) {
        printf("cannot open file\n");
    }

    node_t *head = NULL;

    char *line = NULL;
    size_t linecap = 0;
    ssize_t linelen;
    /* use pointer to node_t* for allocation */
    node_t **current = &head;
    while ((linelen = getline(&line, &linecap, fp)) > 0) {
        /* allocate buffer only if some data is read */
        *current = malloc(sizeof(node_t));
        if (*current == NULL) return 1;
        (*current)->line = line;
        (*current)->next = NULL;
        current = &(*current)->next;
        /* reset the parameter */
        line = NULL;
        linecap = 0;
    }
    print_list(head);
    fclose(fp);
    return 0;
}

【讨论】:

  • 这很有帮助。对于node_t **current = &amp;head;,您正在创建一个指向head 内存位置的指针?在不立即使用时将指针初始化为 null 通常是一种好习惯吗?谢谢!
猜你喜欢
  • 2016-02-12
  • 2019-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多