段错误:链表节点插入函数 [C++]
Posted
技术标签:
【中文标题】段错误:链表节点插入函数 [C++]【英文标题】:Seg Fault: Linked List Node Insertion Function [C++] 【发布时间】:2019-06-26 19:27:56 【问题描述】:我创建了一个名为“插入”的函数,用于在链接列表中插入一个新节点。它采用值和头节点进行插入。 当我自己手动添加节点时,程序按预期运行 使用添加节点的功能时出现分段错误。
我可以通过一些小调整使函数工作,但还有一个问题,我失去了头节点作为指针的属性,它现在包含一些垃圾数据,当我打印 LinkedList 时会打印这些数据.
我执行的调整是:
Change Line 26 to: A->next = NULL;
Change Line 17 to: while(temp->next != NULL)
“分段错误”发生在第 20 行(未完成调整时):
Line 20 -----> temp->next = addTo;
我已经尝试通过引用传递参数,对头节点使用全局变量并检查函数的逻辑。 该逻辑适用于手动添加节点。
我已经附上了下面的完整代码:
#include <bits/stdc++.h>
using namespace std;
struct ListNode
int data;
ListNode *next;
;
void Insert(int x , ListNode* head)
ListNode* addTo = new ListNode();
addTo->data = x;
addTo->next = NULL;
ListNode* temp;
temp = head;
while(temp != NULL)
temp = temp->next;
temp->next = addTo;
int main()
ListNode* A;
A = NULL;
//Inserting A Node Manually
// ListNode* first = new ListNode();
// first->data = 9;
// first->next = NULL;
// while(A != NULL)
// A = A->next;
// A = first;
//Inserting using Insert function.
Insert(2,A);Insert(3,A);Insert(6,A);Insert(7,A);
//Printing
ListNode* temp = A;
while(temp != NULL)
cout << temp->data << " ";
temp = temp->next;
return 0;
我希望将节点添加到列表中,因为逻辑似乎是正确的,但是我遇到了分段错误。
对此的任何帮助/见解都会有很大帮助。
谢谢。
【问题讨论】:
您的问题可能源于非标准头文件bits/stdc++.h
。使用非编译器特定的标准头文件。
回到主题,调试链表的最佳方法之一是绘制图片。画出清单。然后在列表中一步一步地执行你希望调试的函数中的所有操作。当你发现自己画的东西很傻时,你只是发现了一个错误。
简单修复:循环迭代直到 temp
为 NULL
。然后,您尝试访问该位置的next
指针。你应该迭代直到temp->next
是NULL
,因为那将是列表的尾部。
伟大的开始。接下来要做的是使用调试器显示该行中涉及的所有变量。如果您发现 temp
为 null 之类的令人讨厌的内容,请返回代码以查看其为 null 的原因。
@user4581301,是的,我的 temp 值为 0x0,我猜它是 NULL。
【参考方案1】:
问题一:
while(temp != NULL)
temp = temp->next;
temp->next = addTo;
保证当while(temp != NULL)
退出时temp
将是NULL
。这意味着没有temp
可以从中获取next
。
我不在这里解决这个问题,而是继续解决问题 2,用一块石头杀死两只鸟。
问题2:
void Insert(int x , ListNode* head)
如果head
在Insert
函数中发生更改,您将无法更新调用者。您可以更改head
指向的对象,但head
本身只是地址的副本。如果您将此副本更改为指向另一个地址,则调用者不知道。
这意味着每次您拨打Insert(<number>, A);
,A
将始终是NULL
。
解决方案:
通过引用将head
传递给Insert
,以便更新。
void Insert(int x , ListNode*& head)
^ reference to pointer
head
的工作是指向列表中的第一项。这意味着它与任何next
指针做同样的事情:它指向下一项。唯一的区别是名称。我们可以通过添加一个额外的间接寻址,一个指向head
的指针来消除这种差异。
ListNode ** temp = &head;
请注意,我们不能在此处使用引用 (ListNode *& temp
),因为一旦初始化引用以引用一个对象,就不能将其更改为引用不同的对象。您可以更改的指针,允许我们遍历列表并始终将 temp
指向下一个 next
。
现在head
或任何next
都只是temp
。这使得 head
与所有其他 next
变量完全相同,并且不需要特殊情况。
void Insert(int x , ListNode*& head)
ListNode* addTo = new ListNode();
addTo->data = x;
addTo->next = NULL; // consider making a smarter ListNode constructor that makes
// it impossible to forget to set next.
ListNode ** temp = &head; // we can now manipulate the address in head through temp
while(*temp != NULL) // note the dereference to get the pointed at pointer
// temp won't be null, but it could be pointing at a pointer
// that is null, and that is the end of the list
// I always use the optional braces. They prevent confusion.
temp = &(*temp)->next; //get pointer to the next next pointer
// we can now manipulate it exactly the same as head.
// we exit the loop with a pointer to the next pointer that we wish to point at
// the new list item regardless of whether it's head or the next of some later
// link in the list
*temp = addTo; // update the pointed at pointer with the new Node.
How do I properly delete nodes of linked list in C++ 的第一个答案的社区添加演示了如何使用相同的指针到指针技巧来轻松删除节点。
【讨论】:
很好的答案。非常感谢! @Viktor 如果回答了您的问题,您可以通过勾选正确的标记来接受答案。以上是关于段错误:链表节点插入函数 [C++]的主要内容,如果未能解决你的问题,请参考以下文章
c语言链表插入问题,pta提交有个段错误,请各位大佬帮忙找找茬,感激!