数组和指针的分段错误

发布于 2024-12-06 12:29:42 字数 749 浏览 0 评论 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;
    }
}

I have a segmentation fault...i'm not sure what's causing it. Also, when passing the member pname into the function get_names, am I doing this correctly, or is there a better way of doing this?

#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;
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

佞臣 2024-12-13 12:29:42

在您的代码不变的情况下,如果文件无法正确打开(即由于权限而无法读取,或者根本不存在),我会收到分段错误。

这是函数 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 文件,而是一个每行都有一个名称的简单文本文件。

With your code unchanged, I get a segmentation fault if the file can't be opened properly (i.e. it's unreadable due to permissions, or it simply does not exist).

Here's a modified version of you function 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);
}

This would still read the first name 16 times, but it would tell you why it didn't manage to open the file. To read the next name from the file (rather than repeatedly the first name), open (and close) the file in the main() function instead.

Also, you might as well call get_names() like so:

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

No need to do that &(*...) thing you're doing.

And, finally, I hope that the teamnames.rtf file is not actually an RTF file, but a simple text file with a name on each line.

山川志 2024-12-13 12:29:42

问题来自于这一行:

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

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

The problem comes from this line:

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

Understanding pointers and dereferencing is one of the biggest adjustments to learning C if you are switching from another language. You're doing it wrong, and I think you should seek out a tutorial on the subject. Try http://www.cplusplus.com/doc/tutorial/pointers/ as a starting point.

枯叶蝶 2024-12-13 12:29:42

让调试器告诉您出了什么问题。在启用调试的情况下编译代码(请参阅编译器的手册页)并运行如下所示的内容:

gdb a.out core

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

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

Get a debugger to tell you what is wrong. Compile the code with debugging enabled (see you man page for your compiler) and run something like this:

gdb a.out core

Then you should be able to see which line made the code core dump. You could use idb as well, if you have the intle compiler installed. This is, of course, on *nix. If you are talking windows, use the VS debugger.

In addition do NOT use fscanf as it is unsafe. Use fgets instead.

晨光如昨 2024-12-13 12:29:42

有很多奇怪的事情。首先,名称似乎在文件中,但您所做的是在 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、检查数组边界等的问题是不是这个解决方案关心的问题,但这让您知道该做什么,而不是复制粘贴代码。

There are many strange things. First thing is, it seems like the names are in a file, but what you are doing is in every iteration of your for loop, you call get_names which opens the file again, that is goes to the beginning of the file and you read the same name over and over again.

That is if you closed the file. Since you haven't closed the file, the file is already open and you keep reopening it (which could be the cause of your problem)

Another thing is, how can

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

Give you the current count? Regardless of the count of the players in the file, you are just setting it to MAX_PLAYERS.

Another thing is that count is an input to the function that is not a pointer, so setting it does not change the value outside the function (which is what I assumed you wanted).

Here is how I would do it with minimum change to your code:

#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;
    }
}

Here is how I would do it more concisely:

#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);
    }
}

Note that the problems with fscanf, checking array boundaries etc are not the concern of this solution, but this rather gives you the idea of what to do not a code for you to copy-paste.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文