2010-03-17 32 views
0

我使用指針來存放名稱和研究實驗室屬性。但是,當我打印現有的頂點,當我打印頂點時,我無法正確看到所謂的屬性。 例如,雖然名字的真正價值在於「蘭斯洛特」,我認爲這是錯誤的,例如「asdasdasdasd」用於char的指針問題*

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"); 
    } 

回答

5

當你這樣做:

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

要複製的指針琴絃nameresearchLab。您不是自己複製字符串。換句話說,在此之後,newV->namename指向存儲名稱的內存中完全相同的位置;您尚未創建數據的重複副本。

既然你然後進行覆蓋在createNewPerson功能name數組,這個函數結束時,所有的vertex結構都會有自己的name屬性指向同一個內存位置,這是唯一的存儲輸入的姓氏。

更糟的是,當createNewPerson返回時,其本地name數組超出範圍,並被重新用於其他事情。既然你的頂點結構仍然指向這裏的name屬性,這就是你如何得到垃圾。

您需要複製字符串。一個簡單的方法來做到這一點是:

newV->name = strdup(name); 

您需要#include <string.h>得到strdup庫函數。

然後,當處理vertex結構時,還需要確保在name屬性上致電free

0

傳遞給GRAPHinsertV(名稱可變)被分配在createNewPerson()的堆棧,所以指針指向一個局部變量。一旦激活記錄被彈出,該值可以(並且將被)後續代碼覆蓋。

如果只打算在結構中保留char *,則需要在堆上分配內存。

Ex。取而代之的

char name[30]; 

你可以使用

char *name = (char *)malloc(30*sizeof(char)); 

但請記住,如果你手動分配它,你必須照顧釋放它爲好,否則將有內存泄漏。

0

當指定的char *名稱指針,就像

newV->name=name; 

你不是創建一個新的字符串,但使newV.name成員指向同一個存儲器作爲的char []數組,這是你需要malloc()或者分配一個新的char []數組來獲得每個結構的單獨存儲。

4

GRAPHinsertVnameresearchLab字符串的指針指針複製到矢量結構。

createNewPerson會爲nameresearchLab串的臨時

這裏的問題是,你指着一個臨時字符串時,你以後createNewPerson返回訪問它導致未定義行爲

要解決此問題,您可以使用malloc + strcpy或使用非標準strdup複製GRAPHinsertV中的字符串。

+0

'strdup'可能不是ISO C,但它是POSIX,所以它的唯一的「非標「在」選擇「等的意義上說。人。是「非標準的」。 – 2010-03-17 20:26:29

+0

@Tyler,是的,我在'strdup'上做我的作業,並且意識到它不像我想的那樣是GNU擴展,而是POSIX標準的一部分。不過,我認爲這條評論最好留在評論中。 – strager 2010-03-17 20:29:45

0

這裏有一個問題:

Vertex newV = malloc(sizeof newV); 

應該

Vertex *newV = malloc(sizeof(Vertex)); 
+0

我猜'Vertex'是'頂點*'的typedef,因爲大小寫不同。 – 2010-03-17 20:23:25

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有潛在的問題如果輸入我的名字,「大衛·索恩利」,對於名稱,因爲「%s」搜索一個空格分隔的字符串,如果我輸入「42」作爲ID,則不會在id中放置任何東西,如果我輸入一個名字或實驗室名稱超過29個字符,它將覆蓋其他內存

我建議使用fgets()來獲得每個答案的一行輸入,然後使用sscanf()解析它。

0

傳遞和分配字符串時,請始終複製它們。由於指針可能已被釋放,因此無法保證您收到的字符串仍然在內存中。

當然,如果你只打算使用name函數內(也就是,你不會把它分配給一個變量功能的範圍),你不必做複製。

爲了做到這一點,裏面GRAPHinsertV,而不是

newV->name=name; 

if (name != NULL)  // Preventing using null pointer 
{ 
    newV->name = malloc(strlen(name)+1); 
    strcpy(newV->name, name); 
}