C 初学者在这里,试图了解更多关于链表的信息。
下面的代码应该从一个名为"soldier"的结构创建一个循环双向链表。int n
很重要,因为它决定了创建的节点数,每个节点都包含一个值为n
的int data
,只要n=>1
。
所以当用户输入n=6
时,链表将如下所示:
6 <-> 5 <-> 4 <-> 3 <-> 2 <-> 1
^ ^
|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _|
我被困在这里已经有一段时间了。我试图看到我错过了什么,但看不到它。一切都编译文件,除了我只收到以下错误:[错误] 在"*"标记之前预期"="、"、";"、"asm"或"__attribute__">
#include<stdio.h>
#include<stdlib.h>
typedef struct nod{
int data;
struct nod *prev, *next;
}soldier;
soldier *head;
void soldier* create_soldier (int sequence){
if(head->data==NULL) //when the linked list starts
head->data = sequence;
else{
soldier *temp;
soldier *t;
temp= (soldier *) malloc(sizeof(soldier));
temp->data = sequence;
temp->next = NULL;
t= head; //Traversing
while (t->next != NULL)
t= t->next;
if(temp->data==1){ //for the rear end of the array to link back to the head
t->next = temp;
temp->prev = t;
temp->next = head;
head->prev = temp;
}
else{
t->next = temp;
temp->prev = t;
}
}
}
void display(soldier* head){
soldier *t;
t=head;
while (t->next != head){
printf("%d", t->data);
t= t->next;
}
}
void display(soldier* head){
soldier *t;
t=head;
while (t->next != head){
printf("%d", t->data);
t= t->next;
}
}
int main()
{
int n, k;
printf("Enter the number of soldiers to be executed");
scanf("%d", &n);
printf("Enter the number of soldiers to be skipped");
scanf("%d", &k);
for ( ; n>= 1; n--)
create_soldier(n);
display(head);
return 0;
}
有一些错误。返回类型不正确,数据初始化会发出警告,因为您正在比较指针和整数,但最重要的错误是您没有为 head 分配内存,并且您没有正确初始化"head"。另外,完成后您应该释放内存(我没有放进去)。我也没有检查代码是否完全按照您希望它执行的操作,但运行以下内容:
#include<stdio.h>
#include<stdlib.h>
typedef struct nod {
int data;
struct nod *prev, *next;
} soldier;
soldier *head;
void create_soldier (int sequence) {
if(head->data == 0) { // when the linked list starts
head->data = sequence;
head->prev = NULL;
head->next = NULL;
}
else{
soldier *temp;
soldier *t;
temp= (soldier *) malloc(sizeof(soldier));
temp->data = sequence;
temp->next = NULL;
t = head; //Traversing
while (t->next != NULL)
t = t->next;
if(temp->data==1){ //for the rear end of the array to link back to the head
t->next = temp;
temp->prev = t;
temp->next = head;
head->prev = temp;
}
else{
t->next = temp;
temp->prev = t;
}
}
}
void display(soldier* head){
soldier *t;
t=head;
while (t->next != head){
printf("%d", t->data);
t= t->next;
}
}
int main()
{
int n, k;
printf("Enter the number of soldiers to be executed");
scanf("%d", &n);
printf("Enter the number of soldiers to be skipped");
scanf("%d", &k);
head = (soldier *) malloc(sizeof(soldier));
for ( ; n>= 1; n--)
create_soldier(n);
display(head);
free(head);
return 0;
}
我发现了一些潜在的问题:
create_soldier
的原型有两种返回类型:
void soldier* create_soldier (int sequence){ ... }
你必须选择一个或另一个!我在函数中没有看到return
,所以它可能应该是一个void
函数,因为它目前的情况:
void create_soldier (int sequence){ ... }
您在此处将int
与NULL
进行比较:
if(head->data==NULL)
NULL
只能与指针进行有意义的比较,因此您可能打算将指针与士兵head
进行比较,而不是其data
成员:
if (head == NULL)
void display(soldier* head)
定义两次,因此您需要删除或重命名一个定义。它们看起来和我一模一样,所以我想你可以删除一个。
最后,使用完后,不要忘记free
您分配的内存malloc
。如果不这样做,最终会出现内存泄漏。对于一个小程序来说可能无关紧要,但尽早学习是一个好习惯。
看起来你正在解决约瑟夫斯问题!
这里有各种编译问题需要首先解决。使用类似标志编译代码
-Wall -Wextra -Werror -O2 -std=c99 -pedantic
如果你还没有。编码时,请经常编译和运行。使用 valgrind 等工具来验证您的代码不会泄漏内存并帮助检测分段错误。
编译器问题:
void soldier* create_soldier (int sequence)
是一个无效函数,因为它指定了两种返回类型。它应该是void create_soldier(int sequence)
的,因为它不返回任何内容。display
被定义两次。- 警告:
if(head->data==NULL)
比较int
和NULL
;您可能希望0
是一个有效的data
值,并且意图可能if (head == NULL)
。
运行时问题:
(head->data==NULL)
从create_solder
函数开始,但这会立即取消引用空指针。- 内存已分配,但未释放。
设计问题和风格建议:
- 全局变量
head
是不必要的。它应该在main
范围内,并传递给任何需要它的函数。 - 与前一点一致,这些函数是不可重用的,因为它们的实现完全绑定到全局变量
head
,例如,无法创建多个列表。尝试编写不会改变外部状态的纯函数。这使得程序不易出错,并且更容易推理。 - 为了与上一点保持一致,更喜欢使用通用名称(如
node
)作为代码,而不是soldier
。我们希望能够编写一个双向链表"类",并将其重用于任何目的(例如解决此特定问题)。如果需要,只需添加现有node
类型的typedef soldier
别名。 void create_soldier (int sequence)
不是一个非常有用的函数,因为我们很少需要使用来自1..n
的数据创建列表。更常见的是,我们只想创建一个node
并为其提供一些任意数据。考虑到这一点,我更喜欢void create_node(node **head, int data)
,它只会创建一个node
。然后我们可以在main
中运行一个循环,根据问题规范创建n
节点(或者为运行1..n
逻辑的create_node
编写一个包装函数)。- 首选
for
循环而不是while
循环。它们更干净,并使变量的范围保持良好和紧凑。 - 无需投射
malloc
的结果。
这是一个重写建议:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *prev, *next;
} node;
void create_node(node **head, int data) {
if (*head) {
node *new_node = malloc(sizeof(*new_node));
new_node->data = data;
new_node->next = *head;
new_node->prev = (*head)->prev;
(*head)->prev->next = new_node;
(*head)->prev = new_node;
}
else {
*head = malloc(sizeof(**head));
(*head)->data = data;
(*head)->prev = *head;
(*head)->next = *head;
}
}
void display(node *head) {
node *t = head;
if (t) {
printf("%d->", t->data);
for (t = t->next; t != head; t = t->next) {
printf("%d->", t->data);
}
puts("");
}
}
void free_list(node *head) {
node *t = head;
if (t) {
for (t = t->next; t != head;) {
node *dead_node = t;
t = t->next;
free(dead_node);
}
free(head);
}
}
int main() {
int n;
node *head = NULL;
printf("Enter the number of soldiers to be executed: ");
scanf("%d", &n);
for (int i = 0; i < n; create_node(&head, ++i));
display(head);
free_list(head);
return 0;
}