[英]Segmentation fault with arrays and pointers
我有細分錯誤...我不確定是什么原因造成的。 另外,將成員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;
}
}
在您的代碼不變的情況下,如果無法正確打開文件(例如,由於權限而無法讀取,或者根本不存在),則會出現分段錯誤。
這是您的函數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()
:
get_names(i, player[i].pname);
不需要做您正在做的&(*...)
。
最后,我希望teamnames.rtf
文件實際上不是RTF文件,而是每行都有名稱的簡單文本文件。
讓調試器告訴您出了什么問題。 在啟用調試的情況下編譯代碼(請參見您的編譯器手冊頁),然后運行以下命令:
gdb a.out core
然后,您應該能夠看到哪一行進行了代碼核心轉儲。 如果已安裝intle編譯器,則也可以使用idb。 當然,這是在* nix上。 如果您正在使用Windows,請使用VS調試器。
此外, 請勿使用fscanf
因為它不安全。 請改用fgets
。
問題來自此行:
get_names(i, &(*player[i].pname));
如果要從另一種語言切換,那么了解指針和取消引用是對學習C的最大調整之一。 您做錯了,我認為您應該尋找關於該主題的教程。 嘗試以http://www.cplusplus.com/doc/tutorial/pointers/作為起點。
有很多奇怪的事情。 第一件事是,名稱似乎在文件中,但是您正在做的是在for循環的每次迭代中,您調用get_names
再次打開文件,即轉到文件的開頭,然后閱讀一遍又一遍的同名。
那就是如果您關閉文件。 由於您尚未關閉文件,因此該文件已經打開並且您一直在重新打開它(這可能是導致問題的原因)
另一件事是,如何
if (status == EOF) {
count = MAX_PLAYRS;
}
給你當前的數目? 無論文件中有MAX_PLAYERS
播放器,您都將其設置為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
,檢查數組邊界等不是此解決方案的問題,而是使您了解了什么不需要復制粘貼代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.