我正在尝试创建一个链表。当我在创建对象的同一个函数中添加到列表中时,它可以正常工作。
说明:
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;
}
然后在main函数中执行此操作:
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;
}
答案 0 :(得分:3)
以下是使用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()
可以复制传递的内容,或者安排将指针传递给main()
到add()
到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()
; &
中对add()
的每次调用都有一个main()
。结果是:
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
此代码泄漏内存,因为它不会尝试清理列表。暂时还可以。请注意,您最终需要清理。
答案 1 :(得分:1)
add函数还应该使用它添加“student”的链表(或“容器”)。
因此,您不应该在其中创建“temp”容器,而是使用传入的容器并添加到容器中传递的容器的后面。
编辑:刚刚意识到你的背部和前部都是全球性的。这可能不是一个好主意,因为这样你只能为整个程序提供一个链表。现在重读......
编辑2:啊,这是一个很好的。您正在传递学生(制作学生的副本)和然后在add函数中获取其地址,该函数是堆栈中变量的地址。弹出堆栈,因此堆栈中的变量地址没有意义。相反,add应该接收一个指向学生的指针,你应该传入stu2,stu3等的地址。编辑3:太晚了:(
答案 2 :(得分:1)
好的,我试过它正在运行。只能通过地址学生结构获取添加功能 如下
add(&stu2);
add(&stu3);
add(&stu4);
并更改添加功能如下
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;
}