簡體   English   中英

數組和指針的分段錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM