繁体   English   中英

C中的char指针问题*

[英]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;

您正在将指针复制到字符串nameresearchLab 您不是在复制字符串本身。 换句话说,此后, newV->namename指向name在内存中存储的位置完全相同; 您尚未创建数据的重复副本。

由于您随后将继续覆盖createNewPerson函数中的name数组,因此在该函数结束时,所有vertex结构的name属性都指向相同的内存位置,该内存位置仅存储输入的姓氏。

更糟糕的是,当createNewPerson返回时,其本地name数组超出范围,并被重新用于其他用途。 由于您的顶点结构仍指向其name属性,因此这就是获取垃圾的方法。

您需要复制字符串。 一种简单的方法是:

newV->name = strdup(name);

您将需要#include <string.h>来获取strdup库函数。

然后,还需要确保在处置vertex结构时,对name属性进行free调用。

GRAPHinsertVname指针researchLab字符串复制到向量结构。

createNewPersonnameresearchLab字符串创建一个临时目录

这里的问题是,您指向一个临时字符串,该字符串在createNewPerson返回后访问它时会导致未定义的行为

要解决此问题,可以使用malloc + strcpy或使用非标准的strdupGRAPHinsertV复制字符串。

传递给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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM