C 插入到链表中总是返回最后一个节点,而不是当前节点
所以我在写一个程序,创建一个dinamic列表,在最后一个节点后插入一个新节点,最后打印新创建的列表。我希望当我打印它时,它实际上会连续打印当前节点的编号,比如Info:1,Info:2,Info:3,但它总是打印最后一个节点。我猜这是指针错误,但不能真正找到什么C 插入到链表中总是返回最后一个节点,而不是当前节点,c,C,所以我在写一个程序,创建一个dinamic列表,在最后一个节点后插入一个新节点,最后打印新创建的列表。我希望当我打印它时,它实际上会连续打印当前节点的编号,比如Info:1,Info:2,Info:3,但它总是打印最后一个节点。我猜这是指针错误,但不能真正找到什么 #include <stdio.h> #include <stdlib.h> struct node{ int info; struct node* pNext; }; typedef struct
#include <stdio.h>
#include <stdlib.h>
struct node{
int info;
struct node* pNext;
};
typedef struct node Node;
void tail_insertion(Node* pFirst, Node* pLast);
void print_list(Node* pFirst);
static int n=3;
int main()
{
Node *pFirst=NULL, *pLast=NULL;
tail_insertion(pFirst, pLast);
}
void tail_insertion(Node* pFirst, Node* pLast){
// Creation of a new node in the heap
Node *pNew = (Node*) malloc(sizeof(Node));
pNew->info=0;
pNew->pNext= NULL;
for(int i=0; i<3;i++){
if(pFirst == NULL){// No node in the list
pNew->info++;
pFirst = pNew; // The first node is the newly created one
pLast = pNew; // The last node is the newly created one
printf("Ok the list was empty\n");
}
else{
// Else, there is already at least one node in the list
pNew->info++;
pLast-> pNext= pNew; // the last node becomes the second one
pLast= pNew; // The last node is the newly created one
printf("Ok the list wasn't empty\n");
}
}
print_list(pFirst);
return;
}
void print_list(Node* pFirst){
if(pFirst == NULL){
printf("No node in the list!\n");
}
else{
// New pointer used to scan the list.
Node* pScan = pFirst;
do{
printf("Info: %d\n", pScan->info);
// ptrScan is updated to point to the next node in the
// list
pScan = pScan->pNext;
}while(pScan!= NULL && --n); //NULL when this was the last node
}
return;
}
两个问题:
您没有将指针传递到列表指针节点*->节点**
您试图将同一节点插入三次,并将malloc移动到循环中
我猜静态int n=3,而-n可能是为了修复print_列表中的无休止循环而添加的,因为pscan->pNext在原始代码中生成了pscan
修复和清理代码:
包括
包括
typedef结构节点;
类型定义结构节点{
国际信息;
节点*pNext;
}节点;
静态无效打印\u列表节点*pFirst{
//用于扫描列表的新指针。
节点*pScan=pFirst;
而pScan{
printfInfo:%d\n,pScan->info;
//ptrScan更新为指向中的下一个节点
//名单
pScan=pScan->pNext;
}
}
静态无效尾部插入节点**p第一,节点**pLast{
对于int i=0;iinfo=i+1;
pNew->pNext=NULL;
如果*pFirst==NULL{//列表中没有节点
*pFirst=pNew;//第一个节点是新创建的节点
*pLast=pNew;//最后一个节点是新创建的节点
printfOk列表为空\n;
}else{//else,列表中至少已有一个节点
*pLast->pNext=pNew;//最后一个节点成为第二个节点
*pLast=pNew;//最后一个节点是新创建的节点
printfOk列表不是空的\n;
}
}
打印列表*pFirst;
}
int main argc,char*argv[]{
Node*pFirst=NULL;
Node*pLast=NULL;
尾翼插入、首件和塑料件;
}
试运行:
$gcc-Wall-Werror-o dummy.c
美元/虚拟
好的,列表是空的
好的,列表不是空的
好的,列表不是空的
信息:1
信息:2
信息:3
两个问题:
您没有将指针传递到列表指针节点*->节点**
您试图将同一节点插入三次,并将malloc移动到循环中
我猜静态int n=3,而-n可能是为了修复print_列表中的无休止循环而添加的,因为pscan->pNext在原始代码中生成了pscan
修复和清理代码:
包括
包括
typedef结构节点;
类型定义结构节点{
国际信息;
节点*pNext;
}节点;
静态无效打印\u列表节点*pFirst{
//用于扫描列表的新指针。
节点*pScan=pFirst;
而pScan{
printfInfo:%d\n,pScan->info;
//ptrScan更新为指向中的下一个节点
//名单
pScan=pScan->pNext;
}
}
静态无效尾部插入节点**p第一,节点**pLast{
对于int i=0;iinfo=i+1;
pNew->pNext=NULL;
如果*pFirst==NULL{//列表中没有节点
*pFirst=pNew;//第一个节点是新创建的节点
*pLast=pNew;//最后一个节点是新创建的节点
printfOk列表为空\n;
}else{//else,列表中至少已有一个节点
*pLast->pNext=pNew;//最后一个节点成为第二个节点
*pLast=pNew;//最后一个节点是新创建的节点
printfOk列表不是空的\n;
}
}
打印列表*pFirst;
}
int main argc,char*argv[]{
Node*pFirst=NULL;
Node*pLast=NULL;
尾翼插入、首件和塑料件;
}
试运行:
$gcc-Wall-Werror-o dummy.c
美元/虚拟
好的,列表是空的
好的,列表不是空的
好的,列表不是空的
信息:1
信息:2
信息:3
通用代码分析
我们考虑泰勒插入…你希望它做什么:
创建一个新节点;
你给它正确的价值观;
启动for循环的目的是基于特定条件创建更多节点;
打印整个列表以检查其是否有效;
现在,看看你的尾部插入代码。。。删除功能注释:
请注意,我已删除退货。。。因为它不是必需的。这是不必要的,因为尾部插入。。。类型无效
另外,pNew->info正在存储我读取时的节点ID。因此,将i分配给它应该不是一个问题。如有必要,进行适当的更改
最后说明
有评论说你不需要塑料。虽然这是事实,但您需要考虑:
如果只使用pFirst,则需要确保在pFirst->pNext中插入新节点后,执行pFirst->pNext->pNext=NULL。这样,您就可以通过比较NULL来知道何时到达列表的末尾;
如果您继续使用pLast,您可以与pLast进行比较,以了解该地址是否是列表中的最后一个地址。显然,在我的修复之后,您也可以将其与NULL进行比较;
考虑尾随
从长远来看,使用pLast可以大大简化工作,减少CPU的使用;
你可能知道,但你应该把打印列表放在第一位;在主。。。使事情更有条理的功能。而且,它使我的代码强迫症达到新的绝望水平- 通用代码分析
我们考虑泰勒插入…你希望它做什么:
创建一个新节点;
你给它正确的价值观;
启动for循环的目的是基于特定条件创建更多节点;
打印整个列表以检查其是否有效;
现在,看看你的尾部插入代码。。。删除功能注释:
请注意,我已删除退货。。。因为它不是必需的。这是不必要的,因为尾部插入。。。类型无效
另外,pNew->info正在存储我读取时的节点ID。因此,将i分配给它应该不是一个问题。如有必要,进行适当的更改
最后说明
有评论说你不需要塑料。虽然这是事实,但您需要考虑:
如果只使用pFirst,则需要确保在pFirst->pNext中插入新节点后,执行pFirst->pNext->pNext=NULL。这样,您就可以通过比较NULL来知道何时到达列表的末尾;
如果您继续使用pLast,您可以与pLast进行比较,以了解该地址是否是列表中的最后一个地址。显然,在我的修复之后,您也可以将其与NULL进行比较;
考虑到尾部插入,使用pLast可以大大简化工作,并从长远来看减少CPU的使用;
你可能知道,但你应该把打印列表放在第一位;在主。。。使事情更有条理的功能。而且,它使我的代码强迫症达到新的绝望水平- 提示:pFirst的值不会在函数外部更改。@EugeneSh。那我该怎么办?你为什么需要橡皮膏?似乎是多余的,没有检查错误?@NeilEdelman我用它来指向列表的末尾,这样我就知道在结构节点中插入新节点的位置你有一个节点元素,它指向链接列表中的下一个节点变量,您可以使用它来查找列表的结尾。提示:pFirst的值在函数之外不会更改。@EugeneSh。那我该怎么办?你为什么需要橡皮膏?似乎是多余的,没有检查错误?@NeilEdelman我用它来指向列表的末尾,这样我就知道在结构节点中插入新节点的位置。如果有一个节点元素指向链接列表中的下一个节点变量,你可以用它来查找列表的结尾。是的,我添加了-n来尝试修复循环。谢谢你是的,我加了-n来修复这个循环。谢谢你我考虑的另一个设计决定是头部插入,它允许pFirst成为唯一的真相来源,允许O1插入,基本上是一个堆栈。谢谢你的解释,它非常详尽!我现在发现了这个缺陷。我会考虑的另一个设计决策是头部插入,它允许pFirst成为唯一的真相来源,并允许O1插入,基本上是一个堆栈。谢谢你的解释,它非常详尽!我现在发现了缺陷。
Ok the list was empty
Ok the list wasn't empty
Ok the list wasn't empty
Info: 3
Info: 3
Info: 3
Node *pNew = (Node*) malloc(sizeof(Node));
pNew->info=0;
pNew->pNext= NULL;
for(int i=0; i<3;i++){
if(pFirst == NULL){
pNew->info++;
pFirst = pNew;
pLast = pNew;
printf("Ok, the list was empty.\n");
} else {
pNew->info++;
pLast-> pNext= pNew;
pLast= pNew;
printf("Ok, the list wasn't empty.\n");
}
}
print_list(pFirst);
Node *pNew; /* Declaring pNew *without* assignment. */
for(int i = 0; i < 3; i++){
pNew = (Node*) malloc(sizeof(Node)); /* Allocation of new memory address. */
pNew->info = i; /* pNew->info works like an ID in you current code. */
pNew->pNext = NULL; /* It is proper to assign NULL */
if(pFirst == NULL){
pNew->info++;
pFirst = pNew;
pLast = pNew;
printf("The list was empty.\n");
} else {
pNew->info++;
pLast->pNext = pNew;
pLast = pNew;
printf("The list wasn't empty.\n");
}
}
print_list(pFirst);