2014-04-19 98 views
0

我想用一些值初始化一個結構數組,但我無法獲得值保持不變。我使用初始for循環來檢索字符串中的值並將它們分配給數組中的結構。一旦我嘗試用另一個循環遍歷該數組,其中一些值不相同。爲什麼結構初始化後結構的值會損壞?

這是有問題的代碼:

void printOrder(Order *node) 
    { 
     printf("Title is: %s\n",node->title); 
     printf("Price is: $%f\n",node->price); 
     printf("ID is: %d\n",node->custID); 
     printf("Category is: %s\n",node->category); 
    } 

    void initOrder(Order *newOrder, char *title, double price, int custID, char *category) 
    { 
     newOrder->title = title; 
     newOrder->price = price; 
     newOrder->custID = custID; 
     newOrder->category = category; 
     newOrder->next = NULL; 

     printf("new order object initialized\n"); 
    } 

    char *title; 
    char *priceTemp; 
    char *idTemp; 
    char *category; 

    Order localOrders[numOrders]; // numOrders is a value found earlier 

    int k; 
    for(k = 0; k < numOrders; k++) 
    { 

      fgets(Line,orderLineSize,orders); // orderLineSize was found earlier 


      title = strtok(Line,"|"); 
      priceTemp = strtok(NULL,"|"); 
      idTemp = strtok(NULL,"|"); 
      category = strtok(NULL,"|"); 

      price = atof(priceTemp); 
      id = atoi(idTemp); 

      localOrders[k].title = title; 
      localOrders[k].price = price; 
      localOrders[k].custID = id; 
      localOrders[k].category = category; 

      Order *temp = &localOrders[k]; 

      initOrder(temp,title,price,id,category); 
      printOrder(temp); 
    } 
    Order *temp; 

    for(k = 0; k < numOrders; k++) 
    { 
      temp = &localOrders[k]; 
      printOrder(temp); 
      printf("\n"); 
    } 

下面是一個Order頭文件:

#ifndef ORDER_H 
#define ORDER_H 
#include <stdlib.h> 
struct Order { 
    char *title; 
    double price; 
    int custID; 
    char *category; 

    struct Order *next; 
}; 

typedef struct Order Order; 

void initOrder(Order *newOrder, char *title, double price, int custID, char *category); 
void printOrder(Order *node); 

#endif 

例如,第一環路將打印:

Title is: "Tasting Beer: An Insider's Guide to the World's Greatest Drink" 
Price is: $11.310000 
ID is: 5 
Category is: HOUSING01 

作爲第二個循環會給我:

Title is: "Tasting Beer: An Insider's Guide to the World's Greatest Drink" 
Price is: $19.800000 
ID is: 2 
Category is: s Guide to the World's Greatest Drink" 

爲什麼我初始化第一個循環中的結構體的值在第二個循環中被覆蓋?標題似乎沒有受到影響,但其餘參數不斷被覆蓋,我不知道爲什麼。

+0

這似乎不是有效的C代碼。圍繞測試代碼丟失了一個函數? –

+0

要麼爲每個存儲的元素分配內存,要麼爲每個*行*(這是可行的,儘管更復雜)分配內存,但無論如何,每次讀取都在同一行緩衝區中爆炸,將之前存儲的'char * 'strtok'不會製作你的字符串的副本 – WhozCraig

+0

你爲什麼使用VLA? –

回答

1

strtok()返回指向字符緩衝區Line的指針,稍後將被覆蓋 當下一次調用fgets()時。

要保存的標記化字符串的「成分」,例如,您可以複製字符串與strdup()

title = strdup(strtok(Line,"|")); 
// ... 
+0

完美的工作!所以如果我理解正確,strtok()會返回指向'Line'中某個點的指針,而這些指針仍然指向相同的位置,即使用'fgets'生成了一個新的'Line'? – rafafan2010

+0

@ rafafan2010:是的,'Line'是(我假設)一個字符數組,如'char Line [MAXLINELENGTH]','fgets() '把讀取的輸入放到數組中,覆蓋以前的內容 - 並且當訂單被刪除時,不要忘記'釋放'重複的字符串 –

+0

謝謝!我會記住這麼做的 – rafafan2010

0

你需要爲每個數據元素分配內存。你正在做的是爲你的字符串使用相同的內存區域,只記住指向這些區域的指針,而不是爲每個字符串使用新的內存區域。

因此,您需要爲讀取的每個記錄分配一個新的內存區域,以便每條記錄都有自己的唯一內存區域,而不是共享相同內存區域的所有記錄。