2010-05-14 69 views
1

我試圖用結構和文件做一個程序。以下是我的代碼的一部分(它不是整個程序)。 我想要做的是:讓用戶寫他的命令。例如。刪除約翰 例如。輸入John James 5000 ipad購買。構造,strtok,分段錯誤

問題是我想拆分命令爲了保存它的'args'爲一個struct元素。這就是我使用strtok的原因。但是我正在面臨另一個問題,那就是誰在結構上「放置」這些問題。 此外,我似乎很奇怪如何以安全的方式將'args''傳遞'到結構中,因爲我將所有輸入(來自用戶)保存在二進制文件中,可能會重新打開並重新編輯,因此我無法使用:

strcpy(catalog[0]->short_name, args[1]); 

因爲是時候短名稱將被保存在結構的第一個元素中。但是,如果文件被寫入會發生什麼呢?第一個元素存在,所以如果我寫.. [0]我會寫上它? 我該怎麼辦?提前感謝任何幫助! :d

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#define MAX 100 

char command[1500]; 

struct catalogue     
{ 
     char short_name[50]; 
     char surname[50]; 
     signed int amount; 
     char description[1000]; 
}*catalog[MAX]; 

int main (int argc, char *argv[]) 
{ 
    int i,n; 
    char choice[3]; 

    printf(">sort1: Print savings sorted by surname\n"); 
    printf(">sort2: Print savings sorted by amount\n"); 
    printf(">search+name:Print savings of each name searched\n"); 
    printf(">delete+full_name+amount: Erase saving\n"); 
    printf(">enter+full_name+amount+description: Enter saving \n"); 
    printf(">quit: Update + EXIT program.\n"); 

    printf("Choose your selection:\n>"); 
    gets(command);      //it save the whole command 

    /*in choice it;s saved only the first 2 letters(needed for menu choice again)*/ 
    strncpy(choice,command,2);  
    choice[2]='\0';     

char** args = (char**)malloc(strlen(command)*sizeof(char*)); 
memset(args, 0, sizeof(char*)*strlen(command)); 

char* temp = strtok(command, " \t"); 

for (n = 0; temp != NULL; ++n) 
{ 
    args[n] = strdup(temp); 
    temp = strtok(NULL, " \t"); 
    printf(" %s ",args[n]); 
} 

strcpy(catalog[0]->short_name, args[1]);   //segmentation fault 
strcpy(catalog[0]->surname,args[2]); 
catalog[0]->amount=atoi(args[3]);    //atoi doesn't work 
strcpy(catalog[0]->description,args[4]); 


} 

結果,運行該程序後,我收到了分割錯誤... 爲線:

strcpy(catalog[0]->short_name, args[1]); 

任何幫助嗎?有任何想法嗎?

+0

我不是C程序員,但對於您的問題標題,有些人不喜歡說「help plz」的人:http://meta.stackexchange.com/questions/48024/what-is- up-with-everyone-always-saying-plz-help – 2010-05-14 13:19:42

+0

;)okkkk!hehehe thnx Andrew – FILIaS 2010-05-14 13:27:27

回答

1

for循環在時間(args[n] = ...)分配一個參數,但隨後在每次通過訪問幾個參數:*args[1]args[2],等等,這些都在第一遍初始化。

該警告是由於另一個錯誤。你不能只指定一個指向這樣的數組的指針。改爲使用strcpy()

+0

是的,這是真的,我試圖把它從目錄[0] - > short_name的循環。 。 但我得到相同的警告 – FILIaS 2010-05-14 13:26:49

+0

strcpy(catalog [0] - > short_name,args [1]); 再一次...分割錯誤 如果'參數'是一個數字呢? atoi不起作用! – FILIaS 2010-05-14 13:39:29

+0

更新問題。 – 2010-05-14 14:02:21

1

您的數組catalouge是一個指針數組,而不是對象的數組,但這些指針不被初始化到任何東西,因此賽格故障

嘗試:

struct catalogue     
{ 
     char short_name[50]; 
     char surname[50]; 
     signed int amount; 
     char description[1000]; 
}catalog[MAX]; 



strcpy(catalog[0].short_name, args[1]);   //segmentation fault 
strcpy(catalog[0].surname,args[2]); 
catalog[0].amount=atoi(args[3]);    //atoi doesn't work 
strcpy(catalog[0].description,args[4]); 
+0

Thnx Necropolis!這是一個很好的幫助! :D – FILIaS 2010-05-14 14:29:40

4

你有2錯誤:

  1. catalog[MAX]數組保存MAX指向你的struct catalogue,但他們沒有被初始化。解決這個問題的辦法是要麼不聲明它們是指針,或者malloc他們根據需要,就像在catalog[0] = (struct catalogue *)malloc(sizeof(struct catalogue));

  2. args變量是壞的。首先,我不認爲你打算創建一個長度爲命令字符串長度的字符串數組。這意味着如果您輸入「sort1」,您將創建args[5]。這是荒謬的,因爲你的命令的長度與它應該有多少個參數無關。

    但假設你真的想這樣做,你正在爲數組創建空間,但不是爲數組中的字符串創建空間。無論如何,最終你會得到一個段錯誤(雖然你得到的是上面的#1),因此。當您使用它時,您需要爲args中的每個元素分配空間。

的代碼看起來是這樣的:

for (n = 0; temp != NULL; ++n) 
{ 
    args[n] = (char *)malloc((strlen(temp) + 1) * sizeof(char)); 
    strcpy(args[n], temp); 
    // and so on 
} 
1

很多在這段代碼的問題

首先,您對輸入行中參數的數目感到困惑,因爲該參數中的條目數量。在一種情況下,您使用n來計算參數的數量,但在另一種情況下,您正在使用它來索引catalog陣列。

你正在創建你不需要的內存管理頭痛。 args變量是完全沒有必要的,而且你不正確地爲它分配內存。你基本上說,「分配字符指針爲每個字符command,這可能不是你想要的

失去args完全的;你不需要它

我意識到這一點。不是你的整個程序,但目前還不清楚爲什麼你要創建catalog作爲指向struct catalog的指針數組,而不僅僅是一個常規數組。

我不確定你在線上做什麼

*catalog[n]->short_name=*args[1]; 

表達式catalog[n]->short_name的類型是char[50]。在這種情況下,數組類型被隱式轉換(「decays」)爲指針類型,char *。因此,整個表達*catalog[n]->short_name的類型是* (char *),或者僅僅是普通的char,這是一個整體類型。您實質上是試圖將args[1]的第一個字符的值指定爲catalog[n]->short_name的第一個字符。

無論如何都不重要,因爲catalog[n]尚未初始化以指向任何有意義的地方;段錯誤來自嘗試訪問short_name成員,該成員暗指取消引用catalog[n],該指針隨機指向某處。

接下來,您不能使用賦值運算符=來分配字符串數據;您必須使用strcpy()strncpy()來做到這一點。

最後,從來沒有從來沒有永遠不會使用gets()。它在您的代碼中引入一個失敗點。它已在C99中正式棄用,不應再使用。使用fgets()代替:

if (fgets(command, sizeof command, stdin) != NULL) 
{ 
    char *newline = strchr(command, '\n'); 
    if (newline != NULL) 
    *newline = 0; 
} 

這裏有您需要解析出命令字符串並分配領域的結構成員的方式:

curToken = strtok(command, '\t'); 
if (curToken) 
    strncpy(catalog[n]->short_name, curToken, sizeof catalog[n]->short_name); 

curToken = strtok(NULL, '\t'); 
if (curToken) 
    strncpy(catalog[n]->surname, curToken, sizeof catalog[n]->surname); 

curToken = strtok(NULL, '\t'); 
if (curToken) 
{ 
    char *chk; 
    catalog[n]->amount = (int) strtol(curToken, &chk, 10); 
    if (!isspace(*chk) && *chk != 0) 
    fprintf(stderr, 
     "Warning: expected integer value for amount, received %s instead\n", 
     curToken); 
} 

curToken = strtok(NULL, '\t'); 
if (curToken) 
    strncpy(catalog[n]->description, curToken, sizeof catalog[n]->description); 

此代碼假定catalog仍然被聲明爲指針陣列每個元素已被初始化指向某處有意義。否則,將聲明從struct catalog {...} *catalog[MAX];更改爲struct catalog {...} catalog[MAX],並將->更改爲.

+0

使用此代碼...行: curToken = strtok(command,'\ t'); curToken = strtok(NULL,'\ t'); curToken = strtok(NULL,'\ t'); curToken = strtok(NULL,'\ t'); 有一個警告: 警告:使「的strtok」的參數2時將整數指針,未使用本鑄造 日Thnx的幫助反正 – FILIaS 2010-05-14 20:13:56

+0

:字符* curToken = strtok的(命令,」「); 劃分爲LINE: strncpy(catalog [n] - > short_name,curToken,sizeof(catalog [n] - > short_name)); – FILIaS 2010-05-15 14:06:35

+0

廢話;應該是「\ t」而不是'\ t';我有點睡眠不足。至於段錯誤,就像我上面所說的那樣,這假定'catalog [n]'已經被正確地分配並且指向某個有意義的地方。正如我所說的,目前還不清楚爲什麼你將'catalog'作爲* pointer *的數組分配給'struct catalog',但是我寫了我的示例,假設這就是你想要的。如果不是,則將聲明從'struct ... * catalog [MAX];'更改爲'struct ... catalog [MAX]',並使用'.'代替組件選擇'.'。 – 2010-05-15 14:25:57