数组和指针的分段错误

时间:2011-09-27 15:53:31

标签: c segmentation-fault

我有分段错误...我不确定是什么导致它。另外,当将成员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;
    }
}

4 个答案:

答案 0 :(得分: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文件,而是一个简单的文本文件,每行都有一个名称。

答案 1 :(得分:0)

获取调试器以告诉您出了什么问题。在启用调试的情况下编译代码(参见编译器的手册页)并运行如下代码:

gdb a.out core

然后你应该能够看到代码核心转储的哪一行。如果安装了intle编译器,也可以使用idb。当然,这是在* nix上。如果您正在谈论Windows,请使用VS调试器。

此外, NOT 使用fscanf,因为它不安全。请改用fgets

答案 2 :(得分:0)

问题来自这一行:

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

如果您从另一种语言切换,了解指针和解除引用是学习C的最大调整之一。你做错了,我认为你应该找一个关于这个主题的教程。尝试http://www.cplusplus.com/doc/tutorial/pointers/作为起点。

答案 3 :(得分: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的问题,检查数组边界等不是这个解决方案的关注点,但这相当于让你知道什么不是你的代码复制 - 粘贴。