在C语言中使用链表
我正在学习C语言编程,我遇到了一些麻烦,尤其是在使用指针时。这对我来说有点困难,因为我们在Java或C中不使用指针 我试图做的是创建一个链表(在互联网上找到的代码)并在其中推送元素。就像下面的代码一样 当我取消注释第二行代码时,代码会工作,但我会收到以下列表作为答案{0,1,2},即使我没有在列表中输入数字0。我想得到这个答案:{1,2}在C语言中使用链表,c,pointers,linked-list,C,Pointers,Linked List,我正在学习C语言编程,我遇到了一些麻烦,尤其是在使用指针时。这对我来说有点困难,因为我们在Java或C中不使用指针 我试图做的是创建一个链表(在互联网上找到的代码)并在其中推送元素。就像下面的代码一样 当我取消注释第二行代码时,代码会工作,但我会收到以下列表作为答案{0,1,2},即使我没有在列表中输入数字0。我想得到这个答案:{1,2} int main (){ node_t * test_list = NULL; //test_list = malloc(sizeof(no
int main (){
node_t * test_list = NULL;
//test_list = malloc(sizeof(node_t));
push(test_list, 1);
push(test_list, 2);
print_list(test_list);
return 0;
}
这是代码的样子:
typedef struct node
{
int val;
struct node * next;
} node_t;
void print_list(node_t * head)
{
node_t * current = head;
while (current != NULL)
{
printf("%d\n", current->val);
current = current->next;
}
}
node_t* new_node(node_t * head)
{
node_t * head2 = malloc(sizeof(node_t));
return head2;
}
void push(node_t * head, int val)
{
if (head == NULL)
{
head = new_node(head);
head->val = val;
head->next = NULL;
}
else
{
node_t * current = head;
while (current->next != NULL)
current = current->next;
/* now we can add a new variable */
current->next = malloc(sizeof(node_t));
current->next->val = val;
current->next->next = NULL;
}
}
在push函数中,我决定检查head是否等于NULL。如果是这样,我只想创建一个新节点并将其分配给它。我不知道这是不是个好办法。然而,它不起作用
如果有人能指引我走上正确的道路,我将不胜感激
谢谢大家!
(代码来源:)
尝试以下功能
node_t * new_node( int val )
{
node_t * n = malloc( sizeof( node_t ) );
if ( n )
{
n->val = val;
n->next = NULL;
}
return n;
}
void push( node_t **head, int val )
{
node_t *n = new_node( val );
if ( n )
{
while ( *head ) head = &( *head )->next;
*head = n;
}
}
函数push必须像
push( &test_list, 1 );
至于您的函数
push
实现,那么它将处理测试列表的副本。因此,test\u list
的原始值没有改变。我将尝试解释额外元素0
test_list = malloc(sizeof(node_t)); //this changes the pointer test_list
//which is initially NULL to a non-NULL pointer, hence the mysterious extra element "0"
push(test_list, 1);
void push(node_t * head, int val) {
if (head == NULL) //head is not NULL at this point because you called malloc earlier on it, so 1 will be inserted in the next position
{...}
您应该在malloc之后使用一些值初始化列表的头:
test_list = malloc(sizeof(node_t));
head->val = 5; //some value
head->next = NULL;
push(test_list, 1);
...
现在,第一个元素不是0,而是5。莫斯科的Vlad和Violeta Marin已经发布了它不起作用的原因。我对你的代码做了一些更改,使它起作用
#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int val;
struct node * next;
} node_t;
void print_list(node_t * head)
{
node_t * current = head;
printf("called\n");
while (current != NULL) {
printf("%d\n", current->val);
current = current->next;
}
}
node_t* new_node()
{
//you have to return NULL , if malloc fails to allocate memory
node_t * head2 = malloc(sizeof(node_t));
return head2;
}
void push(node_t **head, int val)
{
if (*head == NULL)
{
printf("null\n");
//you have to check the return value of new_node
(*head) = new_node();
(*head)->val = val;
(*head)->next = NULL;
}
else {
printf("not null\n");
node_t * current = *head;
while (current->next != NULL) {
current = current->next;
}
/* now we can add a new variable */
//you have to check the return value of malloc
current->next = malloc(sizeof(node_t));
current->next->val = val;
current->next->next = NULL;
}
}
void my_free(node_t *head)
{
node_t *temp= NULL;
while(head)
{
temp=head->next;
free(head);
head=temp;
}
}
int main ()
{
node_t *test_list = NULL;
push(&test_list, 1);
push(&test_list, 2);
print_list(test_list);
my_free(test_list);
return 0;
}
#包括
#包括
类型定义结构节点
{
int-val;
结构节点*下一步;
}节点t;
无效打印列表(节点头)
{
节点_t*电流=头部;
printf(“称为\n”);
while(当前!=NULL){
printf(“%d\n”,当前->值);
当前=当前->下一步;
}
}
node_t*新节点()
{
//如果malloc无法分配内存,则必须返回NULL
node_t*head2=malloc(sizeof(node_t));
返回头2;
}
无效推送(节点**头部,内部值)
{
如果(*head==NULL)
{
printf(“null\n”);
//您必须检查新_节点的返回值
(*head)=新的_节点();
(*头部)->val=val;
(*head)->next=NULL;
}
否则{
printf(“非空\n”);
节点_t*当前=*头部;
while(当前->下一步!=NULL){
当前=当前->下一步;
}
/*现在我们可以添加一个新变量*/
//您必须检查malloc的返回值
当前->下一步=malloc(sizeof(node_t));
当前->下一步->val=val;
当前->下一步->下一步=空;
}
}
无效我的空闲(节点头)
{
节点温度=NULL;
while(head)
{
温度=头部->下一步;
自由(头);
压头=温度;
}
}
int main()
{
节点测试列表=NULL;
推送(和测试列表,1);
推送(和测试列表,2);
打印测试列表(测试列表);
我的免费(测试列表);
返回0;
}
当您取消注释代码中的下一行时
//test_list = malloc(sizeof(node_t));
在这里,在调用push函数之前分配头指针。
因此,下面的代码行永远不会执行
if (head == NULL)
{
head = new_node(head);
head->val = val;
head->next = NULL;}
因为您已经为head指针malloced了一次,并且还没有初始化它,后面跟着两个push函数。因此,您将在列表中看到0/垃圾,1,2而不是1,2
当您为test_列表注释了malloc之后,在下面的代码段中
if (head == NULL)
{
head = new_node(head);
head->val = val;
head->next = NULL;
}else
{
node_t * current = head;
while (current->next != NULL) {
current = current->next;
}
由于您没有发送test_list的地址(&test_list-您需要使用双指针),因此在中对head所做的任何更改都不会反映在test_list中
浏览链接以获得清晰的理解-
以下代码:
1) corrects several oversights in the posted code
2) works correctly
3) contains the logic that (generally) is always used to
add a node to the end of a linked list
4) demonstrates that to change the contents of a passed in pointer
the simplest way is to pass '**'
and the caller passes the address of the pointer, not the contents of the pointer
5) uses consistent formatting
6) avoids unnecessary/misleading clutter/confusion in the definition of the struct
7) removes unnecessary parameters from functions
8) properly prototypes the functions
notice that the new_node() function prototype has '(void)'
while the actual function body just has '()'
#include <stdio.h>
#include <stdlib.h>
struct node
{
int val;
struct node * next;
};
// prototypes
void print_list( struct node * head);
struct node * new_node( void );
void push( struct node ** head, int val);
int main ( void )
{
struct node * test_list = NULL;
push(&test_list, 1);
push(&test_list, 2);
print_list(test_list);
return 0;
} // end function: main
// step through linked list, printing the val field from each node
void print_list( struct node * head)
{
struct node * current = head;
while (current != NULL)
{
printf("%d\n", current->val);
current = current->next;
}
} // end function: print_list
// create a new node
struct node * new_node()
{
struct node * head2 = NULL;
if( NULL == (head2 = malloc(sizeof( struct node))))
{ // then malloc failed
// handle error, cleanup, and exit
}
return head2;
} // end function: new_node
// append a new node to end of linked list
// need to use '**' so actual pointer in main() will be updated
void push( struct node ** head, int val)
{
struct node * current = NULL;
if (*head == NULL)
{ // then list is empty
current = new_node();
current->val = val;
current->next = NULL;
*head = current;
}
else
{
current = *head;
while (current->next != NULL)
{
current = current->next;
}
/* now we can append a new node to linked list */
current->next = new_node();
current->next->val = val;
current->next->next = NULL;
}
} // end function: push
1)纠正了发布代码中的几个疏忽
2) 工作正常
3) 包含(通常)始终用于
将节点添加到链接列表的末尾
4) 演示如何更改传入指针的内容
最简单的方法是通过'**'
调用者传递的是指针的地址,而不是指针的内容
5) 使用一致的格式
6) 避免结构定义中不必要的/误导性的混乱/混乱
7) 从函数中删除不必要的参数
8) 正确地设计函数的原型
请注意,新的_node()函数原型具有'(void)'
而实际的函数体只有'()'
#包括
#包括
结构节点
{
int-val;
结构节点*下一步;
};
//原型
作废打印列表(结构节点*头);
结构节点*新节点(无效);
无效推送(结构节点**head,int val);
内部主(空)
{
结构节点*test_list=NULL;
推送(和测试列表,1);
推送(和测试列表,2);
打印测试列表(测试列表);
返回0;
}//结束函数:main
//逐步浏览链表,打印每个节点的val字段
无效打印列表(结构节点*头)
{
结构节点*当前=头部;
while(当前!=NULL)
{
printf(“%d\n”,当前->值);
当前=当前->下一步;
}
}//结束函数:打印列表
//创建一个新节点
结构节点*新节点()
{
结构节点*head2=NULL;
if(NULL==(head2=malloc(sizeof(struct node)))
{//然后malloc失败了
//处理错误、清理和退出
}
返回头2;
}//结束函数:新建_节点
//将新节点附加到链表的末尾
//需要使用“**”,以便更新main()中的实际指针
无效推送(结构节点**head,int val)
{
结构节点*current=NULL;
如果(*head==NULL)
{//那么列表是空的
当前=新节点();
当前->val=val;
当前->下一步=空;
*水头=电流;
}
其他的
{
电流=*水头;
while(当前->下一步!=NULL)
{
当前=当前->下一步;
}
/*现在我们可以将一个新节点附加到链表中*/
当前->下一步=新建_节点();
当前->下一个->值=v