繁体   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