【问题标题】:Adding char* to a linked list does not work将 char* 添加到链表不起作用
【发布时间】:2015-03-29 18:48:59
【问题描述】:

很抱歉问了一个我认为是愚蠢的问题,但我觉得我的概念非常错误,需要解决它。

我有这个列出链接的代码,我已经玩了一点来让我的头脑围绕它:

http://www.thegeekstuff.com/2012/08/c-linked-list-example/

现在我需要用同样的方式来操作列表,但不是结构是 int val,而是我希望它是 char * val,所以结构应该是这样的:

struct nodoTemas{
    char * nombreTema;
    struct nodoSuscriptor * nodoCerodeSuscriptores;
    struct nodoTemas * next;
};

我从这样的文件中读取字符 *:

while ((read = getline(&line, &len, fp)) != -1) {
add_to_list(line,true);

}

我根本无法在概念层面上找到差异。是的,getline 在 char * 中添加了一个 \n,所以它有点弄乱我的 fprintf 等等,但我从执行代码中得到的结果是:

 creating list with headnode as [tema1
 ]


  Adding node to end of list with value [tema2
 ]

  -------Printing list Start------- 

  [tema2
 ] 

  [tema2
 ]

应该是什么时候

-------打印列表开始-------

  [tema1
 ] 

  [tema2
 ]

因为那是它首先得到的!!!我只是看不出有什么区别,我重新阅读了有关 char*、char 和 char[] 的信息,我重新阅读了 getline man,我只是不明白为什么链接中的代码有效与 int 完美搭配,如果我使用 char*,它会正确添加和迭代,然后有点……崩溃并覆盖?这就是正在发生的事情吗?没有线索。

另外,如果我应该在其他地方发布此内容,请告诉我。

我也找到了这篇文章,但我认为问题出在我的情况下,但不完全确定

Adding Char Value to a Linked List using Looping [C]

【问题讨论】:

  • 你没有显示你的代码,所以我们无法判断它有什么问题。疯狂的猜测时间:您不会在每次迭代时将参数重置为 getline(),因此下一行会覆盖前一行。
  • 鉴于您尚未发布插入代码,因此尚不清楚,但我猜您没有分配内存来存储您读入的字符串。请注意,指针只是 points 指向内存,它不存储您指向的字符串,它只存储 where 字符串所在的位置。当您打印该指针时,它会在它指向的位置打印字符串。您链接的问题也这样做了,用 strdup 查看答案。
  • 我要添加所有代码吗?害怕这样做,所以帖子会很长。另外,我怀疑 string/getline 的事情,但我想不通,我感觉很愚蠢。这有意义吗? while ((read = getline(&line, &len, fp)) != -1) { add_to_list(line,true); }

标签: c list linked-list getline


【解决方案1】:

正如我在原来的comment 中所猜测的那样,您遇到了问题,因为您没有正确管理getline() 分配并由add_to_list() 使用的空间。

你说你正在使用:

while ((read = getline(&line, &len, fp)) != -1) {
    add_to_list(line, true);
}

您还没有显示add_to_list() 的代码,但症状是您只是在列表中分配line(指针)的值,而不是为函数中的空间制作副本。您可以通过以下方式从表面上修复代码:

char *line = 0;
size_t len = 0;
ssize_t nbytes;
while ((nbytes = getline(&line, &len, fp)) != -1)
{
    add_to_list(line, true);
    line = 0;
    len = 0;
}
free(line);

这将为读取的每一行分配新的内存。然后add_to_list() 函数可以使用它。 但是,您必须确保最终确实释放了内存 - 当您释放列表时。请注意,显示的free() 并不是您唯一需要的。它会在检测到 EOF 之前释放由 getline() 抢先分配的所有内存。

另一种设计是:

char *line = 0;
size_t len = 0;
ssize_t nbytes;
while ((nbytes = getline(&line, &len, fp)) != -1)
    add_to_list(line, true);
free(line);

现在您必须修改 add_to_list() 以复制来自 line 的数据。如图所示,您仍然必须释放该行,并且释放列表的代码仍然必须释放复制的数据。

我已经有一个free(line),但你提到这不是我需要的唯一免费。介意扩大一点吗?是否有必要释放列表中的每个节点?该列表应该在发布者 - 订阅者模型中保存主题,因此除非流程结束,否则我认为内存应该保存列表?

在你完成之前没有必要释放任何东西;过早释放与从未释放一样糟糕。当您分配内存时,您总是必须知道何时释放内存。对于每次分配,请确保您可以确定内存将如何被释放以及何时被释放。

有时内存永远不会被释放(或者直到进程退出)是一个合理的决定,但对于长时间运行的进程,这是需要谨慎决定的事情。即便如此,只有当有一个指针(或指针链)允许您访问内存时,它才是合法的。如果没有办法访问内存,那么它就会泄漏和浪费,这在大型程序中不是一个好主意(尤其是在长时间运行的程序中)。

如果您为列表中的每个项目分配了内存,那么您需要在释放项目时为列表中的每个项目释放内存。当您拆除整个列表时可能会发生这种情况,或者当您决定不再需要某个项目时它可能会逐渐发生。重要的是您知道内存已分配,并且在不再需要时将被释放。如果您不确保这一点,您将泄漏内存,并且您的程序可能会增长,直到它耗尽内存。

如果可能,请使用valgrind 之类的工具来帮助您跟踪内存滥用情况——它会发现内存泄漏和一些内存滥用(读取和写入越界)。

【讨论】:

  • 非常感谢您的回答。我真的错过了一个概念,因为我认为如果我在下一个 getline 之前的列表中插入一个值,在不同的节点中等等,它会起作用。我确实有疑问:我已经有一个免费(线路),但你提到这不是我需要的唯一免费。介意扩大一点吗?是否有必要释放列表中的每个节点?该列表应该在发布者-订阅者模型中保存主题,因此除非流程结束,否则我相信内存应该保存列表?不太确定 tbh
【解决方案2】:

getlinereusing the pointer of line 用于存储 char 数据。使用strdup 将其存储在您的链接节点中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-21
    • 2016-08-12
    • 1970-01-01
    • 2012-04-26
    • 2023-03-17
    • 1970-01-01
    • 2016-02-26
    相关资源
    最近更新 更多