我正在尝试创建一个链表。当我在创建对象的同一函数中添加到列表时,它起作用了。
定义:
typedef struct student {
int num;
char* name;
} student;
typedef struct container {
student* data;
struct container* next;
} container ;
我使用的所有对象都是这样初始化的:
student stu1;
stu1.num = 6;
stu1.name = "grefagf";
front = createContainer(&stu1);
back = front;
student stu2;
stu2.num = 3;
stu2.name = "dsghjyreawre";
student stu3;
stu3.num = 4;
stu3.name = "dsghhjrant";
student stu4;
stu4.num = 213;
stu4.name = "fdsafgrw";
当我将这些元素添加到主函数中的列表时,如下所示:
container* tmp;
tmp = createContainer(&stu2);
back->next = tmp;
back = tmp;
tmp = createContainer(&stu3);
back->next = tmp;
back = tmp;
tmp = createContainer(&stu4);
back->next = tmp;
back = tmp;
它正常工作,输出如下:
1: 6 grefagf
2: 3 dsghjyreawre
3: 4 dsghhjrant
4: 213 fdsafgrw
当我使用我制作的另一个函数打印它时。
但如果我创建一个名为 add()
的函数并传递 stu2、stu3...,如下所示:
int add(student to_add) {
container* tmp;
tmp = createContainer(&to_add);
printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name);
back->next = tmp;
back = tmp;
return 1;
}
然后在主函数中执行此操作:
add(stu2);
add(stu3);
add(stu4);
它输出这个:
1: 6 grefagf
2: 41096808 fdsafgrw
3: 41096808 fdsafgrw
4: 41096808 fdsafgrw
如果您需要,这里是源代码:
非函数示例:https://pastebin.com/ZLqTzp4t
#include <stdio.h>
#include <stdlib.h>
typedef struct student {
int num;
char* name;
} student;
typedef struct container {
student* data;
struct container* next;
} container ;
container* back;
container* front;
container* createContainer(student* data) {
container* tmp = malloc(sizeof(container));
tmp->data = data;
tmp->next = NULL;
return tmp;
}
void printList(container* front) {
container* tmp = front;
int i;
i=0;
while (tmp != NULL) {
i++;
printf("%d:\t%d\t\t%s\n", i, tmp->data->num, tmp->data->name);
tmp = tmp->next;
}
}
int main(void) {
student stu1;
stu1.num = 6;
stu1.name = "grefagf";
front = createContainer(&stu1);
back = front;
student stu2;
stu2.num = 3;
stu2.name = "dsghjyreawre";
student stu3;
stu3.num = 4;
stu3.name = "dsghhjrant";
student stu4;
stu4.num = 213;
stu4.name = "fdsafgrw";
container* tmp;
tmp = createContainer(&stu2);
back->next = tmp;
back = tmp;
tmp = createContainer(&stu3);
back->next = tmp;
back = tmp;
tmp = createContainer(&stu4);
back->next = tmp;
back = tmp;
printf("front\n");
printList(front);
printf("\ntop\n");
printList(back);
return EXIT_SUCCESS;
}
函数示例:https://pastebin.com/TyQY4j5k
#include <stdio.h>
#include <stdlib.h>
typedef struct student {
int num;
char* name;
} student;
typedef struct container {
student* data;
struct container* next;
} container ;
container* back;
container* front;
container* createContainer(student* data) {
container* tmp = malloc(sizeof(container));
tmp->data = data;
tmp->next = NULL;
return tmp;
}
int add(student to_add) {
container* tmp;
tmp = createContainer(&to_add);
printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name);
back->next = tmp;
back = tmp;
return 1;
}
void printList(container* front) {
container* tmp = front;
int i;
i=0;
while (tmp != NULL) {
i++;
printf("%d:\t%d\t\t%s\n", i, tmp->data->num, tmp->data->name);
tmp = tmp->next;
}
}
int main(void) {
student stu1;
stu1.num = 6;
stu1.name = "grefagf";
front = createContainer(&stu1);
back = front;
student stu2;
stu2.num = 3;
stu2.name = "dsghjyreawre";
student stu3;
stu3.num = 4;
stu3.name = "dsghhjrant";
student stu4;
stu4.num = 213;
stu4.name = "fdsafgrw";
add(stu2);
add(stu3);
add(stu4);
printf("front\n");
printList(front);
printf("\ntop\n");
printList(back);
return EXIT_SUCCESS;
}
最佳答案
这是带有 add
功能的代码的或多或少的最小版本。它以 60 行运行,而原始版本为 83 行。
#include <stdio.h>
#include <stdlib.h>
typedef struct student
{
int num;
char *name;
} student;
typedef struct container
{
student *data;
struct container *next;
} container;
static container *back;
static container *front;
static container *createContainer(student *data)
{
container *tmp = malloc(sizeof(container));
tmp->data = data;
tmp->next = NULL;
return tmp;
}
static void add(student to_add)
{
container *tmp = createContainer(&to_add);
printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name);
back->next = tmp;
back = tmp;
}
static void printList(container *item)
{
for (int i = 0; item != NULL; item = item->next)
printf("%d:\t%d\t\t%s\n", ++i, item->data->num, item->data->name);
}
int main(void)
{
student stu1 = { 6, "grefagf" };
student stu2 = { 3, "dsghjyreawre" };
student stu3 = { 4, "dsghhjrant" };
student stu4 = { 213, "fdsafgrw" };
front = createContainer(&stu1);
back = front;
add(stu2);
add(stu3);
add(stu4);
printf("front\n");
printList(front);
printf("\nback\n");
printList(back);
return EXIT_SUCCESS;
}
在我的 Mac 上,它产生了:
added: (3, dsghjyreawre)
added: (4, dsghhjrant)
added: (213, fdsafgrw)
front
1: 6 grefagf
2: 0
3: 0
4: 0
back
1: 0
问题是您将局部变量的地址传递给 createContainer()
函数,但该变量超出范围,因此您的容器指向垃圾。由于这是调用未定义的行为,因此您的机器上的结果可能不同,但两者都是正确的。崩溃也是可能的——这是 UB 的优点之一。
您需要通过以下两种方式之一修改它。 createContainer()
复制它所传递的内容,或者您安排通过 add()
将指针传递给 main()
中的变量> 到 createContainer()
。此代码执行第二个 — 但从长远来看,它可能不是更好的解决方案。但是,对于复制传递的内容的通用解决方案,需要处理(很多)更多的内存管理。
#include <stdio.h>
#include <stdlib.h>
typedef struct student
{
int num;
char *name;
} student;
typedef struct container
{
student *data;
struct container *next;
} container;
static container *back;
static container *front;
static container *createContainer(student *data)
{
container *tmp = malloc(sizeof(container));
tmp->data = data;
tmp->next = NULL;
return tmp;
}
static void add(student *to_add)
{
container *tmp = createContainer(to_add);
printf("added: (%d, %s)\n", tmp->data->num, tmp->data->name);
back->next = tmp;
back = tmp;
}
static void printList(container *item)
{
for (int i = 0; item != NULL; item = item->next)
printf("%d:\t%d\t\t%s\n", ++i, item->data->num, item->data->name);
}
int main(void)
{
student stu1 = { 6, "grefagf" };
student stu2 = { 3, "dsghjyreawre" };
student stu3 = { 4, "dsghhjrant" };
student stu4 = { 213, "fdsafgrw" };
front = createContainer(&stu1);
back = front;
add(&stu2);
add(&stu3);
add(&stu4);
printf("front\n");
printList(front);
printf("\nback\n");
printList(back);
return EXIT_SUCCESS;
}
这里有5个字符与上一个版本不同。 add()
的函数定义中有一个*
; createContainer()
的调用中没有 &
;在 main()
中对 add()
的每个调用中都有一个 &
。结果是:
added: (3, dsghjyreawre)
added: (4, dsghhjrant)
added: (213, fdsafgrw)
front
1: 6 grefagf
2: 3 dsghjyreawre
3: 4 dsghhjrant
4: 213 fdsafgrw
back
1: 213 fdsafgrw
此代码会泄漏内存,因为它不会尝试清理列表。暂时可以。请注意,您最终需要进行清理。
关于c - 为什么在使用函数时无法正确添加到链表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48735436/