динамически распределяемый массив структур - PullRequest
0 голосов
/ 08 марта 2012

Я часами пытался заставить эту функцию работать правильно.Вот назначение:

Добавить: Запрос имени детали, цены и количества.Сохраните информацию в динамически размещенный массив структур.Вы можете выделить место для до 3 структур одновременно.Вам нужно будет динамически создавать больше памяти по мере необходимости.Используйте эту структуру (вы можете использовать typedef, если хотите):

Пока что у меня есть код

typedef struct  {
    char* name;
    float price;
    int quantity;
}part;


void add(part *item, int *part_count)
{
     //char temp[100];

     if (!item){
       item = malloc(sizeof(part)*3);
     }
     else{
      item = realloc(item, sizeof(part) * ((*part_count*3) + 1));
     }

     item[*part_count].name = malloc(sizeof(char)*64); // max of 64 characters

     printf("Please enter item name: \n");
     //fgets(temp, strlen(temp), stdin);
     //sscanf(temp, "%s", item[*part_count].name);
     scanf("%64s", item[*part_count].name);

     printf("Please enter item price: \n");
     //fgets(temp, strlen(temp), stdin);
     //sscanf(temp, "%f", &item[*part_count].price);
     scanf("%f", &item[*part_count].price);

     printf("Please enter item quantity: \n");
     //fgets(temp, strlen(temp), stdin);
     //sscanf(temp, "%d", &item[*part_count].quantity);
     scanf("%d", &item[*part_count].quantity);

     *part_count = *part_count+ 1;
  }

Я пытался получить ввод с помощью fgets()и sscanf(), но с использованием этого кода он никогда не позволяет пользователю вводить данные, а затем завершает функцию.

Я считаю, что проблема заключается в моем распределении памяти, поскольку я получаю ошибки сегментации, когда пытаюсь что-либо сделатьс массивом, например, распечатать содержимое.

Ответы [ 2 ]

1 голос
/ 08 марта 2012

Ваша функция имеет невозможный интерфейс.Он принимает указатель part *.Этот указатель входит в функцию по значению.Внутри функции, которую вы ей назначаете, из вызова malloc или realloc.Но вызывающая сторона не увидит это обновленное значение.Когда функция возвращается, выделенная вами память просочилась, и вызывающая сторона имеет исходное значение указателя (возможно, нулевое).

Кроме того, лучше инкапсулировать динамические массивы в структуру.У вас есть переменная "count count", которая сама по себе свободна и должна передаваться везде вместе с массивом, чтобы отслеживать ее размер.Как насчет упаковки их вместе:

typedef struct part_list {
  struct part *part;
  int count;
} part_list;

Теперь есть функция для инициализации пустого списка деталей.Этот должен вызываться всеми, кто хочет использовать другие функции part_list.

void part_list_init(part_list *pl)
{
  pl->part = 0;
  pl->count = 0;
}

Затем напишите свою функцию для добавления деталей.

int part_list_add(part_list *pl)
{
  part_list *p;
  int index = pl->count++; /*  increment count, keep old value */

  /* realloc accepts a null pointer and then behaves like malloc */
  p = realloc(pl->part, sizeof *pl->part * pl->count);
  if (p == 0)
    return 0; /* failed to allocate/extend array */
  p1->part = p;

  if ((pl->part[index].name = malloc(64)) == 0) {
    pl->count = index; /* roll back the count: we didn't really allocate this part */
    return 0;
  }

  /* your code, updated with pl-> access */
  printf("Please enter item name: \n");
  scanf("%63s", pl->part[index].name); /* 63s not 64s!!! One byte for NUL char! */

  printf("Please enter item price: \n");
  scanf("%f", &pl->part[index].price); /* check the return value of scanf!!! */

  printf("Please enter item quantity: \n");
  scanf("%d", &pl->part[index].quantity);

  return 1; /* 1 means success */
}
1 голос
/ 08 марта 2012

Предположительно, при первом вызове add () item будет иметь значение NULL, и вы выполните его первоначальное распределение; последующие вызовы realloc, так что массив в 3 раза больше необходимого размера (что я не думаю, что вы действительно хотите).

Но аргумент, который соответствует элементу, не изменяется при вызове add (), поэтому он остается равным NULL, и каждый вызов add () действует так, как если бы это был первоначальный вызов, выделяя пространство для 3 структур (что будет проблемой при добавлении 4-й структуры).

Вы можете сделать элемент ** частью и использовать * часть везде, где вы в данный момент используете деталь, так что новое значение указателя будет сохранено (вы передадите адрес части * в качестве аргумента). Или используйте новое значение элемента в качестве возвращаемого значения функции, которая немного чище ИМХО. (Вот где справочные параметры пригодятся, но у C таких вещей нет.)

...