Week 10 Laboratory Sample Solutions
Objectives
- working with structs and pointers
- introducing linked lists
- using memory allocation
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:
- mallocd_array
- list_print
- list_length
- list_insert_head
Worth 0.7 mark(s) in total:
- list_contains
- list_insert_tail
Worth 0.4 mark(s) in total:
- list_reverse
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
(●◌◌)
:
Working with malloc'd arrays
Download mallocd_array.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/mallocd_array/mallocd_array.c .
The main function has already been written for you. You must not modify it in any way.
Examples
dcc mallocd_array.c -o mallocd_array ./mallocd_array Enter size: 5 Enter 5 integers: 1 2 3 4 5 The average of all values in the array is: 3.00 ./mallocd_array Enter size: 1 Enter 1 integers: 10 The average of all values in the array is: 10.00 ./mallocd_array Enter size: 3 Enter 3 integers: 5 -4 -3 The average of all values in the array is: -0.67
Assumptions/Restrictions/Clarifications
- You do not need to handle memory leaks for this exercise. i.e. You should not
call
free
- All inputs be of the correct type
1091 style mallocd_array.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest mallocd_array
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab10_mallocd_array mallocd_array.c
You must run give
before Monday 04 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.
mallocd_array.c
// Written by lorenzo lee solano
// June, 2022
#include <stdio.h>
#include <stdlib.h>
//////////////// DO NOT CHANGE ANY OF THE CODE BELOW HERE //////////////////
int *scan_array(int size);
double calculate_average(int *array, int size);
int main (void) {
int size;
printf("Enter size: ");
scanf(" %d", &size);
if (size <= 0) {
printf("Invalid Size\n");
return 1;
}
printf("Enter %d integers:\n", size);
int *array = scan_array(size);
printf("The average of all values in the array is: %.2lf\n",
calculate_average(array, size));
return 0;
}
//////////////// DO NOT CHANGE ANY OF THE CODE ABOVE HERE //////////////////
////////////////////////////////////////////////////////////////////////////
///////////////////// ONLY WRITE CODE BELOW HERE ///////////////////////////
////////////////////////////////////////////////////////////////////////////
// A function which scans in `size` integers and stores them into a
// malloc'd array.
// returns: a pointer to the malloc'd array
int *scan_array(int size) {
int i = 0;
int *array = malloc(sizeof(int) * size);
while (i < size) {
scanf(" %d", &array[i]);
i++;
}
return array;
}
// Given an integer array and it's size,
// returns the sum of all elements inside the array, divided by the size of the
// array.
double calculate_average(int *array, int size) {
int i = 0;
int sum = 0;
while (i < size ) {
sum += array[i];
i++;
}
return 1.0 * sum/size;
}
////////////////////////////////////////////////////////////////////////////
///////////////////// ONLY WRITE CODE ABOVE HERE ///////////////////////////
////////////////////////////////////////////////////////////////////////////
Exercise
(●◌◌)
:
Print out the elements of a Linked List
Download list_print.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/list_print/list_print.c .
Your task is to add code to this function in list_print.c:
// print a linked list in this format:
// 17 -> 34 -> 51 -> 68 -> X
void print(struct node *head) {
// PUT YOUR CODE HERE
}
print
is given one argument, head
, which is the pointer to the first node
in a linked list.
Your program will be supplied up to 50 integers, which will be put into a
linked list that is passed to the print
.
Add code to print
so that it prints the elements in the list.
For example, if the linked list contains these 8 elements:
1, 7, 8, 9, 13, 19, 21, 42
print
should print
1 -> 7 -> 8 -> 9 -> 13 -> 19 -> 21 -> 42 -> X
(including the X)
Testing
list_print.c
also contains a main
function which allows you to test your
print
function.
This main
function:
- converts the input from terminal into a linked list
- assigns a pointer to the first node in the linked list to
head
- calls
list_print(head)
Do not change this function. If you want to change it, you have misread the question.
Your list_print
function will be called directly in marking. The main
function is only to let you test your list_print
function.
Examples
dcc list_print.c -o list_print ./list_print 1 2 4 8 16 32 64 128 256 1 -> 2 -> 4 -> 8 -> 16 -> 32 -> 64 -> 128 -> 256 -> X ./list_print 2 4 6 5 8 9 2 -> 4 -> 6 -> 5 -> 8 -> 9 -> X ./list_print 42 4 42 -> 4 -> X ./list_print 43 43 -> X ./list_print X
Assumptions/Restrictions/Clarifications
- You can assume the input will never be more than 50 integers.
print
should not change the linked list it is given. Your function should not change the next or data fields of list nodes.print
should not use arrays.print
should not call malloc.print
should not call scanf (or getchar or fgets).- Do not change the supplied
main
function. It will not be tested or marked.
1091 style list_print.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest list_print
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab10_list_print list_print.c
You must run give
before Monday 04 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_print.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define MAX_LEN 50
struct node {
struct node *next;
int data;
};
void print(struct node *head);
struct node *array_to_list(int len, int num_array[]);
int main(void) {
// create linked list from input
int input_arr[MAX_LEN] = {0};
int total_num = 0;
int input_num;
while (scanf(" %d", &input_num) == 1) {
input_arr[total_num] = input_num;
total_num++;
}
struct node *head = array_to_list(total_num, input_arr);
print(head);
return 0;
}
// Solution \/
////////////////////////////////////////////////////////////////////////////////
// print a linked list in this format:
// 17 -> 34 -> 51 -> 68 -> X
void print(struct node *head) {
struct node *n = head;
while (n != NULL) {
printf("%d -> ", n->data);
n = n->next;
}
printf("X\n");
}
////////////////////////////////////////////////////////////////////////////////
// create linked list from array of strings
struct node *array_to_list(int len, int num_array[]) {
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 = num_array[i];
head = n;
}
return head;
}
list_print.c
#include <stdio.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
// print a linked list in this format:
// 17 -> 34 -> 51 -> 68 -> X
void print(struct node *head) {
if (head == NULL) {
printf("X\n");
}
printf("%d -> ", head->data);
print(head->next);
}
Exercise
(●◌◌)
:
Find the length of a Linked List
Download list_length.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/list_length/list_length.c .
Your task is to add code to this function in list_length.c:
// Return the length of the linked list pointed by head
int length(struct node *head) {
// PUT YOUR CODE HERE (change the next line!)
return 42;
}
For this exercise, you will be given a linked list nodes containing integers, shown below.
struct node { struct node *next; int data; };
Your job is to complete the length
function.
length
is given one argument, head
, which is the pointer to the first node
in a linked list.
Add code to length
so that its returns the length of the list.
For example if the linked list contains these 8 elements:
1, 7, 8, 9, 13, 19, 21, 42
length
should return 8
.
Testing
list_length.c
also contains a main
function which allows you to test your
length
function.
This main function:
- scans in number of items in the list, and its values; to create a linked list,
- assigns a pointer to the first node in the linked list to
head
, - calls
list_length(head)
, then - prints the result.
Do not change this function. If you want to change it, you have misread the question.
Your list_length
function will be called directly in marking. The main
function is only to let you test your list_length
function
Examples
dcc list_length.c -o list_length ./list_length How many numbers in initial list?: 9 1 2 3 6 5 4 9 9 0 Counted 9 elements in linked list. ./list_length How many numbers in initial list?: 6 1 2 3 6 5 4 Counted 6 elements in linked list. ./list_length How many numbers in initial list?: 5 1 2 3 4 5 Counted 5 elements in linked list. ./list_length How many numbers in initial list?: 2 42 4 Counted 2 elements in linked list. ./list_length How many numbers in initial list?: 0 Counted 0 elements in linked list.
Assumptions/Restrictions/Clarifications
length
should return a single integerlength
should not change the linked list it is given- Your function should not change the next or data fields of list nodes
length
should not use arrayslength
should not callmalloc
length
should not call scanf (orgetchar
orfgets
)length
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_length.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest list_length
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab10_list_length list_length.c
You must run give
before Monday 04 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_length.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
int length(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 = length(head);
printf("%d\n", result);
return 0;
}
// Return length of a linked list.
int length(struct node *head) {
int len = 0;
struct node *n = head;
while (n != NULL) {
len = len + 1;
n = n->next;
}
return len;
}
// 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_length.c
#include <stdio.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
// Return length of a linked list.
int length(struct node *head) {
if (head == NULL) {
return 0;
}
return 1 + length(head->next);
}
Exercise
(●◌◌)
:
Insert an element at the head of a Linked List
Download list_insert_head.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_head/list_insert_head.c .
Your task is to add code to this function in list_insert_head.c:
// WRITE YOUR CODE INSIDE HERE ONLY!!!
// Insert a new node containing value at the start of the linked list.
// The head of the new list is returned.
struct node *insert_head(int value, struct node *head) {
// PUT YOUR CODE HERE (change the next line!)
return NULL;
}
insert_head
is given two arguments, value
and head
.
value
is anint
head
is the pointer to the first node in a linked list
Add code to insert_head
so that it creates a new list node (using malloc
)
containing value and places it at the start of the list.
insert_head
should return a pointer to the new list.
For example if value
is 12
and the linked list contains these 3 elements:
16, 7, 8
insert_head
should return a pointer to a list with these elements:
12, 16, 7, 8
Testing
list_insert_head.c
also contains a main
function which allows you to test
your insert_head
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
- reads another single integer from standard input and assigns it to
value
- calls
insert_head(value, head)
- prints the result.
Do not change this function. If you want to change it, you have misread the question.
Your insert_head
function will be called directly in marking. The main
function is only to let you test your insert_head
function
dcc list_insert_head.c -o list_insert_head ./list_insert_head How many numbers in initial list?: 3 16 7 8 Enter number to insert to head: 12 [12, 16, 7, 8] ./list_insert_head How many numbers in initial list?: 1 16 Enter number to insert to head: 42 [42, 16] ./list_insert_head How many numbers in initial list?: 0 Enter number to insert to head: 2 [2]
Assumptions/Restrictions/Clarifications
insert_head
should not use arraysinsert_head
should not call scanf (orgetchar
orfgets
)insert_head
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_insert_head.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest list_insert_head
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab10_list_insert_head list_insert_head.c
You must run give
before Monday 04 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_head.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
struct node *insert_head(int value, struct node *head);
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 number to insert to head: ");
int value = 0;
scanf("%d", &value);
struct node *new_head = insert_head(value, head);
print_list(new_head);
return 0;
}
// WRITE YOUR CODE INSIDE HERE ONLY!!!
// Insert a new node containing value at the start of the linked list.
// The head of the new list is returned.
struct node *insert_head(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->next = head;
return new_node;
}
// 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;
}
// 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");
}
Exercise
(●●◌)
:
Find an element in a Linked List
Download list_contains.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/list_contains/list_contains.c .
Your task is to add code to this function in list_contains.c:
// Return 1 if value occurs in linked list, 0 otherwise
int contains(char *value, struct node *head) {
// PUT YOUR CODE HERE (change the next line!)
return 42;
}
contains
is given two arguments, a string value
and head
which is the
pointer to the first node in a linked list.
Add code to contains
so that it returns 1
if value
occurs in the linked
list and otherwise it returns 0
.
For example if the linked list contains these 7 elements:
"mozzarella" "pepperoni" "basil" "ham" "tomato bacon" "cheesy-crust" "bocconcini"
and contains
is called with value
of "mozzarella"
,
contains
should return 1
.
Testing
list_contains.c
also contains a main
function which allows you to test your
contains
function.
This main function:
- Asks for how many strings will be in our list,
- reads in and converts that n many strings to a linked list,
- assigns a pointer to the first node in the linked list to
head
, - reads another single string from standard input and assigns it to
value
. - calls
list_contains(value, head)
and - prints the result.
Do not change this function. If you want to change it, you have misread the question.
Your list_contains
function will be called directly in marking. The main
function is only to let you test your list_contains
function
Examples
dcc list_contains.c -o list_contains ./list_contains How many strings in initial list?: 4 pepperoni ham basil capsicum Enter word to check contained: basil 1 ./list_contains How many strings in initial list?: 4 pepperoni ham basil capsicum Enter word to check contained: mozzarella 0 ./list_contains How many strings in initial list?: 4 chicken mushroom mushroom pizza-sauce Enter word to check contained: mushroom 1 ./list_contains How many strings in initial list?: 4 tomato bacon capsicum mushroom Enter word to check contained: pepperoni 0 ./list_contains How many strings in initial list?: 0 Enter word to check contained: tomato 0
Assumptions/Restrictions/Clarifications
- String matching is case sensitive.
"Tomato"
does not match"tomato"
. No strings will have thespace
character in them contains
should return a single integer.contains
should not change the linked list it is given. Your function should not change the next or data fields of list nodes.contains
should not use arrays.contains
should not call malloc.contains
should not call scanf (or getchar or fgets).contains
should not print anything. It should not call printf.- Do not change the supplied
main
function. It will not be tested or marked.
1091 style list_contains.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest list_contains
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab10_list_contains list_contains.c
You must run give
before Monday 04 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_contains.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define MAX_STRING_SIZE 1024
#define MAX_STRINGS 50
struct node {
struct node *next;
char data[MAX_STRING_SIZE];
};
int contains(char *value, struct node *head);
struct node *strings_to_list(int len, char *strings[]);
void remove_newline(char *string);
// DO NOT CHANGE THIS MAIN FUNCTION
int main(void) {
// Need to read in a number of ints into an array
printf("How many strings in initial list?: ");
int list_size = 0;
scanf("%d ", &list_size);
char *initial_elems[MAX_STRINGS] = {NULL};
int i = 0;
while (i < list_size) {
//Allocate string:
char *string = malloc(sizeof(char) * MAX_STRING_SIZE);
// scan string
fgets(string, MAX_STRING_SIZE, stdin);
remove_newline(string);
initial_elems[i] = string;
i++;
}
printf("Enter word to check contained: ");
// Read in word to check that contained inside
char value[MAX_STRING_SIZE] = {'\0'};
fgets(value, MAX_STRING_SIZE, stdin);
remove_newline(value);
// create linked list from inputs
struct node *head = NULL;
if (list_size > 0) {
// list has elements
head = strings_to_list(list_size, initial_elems);
}
int result = contains(value, head);
printf("%d\n", result);
return 0;
}
// Return 1 if value occurs in linked list, 0 otherwise
int contains(char *value, struct node *head) {
struct node *curr = head;
while (curr != NULL && strcmp(curr->data, value) != 0) {
curr = curr->next;
}
if (curr == NULL) {
return 0;
}
return 1;
}
// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct node *strings_to_list(int len, char *strings[]) {
struct node *head = NULL;
int i = len - 1;
while (i >= 0) {
struct node *n = malloc(sizeof (struct node));
assert(n != NULL);
n->next = head;
strcpy(n->data, strings[i]);
head = n;
i -= 1;
}
return head;
}
// Strips newline off the end of a string.
void remove_newline(char *string) {
int len = strlen(string);
if (len > 0 && string[len - 1] == '\n') {
string[len - 1] = '\0';
}
}
list_contains.c
#include <stdio.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
// Return 1 if value occurs in linked list, 0 otherwise
int contains(int value, struct node *head) {
if (head == NULL) {
return 0;
}
return (head->data == value) || contains(value, head->next);
}
Exercise
(●●◌)
:
Insert an element at the end of a Linked List
Download list_insert_tail.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_tail/list_insert_tail.c .
Your task is to add code to this function in list_insert_tail.c:
// Insert a new node containing value at the end of the linked list.
// Parameters:
// `int value` : The value to insert.
// `struct list *list` : a struct * containing the head pointer of the
// linked list.
void insert_tail(int value, struct list *list) {
// PUT YOUR CODE HERE
}
insert_tail
is given two arguments:
value
is an intlist
is the pointer to astruct list
which contains- the
head
(a pointer to the first node) of the linked list
Add code to insert_tail
so that it creates a new list node (using malloc
)
containing value and places it at the end of the list.
insert_tail
should return nothing.
For example if value
is 12
and the linked list contains these 3 elements:
16, 7, 8
insert_tail
should modify the linked list so that it now has these elements:
16, 7, 8, 12
Testing
list_insert_tail.c
also contains a main
function which allows you to test
your insert_tail
function.
This main function:
- Asks for the size of the initial linked list
- converts the first set of scanned inputs to a linked list
- stores the first node of the linked list in a
struct list
. - reads a single integer from standard input and assigns it to
value
- calls
insert_tail(value, list)
- prints the result.
Do not change this main function. If you want to change it, you have misread the question.
Your insert_tail
function will be called directly in marking. The main
function is only to let you test your insert_tail
function
Examples
dcc list_insert_tail.c -o list_insert_tail ./list_insert_tail How many numbers in initial list?: 3 16 7 8 Enter value to insert: 12 [16, 7, 8, 12] ./list_insert_tail How many numbers in initial list?: 1 16 Enter value to insert: 42 [16, 42] ./list_insert_tail How many numbers in initial list?: 0 Enter value to insert: 2 [2]
Assumptions/Restrictions/Clarifications
insert_tail
should not use arraysinsert_tail
should not call scanf (orgetchar
orfgets
)insert_tail
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_insert_tail.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest list_insert_tail
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab10_list_insert_tail list_insert_tail.c
You must run give
before Monday 04 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_tail.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
// DO NOT CHANGE THESE STRUCTS
struct list {
struct node *head;
};
struct node {
struct node *next;
int data;
};
void insert_tail(int value, struct list *list);
struct list *array_to_list(int len, int array[]);
void print_list(struct list *list);
struct node *last(struct node *head);
struct node *create_node(int data, struct node *next);
// 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 list *list = NULL;
// list has elements
list = array_to_list(n_read, initial_elems);
printf("Enter value to insert: ");
int value;
scanf("%d", &value);
insert_tail(value, list);
print_list(list);
return 0;
}
void insert_tail(int value, struct list *list) {
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 = NULL;
// empty list is a special case
// new node is now the head of the now 1 element list
if (list->head == NULL) {
list->head = new_node;
} else {
struct node *l = last(list->head);
l->next = new_node;
}
}
// return pointer to last node in list
// NULL is returned if list is empty
struct node *last(struct node *head) {
if (head == NULL) {
return NULL;
}
struct node *n = head;
while (n->next != NULL) {
n = n->next;
}
return n;
}
// DO NOT CHANGE THIS FUNCTION
// create linked list from array of strings
struct list *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;
}
struct list *list = malloc(sizeof(struct list));
list->head = head;
return list;
}
// DO NOT CHANGE THIS FUNCTION
// print linked list
void print_list(struct list *list) {
printf("[");
struct node *n = list->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");
}
Exercise
(●●●)
:
Reverse a Linked List
Download list_reverse.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/list_reverse/list_reverse.c .
Your task is to add code to this function in list_reverse.c:
//
// Place the list pointed to by head into reverse order.
// The head of the list is returned.
//
struct node *reverse(struct node *head) {
// PUT YOUR CODE HERE (change the next line!)
return NULL;
}
Note list_reverse.c
uses the following familiar data type:
struct node { struct node *next; int data; };
list_reverse
is given one argument, head
which is the pointer to the first
node in the linked list.
Add code to reverse
which rearranges the list to be in reverse order.
reverse
should return a pointer to the new list.
reverse
must rearrange the list by changing the next
fields of nodes.
reverse
must not change the data
fields of nodes.
For example if the linked list contains these 8 elements:
16, 7, 8, 12, 13, 19, 21, 12
reverse
should return a pointer to a list with these elements:
12, 21, 19, 13, 12, 8, 7, 16
Testing
list_reverse.c
also contains a main
function which allows you to test your
list_reverse
function.
This main function:
- takes in the size of the linked list,
- converts the input numbers to a linked list,
- assigns a pointer to the first node in the linked list to
head
, - calls
reverse(head)
and - prints the result.
Do not change this function. If you want to change it, you have misread the question.
Your list_reverse
function will be called directly in marking. The main
function is only to let you test your list_reverse
function
Examples
dcc list_reverse.c -o list_reverse ./list_reverse How many numbers in list?: 8 16 7 8 12 13 19 21 12 [12, 21, 19, 13, 12, 8, 7, 16] ./list_reverse How many numbers in list?: 6 2 4 6 2 4 6 [6, 4, 2, 6, 4, 2] ./list_reverse 42 How many numbers in list?: 1 42 [42] ./list_reverse How many numbers in list?: 0 []
Assumptions/Restrictions/Clarifications
list_reverse
should not change the data fields of list nodeslist_reverse
should not use arrayslist_reverse
should not callmalloc
list_reverse
should not call scanf (orgetchar
orfgets
)list_reverse
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_reverse.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest list_reverse
When you are finished working on this exercise,
you must
submit your work by running give
:
give dp1091 lab10_list_reverse list_reverse.c
You must run give
before Monday 04 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_reverse.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
struct node *reverse(struct node *head);
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 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);
}
struct node *new_head = reverse(head);
print_list(new_head);
return 0;
}
// Place the list into reverse order.
// The head of the list is returned.
struct node *reverse(struct node *head) {
if (head == NULL) {
return NULL;
}
struct node *previous = NULL;
struct node *x = head;
while (x != NULL) {
struct node *y = x->next;
x->next = previous;
previous = x;
x = y;
}
return previous;
}
// 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("[");
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");
}
list_reverse.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
// Place the list into reverse order.
// The head of the list is returned.
struct node *reverse(struct node *head) {
// lists of 0 or 1 node don't need to be changed
if (head == NULL || head->next == NULL) {
return head;
}
//reverse rest of list
struct node *new_head = reverse(head->next);
// head->next will be the last element in the reversed rest of list
// append head to it
head->next->next = head;
head->next = NULL;
return new_head;
}
Exercise
— individual:
(Not For Marks) Debugging - Product
Copy the program debug_product.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_product/debug_product.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 exercise takes integers as command line arguments and calculates their cumulative product. However, if the number is 0 or not an integer, it is not added to the cumulative product of command line arguments. Currently it has some issues - it is your job to figure them out and fix the code.
Examples
dcc debug_product.c -o debug_product ./debug_product 0 1 2 3 4 5 Product: 120 ./debug_product -5 1 -1 -2 Product: -10 ./debug_product 100 these are my arguments -2 Product: -200 ./debug_product these are my command line arguments Product: 0
Assumptions/Restrictions/Clarifications
- You may find the
atoi()
function in the C standard library (stdlib.h
) useful. - You may assume that
argv[0]
will always be the program name.
1091 style debug_product.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest debug_product
debug_product.c
// debug_product.c
//
// Thir program calucuates the product of command line args
//
// Written by Sofia De Bellis (z5418801), on July 2023
#include <stdlib.h>
#include <stdio.h>
int main (int argc, char *argv[]) {
int prod = 0;
for (int i = 1; i < argc; i++) {
if (atoi(argv[i]) != 0) {
if (prod == 0) {
prod = 1;
}
prod *= atoi(argv[i]);
}
}
printf("Product: %d\n", prod);
}
Exercise
— individual:
(Not For Marks) Debugging - List insert second last
Copy the program debug_insert_second_last.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_insert_second_last/debug_insert_second_last.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 exercise takes in the length of a linked list, followed by the elements of the list. Then it takes in a single value to be inserted as the second last node of the list previously created.
For example if the existing list is 1 -> 2 -> 3 -> X
and a node with value 4 is being inserted, after insertion the list is as follows: 1 -> 2 -> 4 -> 3 -> X
. Note, the node containging the value 4 is inserted before the node containing the value 3 since the node containing the value 3 is at the tail (i.e the last node) of the list since it points at null
.
Currently it has some issues when attempting to insert the value as the second last node in the list - it is your job to figure them out and fix the code.
Examples
dcc debug_insert_second_last.c -o debug_insert_second_last ./debug_insert_second_last How many numbers in initial list?: 3 1 2 3 Enter the value to insert: 4 [1, 2, 4, 3] ./debug_insert_second_last How many numbers in initial list?: 6 5 2 9 10 4 7 Enter the value to insert: 0 [5, 2, 9, 10, 4, 0, 7] ./debug_insert_second_last How many numbers in initial list?: 1 23 Enter the value to insert: 5 [5, 23] ./debug_insert_second_last How many numbers in initial list?: 0 Enter the value to insert: 4 [4]
Assumptions/Restrictions/Clarifications
- You do not need to edit the
main()
,array_to_list()
,print_list()
orget_list_length()
functions.
1091 style debug_insert_second_last.c
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest debug_insert_second_last
debug_insert_second_last.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
struct node {
struct node *next;
int data;
};
#define MAX_INIT_LIST_LEN 100
struct node *insert_second_last(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);
int get_list_length(struct node *head);
int main(void) {
// 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 the value to insert: ");
int value;
scanf("%d", &value);
struct node *new_head = insert_second_last(value, head);
print_list(new_head);
return 0;
}
// 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;
}
// Insert a new node containing value at the second last position of the linked list.
// The head of the new list is returned.
struct node *insert_second_last(int value, struct node *head) {
struct node *new_node = malloc(sizeof (struct node));
new_node->data = value;
new_node->next = NULL;
int list_length = get_list_length(head);
// new node is head of list
if (head == NULL || list_length == 1) {
new_node->next = head;
return new_node;
}
struct node *p = head;
int i = 1;
while (p->next != NULL && i < (list_length - 1) ) {
p = p->next;
i++;
}
new_node->next = p->next;
p->next = new_node;
return head;
}
// DO NOT EDIT
// 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));
n->next = head;
n->data = array[i];
head = n;
i -= 1;
}
return head;
}
// DO NOT EDIT
// 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");
}
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 11 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.