用于char *的C中的指针问题

时间:2010-03-17 20:16:20

标签: c char printing

我使用指针来保存名称和研究实验室属性。但是当我打印现有的顶点时,当我打印顶点时,我无法正确看到所谓的属性。 例如,虽然名称的实际值是 “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");
    }

7 个答案:

答案 0 :(得分:5)

执行此操作时:

   newV->name=name;
   newV->researchLab=researchLab;

您正在将指针复制到字符串nameresearchLab。您没有自己复制字符串。换句话说,在此之后,newV->namename指向存储名称的内存中的完全相同的位置;您尚未创建数据的副本。

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

更糟糕的是,当createNewPerson返回时,其本地name数组超出范围,并被重新用于其他事情。由于你的顶点结构仍然指向它们的name属性,这就是你如何得到垃圾。

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

newV->name = strdup(name);

您需要#include <string.h>才能获得strdup库函数。

然后,您还需要确保在处置free结构时在name属性上调用vertex

答案 1 :(得分:4)

GRAPHinsertVnameresearchLab字符串的指针复制到矢量结构中。

createNewPersonnameresearchLab字符串创建临时

问题在于,您指的是临时字符串,当您在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);
}