我有一个C程序在链表的开头插入元素,但是当我尝试打印元素时,它总是跳过第一个元素。有人可以指出我在我的计划中做错了什么。
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
void PrintElements();
void InsertElement(int x);
struct node
{
int data;
struct node* next;
};
struct node* HEAD;
struct node* temp;
struct node* temp1;
void PrintElements()
{
temp1=HEAD;
while(temp1->next!=NULL)
{
printf("\n\r Data %d\n\r",temp1->data);
printf("\n\r Address %x\n\r",temp1->next);
temp1=temp1->next;
}
}
void InsertElement(int x)
{
struct node* temp=(struct node*)malloc(sizeof(struct node));
temp->data=x;
temp->next=HEAD;
HEAD=temp;
}
int main()
{
int i, x;
int n; //n stores the number of elements to be added to the linked list
HEAD=NULL; //Assigning HEAD to null when there are no elements in the list
printf("Enter the number of elements\n");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("\n\rEnter the number");
scanf("%d",&x);
InsertElement(x);
PrintElements();
}
return 0;
}
当我更改以下行
时while(temp1->next!=NULL)
到
while(temp1!=NULL)
程序正常运行但我仍然无法理解原因。
答案 0 :(得分:3)
while(temp1->next!=NULL)
将此更改为
while(temp1 != NULL)
它应该可以正常工作。
原因:我认为它不会打印您输入的第一个元素。
示例:输入:1 2 3
链接列表形成为:3 -> 2 -> 1 -> NULL
使用的表示法:每个数字都是data
,箭头显示指针next
。
然后当你开始循环时,对于每次迭代:
temp1
指向3
temp1 -> next != NULL
(正如temp1 -> next
指向2
的地址)
打印3
和temp1
现在指向2
的地址
temp1 -> next != NULL
(正如temp1 -> next
指向1
的地址)
打印2
和temp1
现在指向1
的地址
temp1 -> next != NULL
由于temp1
指向1
的地址且temp1 -> next
为NULL,因此变为错误。
所以我们永远不会进入循环来打印1
。
所以正确的方法是使用temp1 != NULL
,因为这将消除上述错误。
答案 1 :(得分:1)
您可以通过将PrintElements()
功能中的控制表达式更改为temp1 != NULL
来解决您描述的问题。这样,如果temp1
指向某个节点,则会打印data
和next
字段,并且循环将继续,直到没有更多节点为止。当迭代链表时,当您查看下一个节点以决定对当前节点执行的操作时,通常会出现混淆。但是这个代码还有其他问题。
首先,在struct
中声明main()
指针并将它们传递给函数会更好,而不是将它们声明为全局变量。您应该检查尽可能调用的函数的返回值。您应该检查scanf()
以确保输入符合预期;这也提供了一种控制输入循环的方法,消除了用户在输入数据之前显式输入计数的需要。您还应检查调用malloc()
返回的值以捕获分配错误。如果在下一行中取消引用temp
,代码中的这种分配错误将导致未定义的行为。
对于free
的每次调用,您应该free()
所有内存分配,一个malloc()
。当您在函数next
中的列表中打印PrintElements()
节点的地址时,将调用未定义的行为。要打印指针的值,您应该使用%p
格式说明符,并且必须将指针强制转换为(void *)
。最后,没有必要#include <malloc.h>
; stdlib.h
会照顾您的需求。
以下是修改后的代码版本,用于实现建议的更改。请注意,如果出现分配错误,会向stderr
和程序exit
打印一条消息。对malloc()
的调用已经简化:没有理由在C中转换malloc()
的结果,最好使用指定内存的指针的名称来代替给malloc()
的参数中的显式类型。 new_node
返回到调用函数,其中指向列表head
的指针被重新分配以指向new_node
。
#include <stdio.h>
#include <stdlib.h>
struct node
{
int data;
struct node* next;
};
void print_elements(struct node *start);
struct node * insert_element(int x, struct node *head);
int main(void)
{
struct node* head = NULL;
struct node* curr = NULL;
int x;
/* Read data into linked list */
printf("Enter the first integer (q to quit): ");
while (scanf("%d", &x) == 1) {
head = insert_element(x, head);
print_elements(head);
printf("Enter another integer (q to quit): ");
}
/* Free allocated memory */
while (head) {
curr = head;
head = curr->next;
free(curr);
}
return 0;
}
void print_elements(struct node *curr)
{
while(curr) {
printf(" Data: %d\n",curr->data);
printf("Address: %p\n\n",(void *) curr->next);
curr = curr->next;
}
}
struct node * insert_element(int x, struct node *head)
{
struct node *new_node = malloc(sizeof(*new_node));
if (new_node == NULL) {
fprintf(stderr, "Allocation error in function insert_element()\n");
exit(EXIT_FAILURE);
}
new_node->data = x;
new_node->next = head;
return new_node;
}