2011-12-19 50 views
0

我只允許使用下列頭scanf函數的char *字結構只顯示最後輸入

#include <stdio.h> 
#include <stdlib.h> 

,我定義我的struct student如下:

struct dict 
{ 
    char* word; 
    struct dict* link; 
}; 

有很多功能,但只有一個功能,我現在有問題。 該函數在鏈接的末尾插入一個結構字典,並帶有某個名稱。

struct student *Linsert(struct dict *list, char *name) 
{ 
    struct student *pnew; 
    struct student *pn; 
    int exist = 1; 

    pnew = (struct dict *)malloc(sizeof(struct dict)); 
    pnew -> next = NULL; 
    pnew -> name = name; 

    if (list != NULL) 
    { 
     for (pn = list; pn -> next != NULL; pn = pn -> next) ; 
     pn -> next = pnew; 
    } 
    else 
     list = pnew; 

    return list; 
} 

使用下面的函數,

//print all the values in the list 
void printList(struct dict* list); 

我這樣做:

int main(void) 
{ 

    struct dict *list = NULL; 

    char *name; 

    while (1) { 
     scanf("%s", name); 
     if (name == 'Q') 
      break; 

     list = Linsert(list, name); 
     printList(list); 
    } 
    return 0; 
} 

比方說輸入,我輸入3 applebananaorange,我的結果顯示了我最後的三個輸入。

這裏有什麼問題?

+1

始終用**所有警告**進行編譯,並且不要忽略其中的任何警告。 –

+0

請看看[如何格式化您的問題](http://stackoverflow.com/editing-help),特別是下一次如何格式化代碼塊。 –

+0

@KerrekSB'-Wall -Wextra -Werror'總是會導致更好的代碼':)' –

回答

2

main片斷就有問題一大堆:

  • name是未初始化的指針;它指向你尚未分配並允許使用的內存中未知的位置,因此導致未定義的行爲。也許你想char name[20]在棧上分配一個20個char的數組,並且有scanf在這個緩衝區中存儲輸入。

  • 你一個char*(一個指向字符串的開始)與單個char'Q' - 你要比較一個指針和一個整數值作爲你的編譯器警告會告訴你。您沒有爲字符串'Q'的值比較字符串的內容,而是將內存地址name'Q'的整數值進行比較。如果你想字符串name以字符串"Q"比較,使用strcmp併爲您的0

返回值,你也想被做傳遞給Linsert變量的副本,否則,當你」我們注意到,每次你都會傳遞一個指向內存中相同位置的指針,而對這塊內存的改變會改變你的每個項目。

如果你把你的編譯器警告起來,你會得到更多的警告。

1

您沒有爲該名稱分配任何內存,因此scanf正在寫入一些隨機位置,並且每次都通過循環覆蓋它。

1

一個問題是,您尚未爲word成員分配存儲以指向該存儲。您還沒有爲name指定空間。這是麻煩的主要原因。

您需要爲name分配空間;最簡單的方法是:

char name[128]; 

您需要分配空間來存儲的話,你需要的name內容複製到word這樣,當下一行覆蓋name,它不破壞保存word

適應你的代碼,你可以使用:

struct student *Linsert(struct dict *list, char *name) 
{ 
    struct student *pnew; 
    struct student *pn; 

    pnew = (struct dict *)malloc(sizeof(struct dict)); 
    if (pnew == 0) 
     ...error... 
    pnew->next = NULL; 
    pnew->word = malloc(strlen(name) + 1); 
    if (pnew->word == 0) 
     ...error... 
    strcpy(pnew->word, name); 

    if (list != NULL) 
    { 
     for (pn = list; pn->next != NULL; pn = pn->next) 
      ; 
     pn->next = pnew; 
    } 
    else 
     list = pnew; 

    return list; 
} 

不要忽略對內存分配錯誤檢查 - 痛苦的,雖然它是。當你忘記時它會咬你。

在風格上,不要在->.附近使用空格;他們是非常緊密結合的運營商,他們不應該像其他二元運營商一樣分開。

有一個方便的功能,strdup(),重複一個字符串,但它不是標準的C(它是標準的POSIX)。

3

我看到兩個問題與您的代碼:

  • 你需要傳遞一個scanf陣列char大小足以存儲輸入字符串的,不是簡單的字符指針。
  • 您需要將傳入的字符串複製到Linsert(使用strdup)。
0

由於name是一個字符指針,因此您對每個dict結構的字段的賦值將使用它指向的最新值。