Pang Yi Yang
Pang Yi Yang

Reputation: 31

Linked list's data being overwritten

I have a problem in adding data into the linked list. This codes basically is trying to insert new course name into the struct first, then insert the struct into the linked list, and the cycle repeats. The user are responsible to insert the new course name.

The problem now is when user go to the add course operation using scanf, it always overwritten the existing course name in the linked list and add into it.

This is the input and output from the console application:

Enter operation: 1
Add Course: asdgvsdrgf
Enter operation: 1
Add Course: ehtyerdc
Enter operation: 1
Add Course: nbcnvbergt
Enter operation: 5    (// Just Print course name in the linked list)
Current enrolments:
nbcnvbergt
nbcnvbergt
nbcnvbergt

Current enrolments:

(Changing h files is impossible as it is the requirement of the assignment from university)

Here are the c and h file attached below:

bst.h

#pragma once

#include <stdio.h>
#include <stdlib.h>

typedef struct bstNode {
long student_id;
struct bstNode *left;
struct bstNode *right;
} *BST;

courselist.h

#include <stdio.h>
#include <stdlib.h>
#include "bst.h"

typedef struct course {
char *name;
BST students;
} Course;

typedef struct courseNode {
Course data;
struct courseNode *next;
} *CourseList;

bst.c

(not yet written)

courselist.c

#include <stdio.h>
#include "courselist.h"
#include <stdlib.h>

void print_course_and_num_students(CourseList *self) {
CourseList current = *self;
while (current != NULL) 
{
    printf("%s\n", (current->data).name);
    current = current->next;
}
printf("\n");
}

void insert_course_at_front(CourseList *self, Course data) {
CourseList newNode = (CourseList)malloc(sizeof(struct courseNode));

if (*self == NULL)
{
    *self = newNode;
    (*self)->data = data;
    (*self)->next = NULL;
    return;
}

   newNode->data = data;
   newNode->next = *self;
   *self = newNode;
}

main.c

#include <stdio.h>
#include "courselist.h"
#include "bst.h"
#include <stdlib.h>
#include <cstdbool>

#define MAX_LEN 100

void main()
{   
CourseList my_course = (CourseList)malloc(sizeof(struct courseNode));
my_course = NULL;
Course my_list;
(&my_list)->name = (char *)malloc(100 * sizeof(char));

bool program_quit = false;
int input_op;

char *insert_course_word;
insert_course_word = (char *)malloc(100 * sizeof(char));

char *delete_course_word;
delete_course_word = (char *)malloc(100 * sizeof(char));

do
{
    printf("Enter operation: ");
    scanf("%d", &input_op);

    switch (input_op)
    {
    case 0:            // Quit
        program_quit = true;
        break;

    case 1:            // Add Course
        program_quit = false;
        printf("Add Course: ");
        scanf("%s", (&my_list)->name);

        //(&my_list)->name = (insert_course_word);

        insert_course_at_front(&my_course, my_list);
        break;

    case 2:            // Remove Course
        program_quit = false;
        printf("Remove Course: ");
        scanf("%s", delete_course_word);
        (&my_list)->name = (delete_course_word);
        delete_course(&my_course, my_list);
        break;

    case 3:            // Enrol Student
        program_quit = false;
        break;

    case 4:            // Un-enrol student
        program_quit = false;
        break;

    case 5:            // Print a summary of courses and the number of students enrolled in each course
        program_quit = false;
        printf("Current enrolments:\n");
        print_course_and_num_students(&my_course);
        break;

    case 6:            // Print an ordered list of students enrolled in a course
        program_quit = false;
        break;

    case 7:            // Print a list of courses that a given student is enrolled in
        program_quit = false;
        break;

    default:
        printf("Invalid operation\n");
    }
} while (program_quit == false);

if (my_course != NULL)
{
    destroy(&my_course);
}

//destroy(&my_list);
return;
}

Upvotes: 2

Views: 170

Answers (2)

MikeMB
MikeMB

Reputation: 21166

The problem is that you never create a new name, but all course structures' name pointers point to the same memory region, which is the one you are allocating at the start of main.

This should do it (waring untested):

program_quit = false;
printf("Add Course: ");
char* name = malloc(100 * sizeof(char));   
scanf("%s", name);    
my_list.name=name;
insert_course_at_front(&my_course, my_list);

However, I would warn against writing such code in anything related to production code. If the user enters more than 100 characters, you get corrupted memory and if he enters less, you are wasting memory. I think in C (i haven#t written production quality c-code in a long long time) you would usually read the input character by character into a local buffer (stopping when either the buffer si full, or you get e.g. a newline) and then allocate a chunk of memory of the appropriate size and finally copy the string to that allocated chunk of memory.

Upvotes: 1

Ed Heal
Ed Heal

Reputation: 60037

Change

typedef struct course {
char *name;
BST students;
} Course;

to

typedef struct course {
char name[MAX_LEN];
BST students;
} Course;

to have some space to place the name

EDIT - On new info

    Course new_course;
    new_course-> name = malloc(MAX_LEN);

    scanf("%s", new_course->name); // This could be better to prevent buffer overwrite
    insert_course_at_front(&my_course, new_course);

Upvotes: 0

Related Questions