开发者

Segmentation fault with arrays and pointers

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


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.


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜