我使用指针来保存名称和研究实验室属性。但是当我打印现有的顶点时,当我打印顶点时,我无法正确看到所谓的属性。 例如,虽然名称的实际值是 “lancelot” ,但我认为它是错误的,例如 “asdasdasdasd”
struct vertex {
int value;
char*name;
char* researchLab;
struct vertex *next;
struct edge *list;
};
void GRAPHinsertV(Graph G, int value,char*name,char*researchLab) {
//create new Vertex.
Vertex newV = malloc(sizeof newV);
// set value of new variable to which belongs the person.
newV->value = value;
newV->name=name;
newV->researchLab=researchLab;
newV->next = G->head;
newV->list = NULL;
G->head = newV;
G->V++;
}
/***
The method creates new person.
**/
void createNewPerson(Graph G) {
int id;
char name[30];
char researchLab[30];
// get requeired variables.
printf("Enter id of the person to be added.\n");
scanf("%d",&id);
printf("Enter name of the person to be added.\n");
scanf("%s",name);
printf("Enter researc lab of the person to be added\n");
scanf("%s",researchLab);
// insert the people to the social network.
GRAPHinsertV(G,id,name,researchLab);
}
void ListAllPeople(Graph G)
{
Vertex tmp;
Edge list;
for(tmp = G->head;tmp!=NULL;tmp=tmp->next)
{
fprintf(stdout,"V:%d\t%s\t%s\n",tmp->value,tmp->name,tmp->researchLab);
}
system("pause");
}
答案 0 :(得分:5)
执行此操作时:
newV->name=name;
newV->researchLab=researchLab;
您正在将指针复制到字符串name
和researchLab
。您没有自己复制字符串。换句话说,在此之后,newV->name
和name
指向存储名称的内存中的完全相同的位置;您尚未创建数据的副本。
由于您继续覆盖name
函数中的createNewPerson
数组,因此在此函数的末尾,您的所有vertex
结构都将具有name
属性指向相同的内存位置,该位置仅存储输入的姓氏。
更糟糕的是,当createNewPerson
返回时,其本地name
数组超出范围,并被重新用于其他事情。由于你的顶点结构仍然指向它们的name
属性,这就是你如何得到垃圾。
您需要复制字符串。一个简单的方法是:
newV->name = strdup(name);
您需要#include <string.h>
才能获得strdup
库函数。
然后,您还需要确保在处置free
结构时在name
属性上调用vertex
。
答案 1 :(得分:4)
GRAPHinsertV
将name
和researchLab
字符串的指针复制到矢量结构中。
createNewPerson
为name
和researchLab
字符串创建临时。
问题在于,您指的是临时字符串,当您在createNewPerson
返回后访问它时会导致未定义的行为。
要解决此问题,您可以使用GRAPHinsertV
+ malloc
或使用非标准strcpy
复制strdup
中的字符串。
答案 2 :(得分:0)
传递给GRAPHinsertV()的名称变量在createNewPerson()的堆栈上分配,因此指针指向局部变量。一旦弹出激活记录,该值就可以(并且将被后续代码覆盖)。
如果你只想在结构中保留一个char *,你需要在堆上分配内存。
实施例。而不是
char name[30];
你可以使用
char *name = (char *)malloc(30*sizeof(char));
但请记住,如果你手动分配它,你也必须小心释放它,否则会有内存泄漏。
答案 3 :(得分:0)
分配char * name指针时,如
newV->name=name;
您没有创建新字符串,但是使newV.name成员指向与传入的char []数组相同的内存。您需要malloc()或以其他方式分配新的char [ ]数组,以便为每个结构获得单独的存储空间。
答案 4 :(得分:0)
这里有一个问题:
Vertex newV = malloc(sizeof newV);
应该是
Vertex *newV = malloc(sizeof(Vertex));
答案 5 :(得分:0)
您正在函数createNewPerson()
中分配内存,该内存与createNewPerson()
正在执行时完全相同,并且可以在返回后立即覆盖。您需要使用strdup(newV->name, name)
之类的内容复制文本字段,而不是指向createNewPerson()
中的局部变量。 (如果您的实施没有strdup()
,您可以轻松地将其定义为:
char * strdup(const char *inp)
{
char * s = malloc(strlen(inp) + 1);
strcpy(s, inp);
return s;
}
此外,您的I / O存在潜在问题。如果您输入我的名字“David Thornley”作为名称,它将以“David”作为名称,将“Thornley”作为实验室,因为“%s”会搜索以空格分隔的字符串。如果我为ID输入“四十二”,则id
中不会放置任何内容,并且将使用“四十二”作为名称。如果我输入超过29个字符的名称或实验室名称,它将覆盖其他内存。
我建议使用fgets()
为每个答案获取一行输入,然后使用sscanf()
来解析它。
答案 6 :(得分:0)
传递和分配字符串时,请始终复制它们。由于指针可能已被释放,因此无法保证您收到的字符串之后仍然在内存中。
当然,如果你只是在函数内部使用name
(也就是说,你不会将它分配给 函数范围内的变量),你不必复制。
为了做到这一点,请在GRAPHinsertV
内,而不是
newV->name=name;
做
if (name != NULL) // Preventing using null pointer
{
newV->name = malloc(strlen(name)+1);
strcpy(newV->name, name);
}