Week 11 Laboratory Sample Solutions
Objectives
- using linked lists to store real-world data
- more advanced linked list operations
Activities To Be Completed
The following is a list of all the activities available to complete this week...
Worth 0.7 mark(s) in total:
- list_delete_first
- list_increasing
Worth 0.7 mark(s) in total:
- list_insert_nth
- list_get_nth_v2
Worth 0.4 mark(s) in total:
- lists_diagonal
Problem sets are capped at 15 marks (there are 4 possible bonus marks from the three-dot exercises that can bring you up to a total of 15 if you missed out on any other marks in the one- or two-dot exercises).
Completing just the one and two-dot exercises every week can give you the full 15 marks needed in this component.
For more details, see the course outline.
Exercise
(●◌◌)
:
Delete First Element from a Linked List
Download list_delete_first.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/list_delete_first/list_delete_first.c .
Your task is to add code to this function in list_delete_first.c:
//
// Delete the first node in list.
// The deleted node is freed.
// The head of the list is returned.
//
struct node *delete_first(struct node *head) {
// PUT YOUR CODE HERE (change the next line!)
return NULL;
}
Note list_delete_first.c
uses the following familiar data type:
struct node { struct node *next; int data; };
delete_first
is given one argument, head
which is the pointer to the first
node in the linked list
Add code to delete_first
so that it deletes the first node from list
delete_first
should return a pointer to the new first node in the list
If the list is now empty, delete_first
should return NULL
delete_first
should call free
to free the memory of the node it deletes
For example if the linked list contains these 8 elements:
16, 7, 8, 12, 13, 19, 21, 12
delete_first
should return a pointer to a list with these elements:
7, 8, 12, 13, 19, 21, 12
Hint: This task should only require a few lines of code
Testing
list_delete_first.c
also contains a main
function which allows you to test
your delete_first
function. It converts the inputs to a linked list,
calls delete_first
and then prints the result.
Do not change this main
function. If you want to change it, you have misread
the question.
Your delete_first
function will be called directly in marking. The main
function is only to let you test your delete_first
function
Examples
dcc list_delete_first.c -o list_delete_first ./list_delete_first Total numbers: 8 16 7 8 12 13 19 21 12 [7, 8, 12, 13, 19, 21, 12] ./list_delete_first Total numbers: 6 2 4 6 2 4 6 [4, 6, 2, 4, 6] ./list_delete_first Total numbers: 1 42 [] ./list_delete_first Total numbers: 0 []
Assumptions/Restrictions/Clarifications
delete_first
should callfree
to free the memory for the node it deletesdelete_first
should not change the data fields of list nodesdelete_first
should not use arraysdelete_first
should not callmalloc
delete_first
should not call scanf (orgetchar
orfgets
)delete_first
should not print anything. It should not callprintf
- Do not change the supplied
main
function. It will not be tested or marked
1091 style list_delete_first.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest list_delete_first
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab11_list_delete_first list_delete_first.c
You must run give
before Monday 11 November 09:00
to obtain the marks for this lab exercise.
Note that this is an individual exercise,
the work you submit with give
must be entirely your own.
list_delete_first.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define MAX_LIST_LEN 100
struct node {
struct node *next;
int data;
};
struct node *delete_first(struct node *head);
struct node *array_to_list(int len, int array[]);
void print_list(struct node *head);
int main(void) {
// get list size
int list_size;
printf("Total numbers: ");
scanf(" %d", &list_size);
// read in numbers
int list[MAX_LIST_LEN] = {0};
int index_count = 0;
while (index_count < list_size && scanf(" %d", &list[index_count])) {
index_count++;
}
// create linked list from input numbers
struct node *head = NULL;
if (index_count > 0) {
// list has elements
head = array_to_list(list_size, list);
}
struct node *new_head = delete_first(head);
print_list(new_head);
return 0;
}
// Delete the first node in list.
// The deleted node is freed.
// The head of the list is returned.
struct node *delete_first(struct node *head) {
if (head == NULL) {
// list is empty no node to delete
return NULL;
}
struct node *new_head = head->next;
free(head);
return new_head;
}
// create linked list from array of ints
struct node *array_to_list(int len, int array[]) {
struct node *head = NULL;
int i = len - 1;
while (i >= 0) {
struct node *n = malloc(sizeof (struct node));
assert(n != NULL);
n->next = head;
n->data = array[i];
head = n;
i--;
}
return head;
}
// print linked list
void print_list(struct node *head) {
printf("[");
for (struct node *n = head; n != NULL; n = n->next) {
// If you're getting an error here,
// you have returned an invalid list
printf("%d", n->data);
if (n->next != NULL) {
printf(", ");
}
}
printf("]\n");
}
// free linked list
static void free_list(struct node *head) {
if (head != NULL) {
free_list(head->next);
free(head);
}
}
Exercise
(●◌◌)
:
Check whether a Linked List is in Increasing Order
Download list_increasing.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/list_increasing/list_increasing.c .
Your task is to add code to this function in list_increasing.c:
int increasing(struct node *head) {
// PUT YOUR CODE HERE (change the next line!)
return 42;
}
increasing
is given one argument, head
which is the pointer to the first
node in a linked list.
Add code to increasing
so that its returns 1
if the list is in increasing
order - the value of each list element is larger than the element before.
For example if the linked list contains these 8 elements:
1, 7, 8, 9, 13, 19, 21, 42
increasing
should return 1
because it is increasing order
Testing
list_increasing.c
also contains a main
function which allows you to test
your increasing
function.
This main function:
- converts the first set of read integers to a linked list,
- assigns a pointer to the first node in the linked list to
head
, - calls
list_increasing(head)
and - prints the result.
Do not change this main
function. If you want to change it, you have misread
the question.
Your list_increasing
function will be called directly in marking. The main
function is only to let you test your list_increasing
function
Examples
dcc list_increasing.c -o list_increasing ./list_increasing How many numbers in initial list?: 9 1 2 4 8 16 32 64 128 256 1 ./list_increasing How many numbers in initial list?: 6 2 4 6 5 8 9 0 ./list_increasing How many numbers in initial list?: 6 13 15 17 17 18 19 0 ./list_increasing How many numbers in initial list?: 2 2 4 1 ./list_increasing How many numbers in initial list?: 1 42 1 ./list_increasing How many numbers in initial list?: 0 1
Assumptions/Restrictions/Clarifications
increasing
should return a single integerincreasing
should not change the linked list it is given. Your function should not change the next or data fields of list nodesincreasing
should not use arraysincreasing
should not callmalloc
increasing
should not call scanf (orgetchar
orfgets
)- You can assume the linked list only contains positive integers
increasing
should not print anything. It should not callprintf
- Do not change the supplied
main
function. It will not be tested or marked.
1091 style list_increasing.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest list_increasing
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab11_list_increasing list_increasing.c
You must run give
before Monday 11 November 09:00
to obtain the marks for this lab exercise.
Note that this is an individual exercise,
the work you submit with give
must be entirely your own.
list_increasing.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
int increasing(struct node *head);
struct node *array_to_list(int len, int array[]);
#define MAX_INIT_LIST_LEN 100
int main() {
// Need to read in a number of ints into an array
printf("How many numbers in initial list?: ");
int list_size = 0;
scanf("%d", &list_size);
int initial_elems[MAX_INIT_LIST_LEN] = {0};
int n_read = 0;
while (n_read < list_size && scanf("%d", &initial_elems[n_read])) {
n_read++;
}
// create linked list from first set of inputs
struct node *head = NULL;
if (n_read > 0) {
// list has elements
head = array_to_list(n_read, initial_elems);
}
int result = increasing(head);
printf("%d\n", result);
return 0;
}
// return 1 if values in a linked list are in increasing order,
// return 0, otherwise
int increasing(struct node *head) {
// If the list is empty, it's considered increasing, so return 1.
if (head == NULL) {
return 1;
}
// Assume that it is increasing, and look for evidence
// that proves otherwise.
int is_increasing = 1;
struct node *curr = head;
while (curr->next != NULL) {
// If this one is not less than the next one,
// the list definitely isn't increasing
// (since these two nodes are out of order).
if (curr->data >= curr->next->data) {
is_increasing = 0;
}
curr = curr->next;
}
// At this point, if is_increasing is still 1, we didn't find
// any nodes that were out of order.
//
// However, if we did find any nodes that were out of order,
// we set it to 0 in the loop above.
//
// So, is_increasing contains the answer to return.
return is_increasing;
}
// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *array_to_list(int len, int array[]) {
struct node *head = NULL;
int i = len - 1;
while (i >= 0) {
struct node *n = malloc(sizeof (struct node));
assert(n != NULL);
n->next = head;
n->data = array[i];
head = n;
i -= 1;
}
return head;
}
list_increasing.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
int increasing(struct node *head);
struct node *strings_to_list(int len, char *strings[]);
int main(int argc, char *argv[]) {
// create linked list from command line arguments
struct node *head = strings_to_list(argc - 1, &argv[1]);
int result = increasing(head);
printf("%d\n", result);
return 0;
}
// return 1 if values in a linked list are in increasing order,
// return 0, otherwise
int increasing(struct node *head) {
if (head == NULL) {
return 1;
}
struct node *p = head;
while (p->next != NULL) {
if (p->data >= p->next->data) {
return 0;
}
p = p->next;
}
return 1;
}
// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
struct node *head = NULL;
for (int i = len - 1; i >= 0; i = i - 1) {
struct node *n = malloc(sizeof (struct node));
assert(n != NULL);
n->next = head;
n->data = atoi(strings[i]);
head = n;
}
return head;
}
list_increasing.c
#include <stdio.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
// return 1 if values in a linked list in increasing order
// recursive solution
int increasing(struct node *head) {
if (head == NULL || head->next == NULL) {
return 1;
} else if (head->data >= head->next->data) {
return 0;
} else {
return increasing(head->next);
}
}
Exercise
(●●◌)
:
Insert into the nth position in a Linked List
Download list_insert_nth.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/list_insert_nth/list_insert_nth.c .
Your task is to add code to this function in list_insert_nth.c:
// Insert a new node containing value at position n of the linked list.
// if n == 0, node is inserted at start of list
// if n >= length of list, node is appended at end of list
// The head of the new list is returned.
struct node *insert_nth(int n, int value, struct node *head) {
// PUT YOUR CODE HERE! CHANGE THE NEXT LINES!
return NULL;
}
insert_nth
is given three arguments, n
value
and head
n
is an int.value
is an int.head
is the pointer to the first node in a linked list.
Add code to insert_nth
so that it creates a new list node (using malloc
)
containing value and places it before position n
of the list.
The elements are counted in the same manner as array elements (zero-based), so the first element in the list is regarded as at position 0, the second element position 1 and so on.
If there are less than n
elements in the list, the new list node should be
appended to the end of the list.
insert_nth
should return a pointer to the new list.
For example if n
is 1
and value
is 12
and the linked list contains
these 3 elements:
16, 7, 8
insert_nth
should return a pointer to a list with these elements:
16, 12, 7, 8
Testing
list_insert_nth.c
also contains a main
function which allows you to test
your insert_nth
function.
This main function:
- Asks for the size of the linked list,
- asks for standard input to convert to a linked list,
- assigns a pointer to the first node in the linked list to
head
, - reads an integer from standard input and assigns it to
n
, - reads a second integer from standard input and assigns it to
value
- calls
insert_nth(n, value, head)
and - prints the result.
Do not change this function. If you want to change it, you have misread the question.
Your insert_nth
function will be called directly in marking. The main
function is only to let you test your insert_nth
function
dcc list_insert_nth.c -o list_insert_nth ./list_insert_nth How many numbers in initial list?: 3 16 7 8 Enter position and value to insert: 0 12 [12, 16, 7, 8] ./list_insert_nth How many numbers in initial list?: 3 16 7 8 Enter position and value to insert: 1 12 [16, 12, 7, 8] ./list_insert_nth How many numbers in initial list?: 3 16 7 8 Enter position and value to insert: 2 12 [16, 7, 12, 8] ./list_insert_nth How many numbers in initial list?: 3 16 7 8 Enter position and value to insert: 3 12 [16, 7, 8, 12] ./list_insert_nth How many numbers in initial list?: 3 16 7 8 Enter position and value to insert: 42 12 [16, 7, 8, 12] ./list_insert_nth How many numbers in initial list?: 1 42 Enter position and value to insert: 0 16 [16, 42] ./list_insert_nth How many numbers in initial list?: 0 Enter position and value to insert: 0 2 [2] ./list_insert_nth How many numbers in initial list?: 0 Enter position and value to insert: 10 2 [2]
Assumptions/Restrictions/Clarifications
insert_nth
should not use arrays.insert_nth
should not call scanf (orgetchar
orfgets
).insert_nth
should not print anything. It should not callprintf
.- The
n
provided will always be non-negative - Do not change the supplied
main
function. It will not be tested or marked.
1091 style list_insert_nth.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest list_insert_nth
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab11_list_insert_nth list_insert_nth.c
You must run give
before Monday 11 November 09:00
to obtain the marks for this lab exercise.
Note that this is an individual exercise,
the work you submit with give
must be entirely your own.
list_insert_nth.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
struct node *insert_nth(int n, int value, struct node *head);
struct node *create_node(int data, struct node *next);
struct node *array_to_list(int len, int array[]);
void print_list(struct node *head);
// DO NOT CHANGE THIS MAIN FUNCTION
#define MAX_INIT_LIST_LEN 100
int main() {
// Need to read in a number of ints into an array
printf("How many numbers in initial list?: ");
int list_size = 0;
scanf("%d", &list_size);
int initial_elems[MAX_INIT_LIST_LEN] = {0};
int n_read = 0;
while (n_read < list_size && scanf("%d", &initial_elems[n_read])) {
n_read++;
}
// create linked list from first set of inputs
struct node *head = NULL;
if (n_read > 0) {
// list has elements
head = array_to_list(n_read, initial_elems);
}
printf("Enter position and value to insert: ");
int n;
scanf("%d", &n);
int value;
scanf("%d", &value);
struct node *new_head = insert_nth(n, value, head);
print_list(new_head);
return 0;
}
// Insert a new node containing value at position n of the linked list.
// if n == 0, node is inserted at start of list
// if n >= length of list, node is appended at end of list
// The head of the new list is returned.
struct node *insert_nth(int n, int value, struct node *head) {
struct node *new_node = malloc(sizeof (struct node));
if (new_node == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
new_node->data = value;
// new node is head of list
if (head == NULL || n == 0) {
new_node->next = head;
return new_node;
}
int i = n - 1;
struct node *p = head;
while (p->next != NULL && i > 0) {
p = p->next;
i = i - 1;
}
new_node->next = p->next;
p->next = new_node;
return head;
}
// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *array_to_list(int len, int array[]) {
struct node *head = NULL;
int i = len - 1;
while (i >= 0) {
struct node *n = malloc(sizeof (struct node));
assert(n != NULL);
n->next = head;
n->data = array[i];
head = n;
i -= 1;
}
return head;
}
// print linked list
void print_list(struct node *head) {
printf("[");
struct node *n = head;
while (n != NULL) {
// If you're getting an error here,
// you have returned an invalid list
printf("%d", n->data);
if (n->next != NULL) {
printf(", ");
}
n = n->next;
}
printf("]\n");
}
list_insert_nth.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
// Insert a new node containing value at position n of the linked list.
// if n == 0, node is inserted at start of list
// if n >= length of list, node is appended at end of list
// The head of the new list is returned.
// recursive version
struct node *insert_nth(int n, int value, struct node *head) {
if (n > 0 && head != NULL) {
head->next = insert_nth(n - 1, value, head->next);
return head;
}
struct node *new_node = malloc(sizeof (struct node));
if (new_node == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
new_node->data = value;
new_node->next = head;
return new_node;
}
Exercise
(●●◌)
:
Insert into the nth position in a Linked List
Download list_get_nth_v2.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/list_get_nth_v2/list_get_nth_v2.c .
Your task is to add code to this function in list_get_nth_v2.c:
Your task is to complete the program list_get_nth_v2.c
. This will be achieved by completing the get_nth
function. The program will ask the user to input the length of a linked list and the number of elements it contains. It will then ask for an nth element.
The elements are counted in the same manner as array elements (zero-based), so the first element in the list is regarded as n = 0, the second element as n = 1 and so on. In the case where there is no nth element in the list, an error message should be printed out.
Examples
dcc list_get_nth_v2.c -o list_get_nth_v2 ./list_get_nth_v2 How many elements in the list: 5 5 2 6 1 6 Which nth element would you like to find: 0 The nth value is 5! ./list_get_nth_v2 How many elements in the list: 6 1 2 3 4 5 6 Which nth element would you like to find: 7 ERROR: no nth element in list.
Assumptions/Restrictions/Clarifications
- The list will always have at least one element.
- The nth value will always be a whole number >= 0.
- Correct number of elements will always be given.
1091 style list_get_nth_v2.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest list_get_nth_v2
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab11_list_get_nth_v2 list_get_nth_v2.c
You must run give
before Monday 11 November 09:00
to obtain the marks for this lab exercise.
Note that this is an individual exercise,
the work you submit with give
must be entirely your own.
list_get_nth_v2.c
// List get nth
// list_get_nth.c
//
// This program was written by Morgan Swaak (z5476300)
// on 31-03-2024
//
// Prints the nth element in a linked list
#include <stdio.h>
#include <stdlib.h>
struct node {
struct node *next;
int data;
};
void create_list(struct node *head);
void get_nth(struct node *head, int n);
void delete_list(struct node *head);
// calls the functions for code to operate
int main(void) {
struct node *head = malloc(sizeof(struct node));
create_list(head);
int n;
printf("Which nth element would you like to find: ");
scanf("%d", &n);
get_nth(head, n);
delete_list(head);
return 0;
}
// finds the nth element of a linked list
void get_nth(struct node *head, int n) {
struct node *current = head;
while (current != NULL && n >= 0) {
if (n == 0) {
printf("The nth value is %d!\n", current->data);
}
n--;
current = current->next;
}
if (current == NULL && n >= 0) {
printf("ERROR: no nth element in list.\n");
}
}
// creates a linked list
void create_list(struct node *head) {
int num_elements;
printf("How many elements in the list: ");
scanf("%d", &num_elements);
struct node *current = head;
//always at least one element in list
int data;
scanf("%d", &data);
current->data = data;
int i = 1;
while (i < num_elements) {
current->next = malloc(sizeof(struct node));
current = current->next;
scanf("%d", &data);
current->data = data;
i++;
}
current->next = NULL;
printf("\n");
}
// frees all the memory associated with the linked list
void delete_list(struct node *head) {
struct node *current = head;
while (current != NULL) {
struct node *delete = current;
current = current->next;
free(delete);
}
}
Exercise
(●●●)
:
Determine whether a list of lists contains a diagonal line of identical values
Download lists_diagonal.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/lists_diagonal/lists_diagonal.c .
Your task is to add code to this function in lists_diagonal.c:
// Treat the linked lists like they're a 2D array
// and return 1 if the first element is repeated
// diagonally through the lists
int has_diagonal(struct list_node *head) {
return 0;
}
lists_diagonal.c
is written using struct node
and struct list_node
that
cannot be changed.
struct node
is a normal linked list node while struct list_node
is used to
make a linked list where each element contains a list of struct node
s.
For this exercise, you will implement the function has_diagonal
It should
take a pointer to the head of a struct list_node
linked list, and check the
values of the inner struct node
linked list.
Imagine each struct node
list as extending out from each struct list_node
list (i.e. a 2D linked list). has_diagonal
will return 1
if there is a
diagonal pattern, and 0
if there isn't.
A diagonal in this exercise means that the first number in the first list is the same as the second number in the second list and the third number in the third list and so on.
For example if the list of lists looks like this:
list_node 0 contains the list {5, 0, 0} list_node 1 contains the list {0, 5, 0} list_node 2 contains the list {0, 0, 5}
has_diagonal
should return 1
as the number 5
is repeated diagonally down
the list of lists:
list_node 0 contains the list {5, 0, 0} list_node 1 contains the list {0, 5, 0} list_node 2 contains the list {0, 0, 5}
However, if the list of lists looks like this:
list_node 0 contains the list {5, 0, 0, 0} list_node 1 contains the list {0, 4, 0, 0} list_node 2 contains the list {0, 0, 5, 0} list_node 3 contains the list {0, 0, 0, 5}
has_diagonal
should return 0
, because the 2nd element of the second list
does not equal the value of the first element of the first list:
list_node 0 contains the list {5, 0, 0, 0} list_node 1 contains the list {0, 4, 0, 0} list_node 2 contains the list {0, 0, 5, 0} list_node 3 contains the list {0, 0, 0, 5}
Assumptions/Restrictions/Clarifications
struct node
andstruct list_node
cannot be edited. They must be used as they are- You may not use arrays in this solution. Arrays are not necessary to complete this task
- You can assume that you'll never receive an empty list of
struct list_node
s - You can assume that all lists of
struct node
s are also not empty - You can assume that there will always be the same number of
struct node
s in each list and that will be the same number ofstruct list_node
s. That is to say, the 2D grid formed by the lists will always be square - Your submitted file may contain a
main
function. It will not be tested or marked
1091 style lists_diagonal.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest lists_diagonal
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab11_lists_diagonal lists_diagonal.c
You must run give
before Monday 11 November 09:00
to obtain the marks for this lab exercise.
Note that this is an individual exercise,
the work you submit with give
must be entirely your own.
lists_diagonal.c
#include <stdio.h>
#include <stdlib.h>
// Do not edit these structs. You may use them exactly as
// they are but you cannot make changes to them
// A node in a linked list
struct node {
int data;
struct node *next;
};
// a list_node in a linked list. Each list_node
// contains a list of nodes.
struct list_node {
struct node *my_list;
struct list_node *next;
};
// Treat the linked lists like they're a 2D array
// and return 1 if the first element is repeated
// diagonally through the lists
int has_diagonal(struct list_node *head) {
int has = 1;
int i = 0;
// assuming that we're never getting an empty first list
int number = head->my_list->data;
while (head != NULL) {
int j = 0;
struct node *n = head->my_list;
while (n != NULL) {
if (j == i && n->data != number) {
// we're at the diagonal and they're not equal
has = 0;
}
n = n->next;
j++;
}
i++;
head = head->next;
}
return has;
}
// This helper function is for the main below and will
// have no effect on your has_diagonal. It does not
// need to be modified.
struct node *make_list(int a, int b, int c);
// This is a main function which could be used
// to test your has_diagonal function.
// It will not be marked.
// Only your has_diagonal function will be marked.
//
// It's recommended to change the int values in this
// main to test whether your has_diagonal is working.
int main(void) {
struct list_node *head = malloc(sizeof (struct list_node));
struct list_node *l = head;
// create the first list
l->my_list = make_list(5, 0, 0);
// create the second list
l->next = malloc(sizeof (struct list_node));
l = l->next;
l->my_list = make_list(0, 5, 0);
// create the third list
l->next = malloc(sizeof (struct list_node));
l = l->next;
l->my_list = make_list(0, 0, 5);
l->next = NULL;
printf("The result of has_diagonal is: %d\n", has_diagonal(head));
return 0;
}
struct node *make_list(int a, int b, int c) {
struct node *head = malloc(sizeof (struct node));
struct node *n = head;
n->data = a;
n->next = malloc(sizeof (struct node));
n = n->next;
n->data = b;
n->next = malloc(sizeof (struct node));
n = n->next;
n->data = c;
n->next = NULL;
return head;
}
Exercise
— individual:
(Not For Marks) Debugging - List remove nth
Copy the program debug_cloud.c
from the course account to your
directory by typing (make sure you type the dot at the end):
cp ~dp1091/public_html/24T3/activities/debug_remove_nth/debug_remove_nth.c .
Note that this exercise is not marked or worth marks!
Debugging Tips!
Some debugging tips for you:
- dcc output - as you run into issues, dcc will point you to where the errors are. Remember that dcc gives you the line number the issue is on, and will give some sort of explanation. Make sure you read everything dcc gives you. Sometimes we get “errors carried forward”, so find your first error, fix that, then recompile.
- print statements - sometimes it can be handy to see if the flow of your code puts you in the spot you expect it to be (ie. inside the right if statement, or going through a loop the correct amount of times). A quick way you can check this is by putting print statements in your code for testing purposes, like
"the value of x is %d and y is %d"
. This lets you check that you got against what you expected. - DPST1091 debugging guide - https://cgi.cse.unsw.edu.au/~dp1091/23T3/resources/debugging_guide.html
The Task
This task takes in a linked list via command line arguments. Prompts the user to imput the index n
of the node which they wish to remove form the list. Then, the porgram attempts to remove the node at index n
via calling the delete_nth
.
For example if the existing list is 1 -> 2 -> 3 -> 4-> X
, if the user inputs 2
as the index of the node they wish to delete after calling the delete_nth
function on the list is as follows: 1 -> 2 -> 4 -> X
. Note, the node containing the value 3 is removed from the list since is the node at index 2
in the original list. Note we start counting indexes from 0.
Currently it has some issues it is your job to figure them out and fix the code. Note, you should only need to modify the delete_nth
function to fix the program.
Examples
dcc debug_remove_nth.c -o debug_remove_nth ./debug_remove_second_last 1 2 3 4 5 6 What is the position of the node you wish to remove: 2 Original list: [1, 2, 3, 4, 5, 6] Modified list: [1, 2, 4, 5, 6] ./debug_remove_second_last 1 2 3 What is the position of the node you wish to remove: 0 Original list: [1, 2, 3] Modified list: [2, 3] ./debug_remove_second_last 1 2 3 4 5 What is the position of the node you wish to remove: 4 Original list: [1, 2, 3, 4, 5] Modified list: [1, 2, 3, 4] ./debug_remove_second_last 1 What is the position of the node you wish to remove: 0 Original list: [1] Modified list: [] ./debug_remove_second_last What is the position of the node you wish to remove: 0 Original list: [] Modified list: [] ./debug_remove_second_last 1 2 3 4 What is the position of the node you wish to remove: 4 Original list: [1, 2, 3, 4] Index out of range, no node deleted Modified list: [1, 2, 3, 4] ./debug_remove_second_last 1 2 3 4 What is the position of the node you wish to remove: -1 Original list: [1, 2, 3, 4] Index out of range, no node deleted Modified list: [1, 2, 3, 4]
Assumptions/Restrictions/Clarifications
- You may assume all command line arguments will be integers
- The function prints
Index out of range, no node deleted
if the index entered by the user is greater then the legnth of the list. It then also does not modify the list.
1091 style debug_remove_nth.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest debug_remove_nth
debug_remove_nth.c
// debug_remove_nth.c
// This program removes the nth node of a linked list
// Written by Sofia De Bellis (z5418801), on July 2023
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
struct node {
struct node *next;
int data;
};
struct node *delete_nth(struct node *head, int index);
struct node *array_to_list(int len, char *array[]);
void print_list(struct node *head);
int get_list_length(struct node *head);
// DO NOT CHANGE THIS MAIN FUNCTION
int main(int argc, char *argv[]) {
// create linked list from command line arguments excluding the program name
struct node *head = NULL;
if (argc > 0) {
// list has elements
head = array_to_list(argc - 1, &argv[1]);
}
int index;
printf("What is the position of the node you wish to remove: ");
scanf("%d", &index);
printf("Original list: ");
print_list(head);
head = delete_nth(head, index);
printf("Modified list: ");
print_list(head);
return 0;
}
// Deletes the second last node in a linked list
// The deleted node is freed.
// The head of the list is returned.
struct node *delete_nth(struct node *head, int index) {
struct node *current = head;
if (head == NULL) {
return NULL;
}
if (index == 0) {
struct node *temp = head;
current = current->next;
free(temp);
return current;
}
int list_length = get_list_length(head);
if (index > list_length - 1 || index < 0) {
printf("Index out of range, no node deleted\n");
return head;
}
int i = 0;
while (current->next != NULL && i < index - 1) {
current = current->next;
i++;
}
struct node *temp = current->next;
current->next = temp->next;
free(temp);
return head;
}
// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *array_to_list(int len, char *array[]) {
struct node *head = NULL;
int i = len - 1;
while (i >= 0) {
struct node *n = malloc(sizeof (struct node));
assert(n != NULL);
n->next = head;
n->data = atoi(array[i]);
head = n;
i -= 1;
}
return head;
}
// DO NOT CHANGE THIS FUNCTION
// print linked list
void print_list(struct node *head) {
printf("[");
struct node *n = head;
while (n != NULL) {
// If you're getting an error here,
// you have returned an invalid list
printf("%d", n->data);
if (n->next != NULL) {
printf(", ");
}
n = n->next;
}
printf("]\n");
}
// DO NOT EDIT
// Gets the length of a linked lists
int get_list_length(struct node *head) {
int length = 0;
struct node *current = head;
while (current != NULL) {
length++;
current = current->next;
}
return length;
}
Submission
give
.
You only need to do this if the exercise specifies a give command, otherwise - the exercise is not worth marks.
You can run give
multiple times.
Only your last submission will be marked.
Don't submit any exercises you haven't attempted.
If you are working at home, you may find it more convenient to upload your work via give's web interface.
Remember you have until Week 12 Monday 9:00am to submit your work.
You cannot obtain marks by e-mailing your code to tutors or lecturers.
You check the files you have submitted here.
Automarking will be run by the lecturer several days after the submission deadline,
using test cases different to those autotest
runs for you.
(Hint: do your own testing as well as running autotest
.)
After automarking is run by the lecturer you can view your results here. The resulting mark will also be available via give's web interface.
Lab Marks
When all components of a lab are automarked you should be able to view the the marks via give's web interface or by running this command on a CSE machine:
1091 classrun -sturec
Generative AI Permission Level
In completing this assessment, you are permitted to use standard editing and referencing functions in the software you use to complete your assessment. These functions are described below. You must not use any functions that generate or paraphrase passages of text or other media, whether based on your own work or not.
If your Convenor has concerns that your submission contains passages of AI-generated text or media, you may be asked to account for your work. If you are unable to satisfactorily demonstrate your understanding of your submission, you may be referred to UNSW Conduct & Integrity Office for investigation for academic misconduct and possible penalties.
DPST1091/CPTG1391 Specific Information
You are permitted to use the tools dcc-help to help you understand the error messages you may get when compiling the code you have written.
You are permitted to use autotest-help to help you understand why your code may not be passing the automated tests.
You are not permitted to submit code generated by automatic AI tools such as Github Copilot, ChatGPT, Google Bard in DPST1091/CPTG1391/COMP1511 for assignments. Submitting code generated by Github Copilot, ChatGPT, Google Bard and similar tools will be treated as plagiarism.
Our reasoning behind our decisions:
Systems such as Github Copilot and ChatGPT based on large language models or other generative artificial intelligence techniques, look likely to become heavily used by programmers. However, you need a good understanding of the language you are coding in and the systems involved before you can effectively use these tools. Using these tools to generate code for DPST1091/CPTG1391/COMP1511 instead of writing the code yourself will hinder your learning.