2012-08-05 58 views
1
typedef struct Data* DATAS; 

    struct Data { 
     char *name; 
     char *city; 
     DATAS next; 
    }; 
    typedef struct Data DATA; 

    int main(void){ 
    DATAS tmp; 

    tmp=(DATAS) malloc(sizeof(DATA)); 
    printf("please enter name:\n"); 
    scanf("%s",&tmp->name); 
    printf("%s\n",&tmp->name); 
    printf("please enter city:\n"); 
    scanf("%s",&tmp->city); 
    printf("%s\n",&tmp->name); 
    printf("%s\n",&tmp->city); 

    return 0; 
    } 

這是一個家庭作業的一部分。或者說是這個概念。我需要使用'typedef struct Data * DATAS'這是拋棄我。當我運行這個時,我用城市的一部分覆蓋了名字,所以我得到了這個結果。C結構與指針認爲我沒有正確分配內存

please enter name: 
name 
name 
please enter city: 
city 
namecity 
city 

任何幫助將是偉大的。謝謝。我已經使用

tmp=(DATAS) malloc(sizeof(DATA)); 
tmp=(DATA) malloc(sizeof(DATA)); 

回答

4

分配一個struct Data的最佳方式是:

struct Data *tmp; 
tmp = malloc(sizeof *tmp); 
if (tmp == NULL) { 
    /* malloc failed, abort or take corrective action */ 
} 

定義爲指針類型一個typedef不建議(至少由我);使用struct Data *明確地向讀者說明你正在處理指針。

定義結構類型的typedef也是不必要的。 typedef只是爲現有類型聲明一個新名稱;你的類型已經有了一個非常好的名字,struct Data。無可否認,您必須重複鍵入struct關鍵字,但這不是一個真正的問題。

施放malloc的結果是不必要的; malloc返回一個void*結果,它可以隱式轉換爲指針類型。演員可以隱藏錯誤,例如忘記所需的#include <stdlib.h>

但這些都是風格問題。您目前的代碼:

tmp=(DATAS) malloc(sizeof(DATA)); 

是好的,它應該工作。問題在後面的代碼中。

scanf"%s"格式期望char* argument. You're giving it the *address* of a char *對象,即類型爲char**的值。編譯器不一定會提醒你。所以這個:

scanf("%s",&tmp->name); 

應該是:

scanf("%s", tmp->name); 

但是,這仍然是一個問題,因爲tmp->name是未初始化的指針。它可能指向內存中的某個隨機位置,並且該調用嘗試在該位置存儲數據。或者它可能包含無效地址,導致崩潰。行爲是未定義的。

您需要分配空間來保存名稱,並使tmp->name指向它。您可能需要在此處撥打另一個malloc()

那麼你需要分配多少空間?那麼,對此沒有好的答案,因爲scanf("%s", ...)對它將讀取的字節數沒有限制。然而,分配的空間很大,如果輸入足夠的數據,則可以將其溢出。

您可能不需要擔心這一點;請牢記未來。現在,您可以分配「足夠」的空間(比如100個字節),並小心不要輸入太多的數據。這應該足以讓你的程序工作。 (檢查文檔scanf,並考慮使用類似"100s"

而且記住,scanf("%s", ...")讀取空格分隔的輸入字符串;如果您鍵入「John Doe」,則只會讀取「John」,並在下一個輸入操作中留下「Doe」。

(我希望這不是太勢不可擋。)

+0

這太好了。沒有比一般的指針更令人沮喪的了。正當我想我已經把它放下時,我感到困惑。我正在使用'&tmp-> name',因爲你指出'tmp-> name'崩潰了。我認爲'tmp =(DATAS)malloc(sizeof(DATA));'會爲包括'name'和'city'在內的整個結構分配內存。 – ScottEdge 2012-08-05 03:50:54

+0

我想你會發現[comp.lang.c FAQ](http://www.c-faq.com/)是一個有價值的資源。 – 2012-08-05 03:53:04

2

你傳入未初始化的指針scanf,使用它們來進行寫入嘗試的malloc的不同變體;這是未定義的行爲。您還將字符串指針的地址傳遞給scanfprintf; C中的字符串已經是指針了,你不應該將指針傳遞給I/O例程。

如果您知道字符的名稱數量限制/城市名稱,你可以閱讀的字符串是這樣的:

char buf[128]; // 127 is the limit; buffer needs an extra character 
printf("please enter name:\n"); 
scanf("%127s", buf); 
size_t len = strlen(buf)+1; // plus one for null terminator 
tmp->name = malloc(len); 
strcpy(tmp->name, buf); 
printf("%s\n", tmp->name); // No ampersand 
+0

謝謝,這是非常有幫助的 – ScottEdge 2012-08-05 03:46:54

+0

我將給出答案基思·湯普森因爲他給的解釋。如果我可以upvote你回答我會的。 – ScottEdge 2012-08-05 03:52:55

0

您已經分配給包含三個三分球結構的空間。您還需要爲兩個字符串分配空間。您還應該確保next字段被適當地初始化 - 可能爲NULL。

就個人而言,我不打擾DATAS typedef,並且儘可能最好保留宏的所有大寫名稱(FILE *類型儘管)。