Ошибка сегментации с массивами и указателями - PullRequest
0 голосов
/ 27 сентября 2011

У меня ошибка сегментации ... Я не уверен, что это вызвало.Кроме того, при передаче члена 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 ]

1 голос
/ 27 сентября 2011

Если ваш код не изменился, я получаю ошибку сегментации, если файл не открывается должным образом (т. Е. Он не читается из-за разрешений или просто не существует).

Вот модифицированная версия вашей функции 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-файл, а простой текстовый файл с именем в каждой строке.

0 голосов
/ 27 сентября 2011

Есть много странных вещей. Во-первых, кажется, что имена находятся в файле, но вы делаете на каждой итерации цикла 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, проверкой границ массива и т. Д. Не являются проблемой этого решения, но это скорее дает вам представление о том, что делать, а не код для копирования-вставки .

0 голосов
/ 27 сентября 2011

Проблема возникает из этой строки:

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

Понимание указателей и разыменование является одной из самых больших корректировок в изучении C, если вы переходите с другого языка.Вы делаете это неправильно, и я думаю, что вы должны искать учебник по этому вопросу.Попробуйте http://www.cplusplus.com/doc/tutorial/pointers/ в качестве отправной точки.

0 голосов
/ 27 сентября 2011

Получить отладчик, чтобы сказать вам, что не так.Скомпилируйте код с включенной отладкой (см. Справочную страницу вашего компилятора) и запустите что-то вроде этого:

gdb a.out core

Тогда вы сможете увидеть, какая строка создала дамп ядра кода.Вы также можете использовать idb, если у вас установлен встроенный компилятор.Это, конечно, на * nix.Если вы говорите Windows, используйте отладчик VS.

Кроме того, НЕ используйте fscanf, поскольку это небезопасно.Вместо этого используйте fgets.

...