COMP2011 PA3: Course Management System
Announcements
This section will be updated after the release. Important announcements will also be sent to students via Canvas.
Introduction
Your goal is to implement a course management system using linked lists.
The system maintains 2-dimensional sorted linked lists:
- The main course list is a sorted Course linked list, sorted by code
- For each course, there are 2 sorted CourseItem linked lists, sorted by course->code
Here is an example to illustrate the system. In this example,
- 3 courses (COMP1021, COMP1022P, and COMP2011) are added
- Several pre-requisites and exclusions are added
You can see a sample list display on the left.
The equivalent linked list illustration is shown on the right, surrounded by a dashed box.
To simplify the display, attributes such as title and credit are not shown on the linked list illustration.
Design
The high-level design is shown on the left.
The C++ struct definitions are shown on the right.
The course code is the unique key (i.e., there won't be duplicated course codes in the system).
In this figure, only the main list and one exclusions sub-list are shown.
Tasks
The system supports the following 11 tasks:
Assumptions
- The course code is at least 2 characters (including NULL) and at most 10 characters (including NULL). You don't need to check if the input is invalid.
- The course title is at least 2 characters (including NULL) and at most 100 characters (including NULL). You don't need to check if the input is invalid.
- The course credit is a non-negative integer. The checking is already done in the skeleton code.
Think carefully before writing code
In this project assignment, you are free to define new constants, variables (excluding global variables), functions, etc.
The suggested order of implementation is: Insertions > Modifications > Deletions
For each task on this web page, we illustrate the general cases using some sample data
For each task, think carefully about the special cases. For example:
- What should you do if a linked list is empty?
- What should you do if there is an existing course code/pre-requisite/exclusion when you are doing insertions?
- What should you do if one/both of the course codes does not exist when you are doing insertions of pre-requisite and exclusion?
- What should you do if the course code/pre-requisite/exclusion does not exist when you are doing modifications/deletions?
- What situations you need to consider when you need to change the head pointer (e.g., deleting the first item, inserting as the new first item, etc.)?
- ... and so on
Think carefully about the code design. For example:
- Pre-requisites and exclusions are similar.
Can you write some helper functions to handle the common parts, and reuse them in the handling of pre-requisites and exclusions?
Although the code design is not one of the grading criteria, a good design will make your code more readable and easier to debug and maintain.
For deletions, you should avoid problems such as dangling pointer and memory leak
Task 1: Display the current list
Given Do not modify
voidll_print_all(const
Course
*head
);// given, you cannot make any changes
The display of the current list is given. Do not modify any lines of the given code of the display list function. The display consists of 4 sections:
- Display the main course list
- Display the course titles
- Display the pre-requisites
- Display the exclusions
Here is a sample list when the system is empty:
Here is a sample list when there are some courses, pre-requisites, and exclusions:
Task 2: Insert a new course
To simplify the display, attributes such as title and credit are not shown
boolll_insert_course(
Course
*&
head
,const
char
c
[MAX_CODE
],const
char
t
[MAX_TITLE
],int
cred
);
The main course list is sorted by code. For each insertion, you need to find the correct position to insert.
Here is an example, starting from an empty linked list:
Step 1: Start from an empty linked list
Step 2: Insert COMP1021
Task 3: Insert a Prerequisite
To simplify the display, attributes such as title and credit are not shown
boolll_insert_prerequisite(
Course
*head
,const
char
targetCode
[MAX_CODE
],const
char
preCode
[MAX_CODE
]);
For each insertion, you need to find the correct position to insert.
The self-prerequisite (i.e., pointing to itself) is already handled in the skeleton code. You don't need to handle this special case.
You don't need to handle logical errors, such as circular pre-requisites (e.g., A requires B, B requires C, C requires A)
Here is an example, starting from the main course list without any prerequisites.
Step 1: A starting point
Step 2: Insert a Prerequisite (COMP2011 requires COMP1021)
Step 3: Insert a Prerequisite (COMP2011 requires COMP1022P)
Task 4: Insert an Exclusion
To simplify the display, attributes such as title and credit are not shown
boolll_insert_exclusion(
Course
*head
,const
char
targetCode
[MAX_CODE
],const
char
excludeCode
[MAX_CODE
]);
The task is very similar to inserting pre-requisites.
The self-exclusion (i.e., pointing to itself) is already handled in the skeleton code. You don't need to handle this special case.
You don't need to handle logical errors, such as circular exclusions (e.g., A excludes B, B excludes C, C excludes A)
Here is an example, starting from a main course list without any exclusions.
Step 1: A starting point (from the previous task)
Step 2: Insert an Exclusion (COMP1021 excludes COMP1022P)
Step 3: Insert an Exclusion (COMP1022P excludes COMP1021)
Task 5-6: Delete an existing prerequisite/exclusion
To simplify the display, unrelated attributes and links are hidden
boolll_delete_prerequisite(
Course
*head
,const
char
targetCode
[MAX_CODE
],const
char
preCode
[MAX_CODE
]);
boolll_delete_exclusion(
Course
*head
,const
char
targetCode
[MAX_CODE
],const
char
excludeCode
[MAX_CODE
]);
Deleting an existing pre-requisite and deleting an existing exclusion are very similar.
In this example, only the deletion of an existing pre-requisite is shown:
Step 1: Before deleting a prerequisite COMP1021 from COMP2011
Step 2: After deleting a prerequisite COMP1021 from COMP2011
Task 7: Delete an existing course
To simplify the display, unrelated attributes and links are hidden
boolll_delete_course(
Course
*&
head
,const
char
c
[MAX_CODE
]);
Deleting an existing course is not trivial. You need to handle problems such as dangling pointer and memory leak
Here is an example to delete a course (COMP1022P) from the system:
Step 1: Explanation about the dangling pointer problem
Step 2: A starting point before deletion of COMP1022P
Step 3: Deleting all links that are pointed to COMP1022P
Step 4: Deleting all prerequisites and exclusions to avoid memory leak
Step 5: Deleting the COMP1022P node from the main list
ask 8-9: Modify a course title/credit
To simplify the display, unrelated attributes and links are hidden
boolll_modify_course_title(
Course
*head
,const
char
c
[MAX_CODE
],const
char
t
[MAX_TITLE
]);
boolll_modify_course_credit(
Course
*head
,const
char
c
[MAX_CODE
],int
cred
);
Modifying the course title/credit if the target node is found.
Suppose COMP2011 is the target, here is an example to modify its course title and credit:
If the new course title/credit is the same as the old course title/credit, it is still regarded as a successful modification.
In this assignment, you do not need to modify the course code. It is because all the linked lists in the system are sorted by course code, it is very tricky to modify a course code. We cannot simply delete a course and then add the course back because all the course links of pre-requisites and exclusions will be lost.
Task 10-11: Exit with/without clean-up
voidll_cleanup_all(
Course
*&
head
);