我在C程序下面实现了升序链表。问题出在buildList()函数中,因此您可以忽略除main()和buildList()之外的其他函数。
#include<stdio.h>
#include<stdlib.h>
struct node
{
int data;
struct node *next;
};
void buildList(struct node **, int);
void printList(struct node **);
int main()
{
struct node *head;
head = NULL; /*Empty list*/
int hold, i, j;
printf("How many integers in this list: ");
scanf("%d",&i);
j = 1;
for(i; i > 0; i--)
{
printf("Integer %d: ",j);
scanf("%d",&hold);
buildList(&head, hold);
j++;
}
printList(&head);
return 0;
}
void buildList(struct node **headRef, int data)
{
struct node *newNode;
newNode = malloc(sizeof(struct node));
struct node *current, *current1;
current = *headRef;
//If list is empty, add the number as the first node.
if (current == NULL)
{
newNode->data = data;
newNode->next = *headRef;
*headRef = newNode;
}
//If the list is not empty.
else
{
//If the number is not greater than first number.
if (data <= current->data)
{
newNode->data = data;
newNode->next = current;
*headRef = newNode;
}
//If the number is greater than the first number in list.
else
{
int flag = 0;
while (data > (current->data))
{
current1 = current;
current = current->next;
}
newNode->data = data;
current1->next = newNode;
newNode->next = current;
}
}
}
//Prints nodes and total number of nodes.
void printList(struct node **headRef)
{
int count = 0;
struct node *current;
current = *headRef;
while (current != NULL)
{
count++;
printf("%d ",current->data);
current = current->next;
}
printf("\nTotal nodes: %d\n",count);
}
这个程序运行正常,直到我给出一个大于列表中任何数字的数字。在那种情况下,我得到了一个分段错误。
案例I(精确输出正确)
-bash-4.1$ ./a.out
How many integers in this list: 3
Integer 1: 5
Integer 2: 1
Integer 3: 4
1 4 5
Total nodes: 3
-bash-4.1$
案例II(这里是代码中断(分段错误))
-bash-4.1$ ./a.out
How many integers in this list: 3
Integer 1: 5
Integer 2: 6
Segmentation fault
-bash-4.1$
经过很长一段时间试图弄清楚我的代码出了什么问题,我发现当一个数字大于列表中的任何数字时,在这种情况下它将被插入到列表的末尾,这个语句(在函数buildList()的最后一个中)引起了问题:
current = current->next;
我终于发现当current-&gt; next为NULL时,此语句会导致seg fault。
我提出了类似下面的解决方法,它可以提供正确的输出。
else
{
int flag = 0;
while (data > (current->data))
{
current1 = current;
if(current->next != NULL)
{
current = current->next;
}
else
{
flag = 1;
break;
}
}
newNode->data = data;
current1->next = newNode;
if (flag == 1)
{
newNode->next = NULL;
}
else
{
newNode->next = current;
}
}
现在我得到了正确的输出。
-bash-4.1$ ./a.out
How many integers in this list: 3
Integer 1: 5
Integer 2: 1
Integer 3: 10
1 5 10
Total nodes: 3
-bash-4.1$
现在我想知道为什么不是current = current-&gt; next;当current-&gt; next为NULL时工作。我期待这个语句为当前分配NULL。
有谁能告诉我这个的原因? 我的解决方案也很好吗?或者有更好的方法吗?
对不起这个长问题,但花了2个小时调试这个,我想我会发疯了。
感谢。
答案 0 :(得分:2)
你的调试技术给你一点红鲱鱼。问题出现在这个循环中:
while (data > (current->data))
{
current1 = current;
current = current->next;
}
但不是你认为的那条线。如果current->next
为NULL
,current
就会像您描述的那样设置为NULL
。然而,下一个发生的操作是循环条件 - 解除引用current
。 Blammo。你可能想要这样的东西:
while (current && (data > current->data))
{
current1 = current;
current = current->next;
}
我没有分析你的整个程序,所以除了显而易见的crasher之外,我无法评论这一部分的正确性。
答案 1 :(得分:2)
当第二个输入大于第一个输入时,此while
循环不会停止。
while ( data > (current->data))
{
current1 = current;
current = current->next;
}
您最终取消引用NULL指针。你需要:
while ( current != NULL && data > (current->data))
{
current1 = current;
current = current->next;
}