Исключение, выдаваемое при доступе к массиву структур - PullRequest
0 голосов
/ 15 мая 2018

Когда я вызываю функцию test (), мне предлагается ввести ставку для первого игрока в моем массиве struct. Он принимает мою запись. Во втором раунде цикла for for при запросе ставки для второго человека в моем массиве struct после ввода значения выдается исключение:

  Exception thrown at 0x00577F81 (ucrtbased.dll) in lottery.exe: 
  0xC0000005: Access violation writing location 0x7B7CC9FC.

  If there is a handler for this exception, the program may be safely continued. 

Вот мой код:

void initNames(struct player *p, int size) {
  int i;
  for (i = 0; i < size; i++) {
      printf("Enter player %d's name...\n", (i + 1));
      scanf("%s", p[i].name);
  }
  return;
}

void initScore(struct player *p, int size) {
   int i;
   for (i = 0; i < size; i++) {
      p[i].wins = 0;
      p[i].losses = 0;
      p[i].funds = 100.00;
   }
   return;
}

void test(struct player *p, int size) {
  int i;
  for (i = 0; i < size; i++) {
    printf("%s, you have $%.2lf. Place your bet!\n", p[i].name, p[i].funds);
    scanf("%lf", p[i].bet);
  }
}

void main() {

  int size;
  struct player *playerPtr;

  printf("How many players?");
  scanf("%d", &size);
  playerPtr = malloc(sizeof(struct player)*size);

  initScore(&playerPtr, size);

  initNames(&playerPtr, size);

  test(&playerPtr, size);

  free(playerPtr);
}

Спасибо за любую помощь или объяснения!

1 Ответ

0 голосов
/ 15 мая 2018

Существует несоответствие между тем, как вы объявили функцию initNames и тем, как вы вызываете ее в main.

Она объявлена ​​как -

void initNames(struct player *p, int size);

Что означаетон ожидает указатель на struct player в качестве первого аргумента и int в качестве второго.

В основном вы называете это как -

struct player *playerPtr;
initNames(&playerPtr, size);

Теперь тип playerPtr равен struct player* и, следовательно, тип &playerPtr будет struct player**.Таким образом, существует несоответствие типов для аргументов.Ваш компилятор должен был предупредить вас об этом.Всегда компилируйте с -Wall, чтобы увидеть все предупреждения, и -Werror, чтобы рассматривать предупреждения как ошибки.

Исправление -

Вы не собираетесь изменять playerPtr внутри любого изфункции.Так что вам не нужно пропускать struct player**.Поэтому измените вызов функции на -

initNames(playerPtr, size);

Ничего не нужно менять внутри функции, поскольку прототип функции не был изменен.

Точно такие же проблемы возникают сфункции initScore и test тоже.Вы можете исправить их аналогичным образом, изменив первый аргумент на их вызов.

Теперь и после исправления программа не будет корректной.Посмотрите на строку -

scanf("%lf", p[i].bet);

Я предполагаю, что bet объявлено с типом double.Теперь вы передаете double на scanf, где ожидается double*.Вам необходимо передать адрес ставки.Поэтому измените строку на -

scanf("%lf", &p[i].bet);

Я исправил все ошибки и рабочая версия на Ideone .

Я принял определение для struct player.

Чтобы быть более уверенным в читаемых значениях, всегда проверяйте возвращаемое значение scanf как -

int ret = scanf("%lf", p[i].bet);

if(ret == 0) {
    // Print appropriate error message that the value entered in not a double and ask the user to retry
} else if (ret == EOF) {
    // The input stream has been closed by the user without providing appropriate input, print appropriate error message and abort. 
}
// If execution reaches this point, p[i].bet is safe to use.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...