2011-09-27 134 views
0

我有一個分段錯誤...我不知道是什麼導致它。另外,當將成員pname傳遞給函數get_names時,我是否正確地做了這件事,還是有更好的方法來做到這一點?數組和指針的分段錯誤

#include <stdio.h> 

#define MAX_NAME 20 
#define MAX_PLAYRS 16 

typedef struct { 
    char pname[MAX_NAME]; 
    int runs; 
    char how_out; 
} Team_t; 

Team_t player[MAX_PLAYRS]; 
Team_t *player_ptr[MAX_PLAYRS]; 
void get_names (int count, char *str); 

int main (void) { 
    int i; 
    for (i = 0; i < MAX_PLAYRS; i++) { 
     get_names(i, &(*player[i].pname)); 
     printf("Player: %s\n", player[i].pname); 
    } 
} 

void get_names (int count, char *str) { 
    FILE *inp; 
    char status; 

    inp = fopen("teamnames.rtf", "r"); 
    status = fscanf(inp, "%s", str); 
    if (status == EOF) { 
     count = MAX_PLAYRS; 
    } 
} 
+0

道歉的佈局,新的堆棧溢出以及 –

+2

這是一些反向縮進佈局?縮進塊比左側更靠近o.0 – orlp

+0

段錯誤在哪裏? – Chowlett

回答

0

問題來源於此行:

get_names(i, &(*player[i].pname)); 

瞭解指針和非關聯化是最大的調整,以學習C,如果你是從其他語言轉換的一個。你做錯了,我認爲你應該尋找關於這個主題的教程。以http://www.cplusplus.com/doc/tutorial/pointers/作爲起點。

0

得到一個調試器,告訴你什麼是錯的。編譯啓用調試代碼(請參閱您的編譯器,你的男人頁),然後運行是這樣的:

gdb a.out core 

那麼你應該能夠看到這行做的代碼核心轉儲。如果你安裝了編譯器,你也可以使用idb。這當然是在* nix上。如果你在說窗口,使用VS調試器。

另外做不是使用fscanf因爲它是不安全的。改爲使用fgets

1

如果代碼不變,如果文件無法正常打開(即由於權限而無法讀取,或者根本不存在),則會出現分段錯誤。

下面是修改後的版本,你的功能get_names()

void get_names(int count, char *str) 
{ 
    FILE *inp; 

    inp = fopen("teamnames.rtf", "r"); 

    if (inp == NULL) { 
    perror("Failed"); 
    return; 
    } 

    fgets(str, MAX_NAME, inp); 

    fclose(inp); 
} 

這仍然會讀取頭名的16倍,但它會告訴你爲什麼它沒能打開該文件。要從文件中讀取下一個名稱(而不是重複輸入名字),請改爲打開(並關閉)main()函數中的文件。

而且,你還不如叫get_names()像這樣:

get_names(i, player[i].pname); 

不需要做你正在做的事情&(*...)

最後,我希望teamnames.rtf文件實際上不是一個RTF文件,而是一個簡單的文本文件,每行都有一個名稱。

0

有很多奇怪的事情。首先,它看起來像名稱在一個文件中,但是你正在做的是在你的for循環的每一次迭代中,你調用get_names,它再次打開文件,這是文件的開始,你讀了一遍又一遍的同名。

這就是如果你關閉了文件。既然你沒有關閉該文件,該文件已經被打開而且你把它重新打開(這可能是你的問題的原因)

另一件事是,

if (status == EOF) { 
    count = MAX_PLAYRS; 
} 

怎麼可以給你目前的計數?無論文件中玩家的數量如何,您只需將其設置爲MAX_PLAYERS即可。

另一件事是,count是不是一個指針的函數的輸入,所以設置它不會改變函數外的值(這正是我認爲你想要的)。

這裏是我將如何以最小的變化對你的代碼做到這一點:

#include <stdio.h> 

#define MAX_NAME 20 
#define MAX_PLAYRS 16 

typedef struct { 
    char pname[MAX_NAME]; 
    int runs; 
    char how_out; 
} Team_t; 

Team_t player[MAX_PLAYRS]; 
Team_t *player_ptr[MAX_PLAYRS]; 
void get_names (int count, char *str, FILE *inp); 

int main (void) { 
    FILE *inp; 
    int i; 
    int count; 
    inp = fopen("teamnames.rtf", "r"); 
    for (i = 0; i < MAX_PLAYRS; i++) { 
     get_names(&count, player[i].pname, inp); 
     printf("Player: %s\n", player[i].pname); 
    } 
} 

void get_names (int *count, char *str) { 
    char status; 

    status = fscanf(inp, "%s", str); 
    if (status == EOF) { 
     *count = MAX_PLAYRS; 
    } 
} 

這裏是我會怎麼做更簡潔:

#include <stdio.h> 

#define MAX_NAME 20 
#define MAX_PLAYRS 16 

typedef struct { 
    char pname[MAX_NAME]; 
    int runs; 
    char how_out; 
} Team_t; 

Team_t player[MAX_PLAYRS]; 
Team_t *player_ptr[MAX_PLAYRS]; 
int get_names (Team_t *team); 

int main (void) { 
    get_names(player); 
} 

int get_names (Team_t *team) { 
    int i = 0; 
    FILE *inp; 
    inp = fopen("teamnames.rtf", "r"); 
    while (i < MAX_PLAYRS && !feof(inp) { 
     fscanf(inp, "%s", team[i].pname); 
     printf("Player: %s\n", player[i].pname); 
    } 
} 

注意fscanf問題,檢查數組邊界等並不是這個解決方案的關注點,但是這樣可以讓你知道不需要代碼來複制粘貼的想法。