开发者

Why does my list only ever return the element most recently added?

Greetings again,

I have this problem again on C but now using struct. Having this structure of student

struct student {
   char *name;
   int age;
}

I wanted to a list where I could add a number of Student and can also view all of its elements. Here's the code I have done so far.

#include<stdio.h>
#include<stdlib.h>
// struct student ...
void ad开发者_运维知识库d(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);
}

I only get the newest student upon the view method.


It makes sense, since you are allocation space for 1 single student structure:

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

You should do something like:

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

The name variable suffers from the same problem.

A dynamic linked list should have a reference to the next and previous elements. You'll have to change your program to work with:

struct student {
   char *name;
   int age;
   struct student* next;
   struct student* previous;
}


Also you are doing *(data++) which isn't necessary. data++ is just fine. You really shouldn't be needing the double pointers everywhere, it only complicates things. For allocation, fine (if you think that's the best way), but for passing to other functions that only READ the pointer, there's no need.


view expects list to be an array (null-terminated) of pointers to student. However, you allocate it in main as a pointer to a single student. Then, you just reassign that student pointer every time you call add. As Chris said, it would probably be fine (and simpler) just to have a list of students.


If you want to implement the list as an array, you need a strategy to re-allocate the list when it gets larger than the initial array size. A typical strategy is to choose an arbitrary size that will handle most cases without wasting tons of memory, and then double that amount when the bound is reached. So, say you start with an 8-element list. When you add the 9th element, it would reallocate the array to a 16-element list.

The other strategy is to use a linked list, where you add a struct pointer (typically named "next") to your structure and use that to iterate through your list. This makes allocation and traversal a lot simpler, although list retrieval becomes an O(n) operation instead of an O(1) operation, which means it takes longer to get a particular element from the list as the list gets larger.


You have two options.

  1. Create linked list and you will be able to insert as many students you want. (each student has also pointer on next student if any else it is NULL)

  2. Create array of pointers on students as suggested by karlphillip, but method to add new student will need to implement position searching or storing this postion. (you have to figure out where should you store pointer that points on student)


I only get the newest student upon the view method.

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

Notice that you are making list point to the newly allocated memory location. The previous value it was pointing to is lost and also causes memory leak. And so only you are getting the last entry. You need to implement a linked list like structure.


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

}
0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜