Почему мой список возвращает только самый последний добавленный элемент? - PullRequest
0 голосов
/ 06 апреля 2011

Снова привет,

У меня снова есть эта проблема на C, но теперь я использую struct. Имея такую ​​структуру студента

struct student {
   char *name;
   int age;
}

Я хотел получить список, в который я мог бы добавить количество учеников, а также просмотреть все его элементы. Вот код, который я сделал до сих пор.

#include<stdio.h>
#include<stdlib.h>
// struct student ...
void add(student **list, char* name, int age) {
   student* temp = (student *)malloc(sizeof(student));
   temp->name = name
   temp->age = age;
   *list = temp;
   *(list++) = (student *)malloc(sizeof(student));
}
void view(student **list) {
   student* data = *list;
   while(data != '\0') { printf("%s%i", data->name, data->age); *(data++); }
}
main() {
   student* list = (student *)malloc(sizeof(student));
   char* name = (char *)malloc(sizeof(char));
   int age=0;
   // inputs for name and age
   // do-while(option != EXIT_VALUE);
   // inside do-while are the following below
   add(&list, name, age);
   view(&list);
}

Я получаю самого нового ученика только по методу просмотра.

Ответы [ 6 ]

3 голосов
/ 06 апреля 2011

Это имеет смысл, поскольку вы выделяете пространство для 1 одиночной студента структуры:

student* list = (student *)malloc(sizeof(student));

Вы должны сделать что-то вроде:

int list_size = 20;
student* list = (student *)malloc(sizeof(student) * list_size);

Переменная name страдает той же проблемой.

Динамический связанный список должен иметь ссылку на следующий и предыдущий элементы. Вам придется изменить свою программу для работы с:

struct student {
   char *name;
   int age;
   struct student* next;
   struct student* previous;
}
1 голос
/ 06 апреля 2011

Также вы делаете *(data++), что не обязательно.data++ просто отлично.Вы действительно не должны нуждаться в двойных указателях везде, это только усложняет ситуацию.Для распределения это хорошо (если вы считаете, что это лучший способ), но для передачи другим функциям, которые только читают указатель, в этом нет необходимости.

0 голосов
/ 06 апреля 2011

У вас есть два варианта.

  1. Создайте связанный список, и вы сможете добавить столько учеников, сколько захотите. (у каждого ученика есть указатель на следующего ученика, если он есть, он равен NULL)

  2. Создайте массив указателей на учеников в соответствии с предложением karlphillip, но метод добавления нового ученика должен будет осуществить поиск позиции или сохранение этой позиции. (Вы должны выяснить, где хранить указатель, указывающий на студента)

0 голосов
/ 06 апреля 2011

Если вы хотите реализовать список в виде массива, вам нужна стратегия перераспределения списка, когда он становится больше, чем начальный размер массива.Типичная стратегия состоит в том, чтобы выбрать произвольный размер, который будет обрабатывать большинство случаев, не тратя тонны памяти, а затем удваивать это количество при достижении границы.Итак, скажем, вы начинаете со списка из 8 элементов.Когда вы добавляете 9-й элемент, он перераспределяет массив в список из 16 элементов.

Другая стратегия заключается в использовании связанного списка, в который вы добавляете указатель структуры (обычно называемый «следующий») к вашему.структурировать и использовать это для перебора вашего списка.Это значительно упрощает распределение и обход, хотя извлечение списка становится операцией O (n) вместо операции O (1), что означает, что получение определенного элемента из списка занимает больше времени, поскольку список становится больше.

0 голосов
/ 06 апреля 2011

view ожидает, что list будет массивом (с нулевым символом в конце) указателей на студента.Тем не менее, вы выделяете его в основном как указатель на одного студента.Затем вы просто назначаете указатель учащегося каждый раз, когда звоните add.Как сказал Крис, было бы неплохо (и проще) просто иметь список студентов.

0 голосов
/ 06 апреля 2011

Я получаю самого нового ученика только по методу просмотра.

void add(student **list, char* name, int age) {
   student* temp = (student *)malloc(sizeof(student));
   temp->name = name
   temp->age = age;
   *list = temp;
   *(list++) = (student *)malloc(sizeof(student));
}

Обратите внимание, что вы list указываете на недавно выделенную область памяти.Предыдущее значение, на которое оно указывало, теряется и также вызывает утечку памяти.И так только вы получаете последнюю запись.Вам необходимо реализовать связанный список, например структуру.


struct student {
   char *name;
   int age;

   struct student *next ;
}

// ....

void add(student **list, char* name, int age) {
   // Make sure that every new location is saved in next
   // And also the next time when you call this method, it should be
   // location of "next" pointing to being passed as parameter.      
}

int main()
{
    student *list = malloc(sizeof(student));  // No need to type cast malloc

    student *preserveHeadNode = list ;

    add(&list, name, age);

    // .. While viewing pass the "preserveHeadNode" and run the loop until
    //    student::next == NULL

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...