[英]Pointer problem in C for char*
我使用指针来持有名称和研究实验室的财产。 但是当我打印现有的顶点时,当我打印顶点时,我看不到所谓的属性。 例如,尽管名称的实际值是“ 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");
}
执行此操作时:
newV->name=name;
newV->researchLab=researchLab;
您正在将指针复制到字符串name
和researchLab
。 您不是在复制字符串本身。 换句话说,此后, newV->name
和name
指向name
在内存中存储的位置完全相同; 您尚未创建数据的重复副本。
由于您随后将继续覆盖createNewPerson
函数中的name
数组,因此在该函数结束时,所有vertex
结构的name
属性都指向相同的内存位置,该内存位置仅存储输入的姓氏。
更糟糕的是,当createNewPerson
返回时,其本地name
数组超出范围,并被重新用于其他用途。 由于您的顶点结构仍指向其name
属性,因此这就是获取垃圾的方法。
您需要复制字符串。 一种简单的方法是:
newV->name = strdup(name);
您将需要#include <string.h>
来获取strdup
库函数。
然后,还需要确保在处置vertex
结构时,对name
属性进行free
调用。
GRAPHinsertV
将name
的指针和researchLab
字符串复制到向量结构。
createNewPerson
为name
和researchLab
字符串创建一个临时目录 。
这里的问题是,您指向一个临时字符串,该字符串在createNewPerson
返回后访问它时会导致未定义的行为 。
要解决此问题,可以使用malloc
+ strcpy
或使用非标准的strdup
在GRAPHinsertV
复制字符串。
传递给GRAPHinsertV()的名称变量在堆栈上分配给createNewPerson(),因此指针指向局部变量。 一旦激活记录弹出,该值就可以(并且将被)后续代码覆盖。
如果仅要将char *保留在结构中,则需要在堆上分配内存。
例如 代替
char name[30];
你可以用
char *name = (char *)malloc(30*sizeof(char));
但请记住,如果您手动分配它,则还必须注意释放它,否则它将发生内存泄漏。
当您分配char * name指针时,例如
newV->name=name;
您不是在创建新字符串,而是使newV.name成员指向与传入的char []数组相同的内存。您将需要malloc()或在其中分配一个新的char []数组。为了获得每个结构的单独存储。
这里有个问题:
Vertex newV = malloc(sizeof newV);
它应该是
Vertex *newV = malloc(sizeof(Vertex));
您正在函数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”搜索以空格分隔的字符串。 如果我输入“ 42”作为ID,则不会在id
放置任何内容,而“ 42”将用作名称。 如果我输入的名称或实验室名称超过29个字符,它将覆盖其他内存。
我建议使用fgets()
获得每个答案的一行输入,然后使用sscanf()
进行解析。
传递和分配字符串时,请始终复制它们。 由于指针可能已经释放,因此不能保证以后收到的字符串仍在内存中。
当然,如果仅在函数内部使用name
(也就是说,您不会将其分配给函数范围以外的变量),则不必执行复制操作。
为此,请在GRAPHinsertV
,而不是
newV->name=name;
做
if (name != NULL) // Preventing using null pointer
{
newV->name = malloc(strlen(name)+1);
strcpy(newV->name, name);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.