Week 06 Extra Sample Solutions
Information
- This page contains extra exercises for week 06.
- These exercises are not compulsory, nor do they provide any marks in the course.
- You cannot submit any of these exercises, however autotests are available for them (Command included at bottom of each exercise).
Exercise
(●◌◌)
:
Count Bigger
Download count_bigger.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/count_bigger/count_bigger.c .
count_bigger
should return a single integer: the number of values in the
array which are larger than 99 or smaller than -99.
For example if the array contains these 8 elements:
141, 5, 92, 6, 535, -89, -752, -3
Your function should return 3
, because these 3
elements are
bigger than 99
or smaller than -99
:
141, 535, -752
Assumptions/Restrictions/Clarifications
count_bigger
should return a single integercount_bigger
should not change the array it is givencount_bigger
should not callscanf
(orgetchar
orfgets
)- You can assume the array contains at least one integer
count_bigger
should not print anything. It should not callprintf
- Your submitted file may contain a main function. It will not be tested or marked
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest count_bigger
count_bigger.c
int count_bigger(int length, int array[length]) {
int bigger = 0;
int i = 0;
while (i < length) {
if (array[i] > 99 || array[i] < -99) {
bigger = bigger + 1;
}
i = i + 1;
}
return bigger;
}
Exercise
(●◌◌)
:
Identity Matrix
Download identity_matrix.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/identity_matrix/identity_matrix.c .
Your task is to add code to this function in identity_matrix.c:
//Makes a square matrix into an identity matrix
void make_identity(int size, int matrix[size][size]) {
//TODO: Complete this function
}
The above file identity_matrix.c contains a function make_identity(), which should change the matrix passed in to be the identity matrix of coresponding size.
The identity matrix is a square, 2D array with all the cells containing 0, excluding those on the diagonal from top left to bottom right, which contain a value of 1.
For example, the identity matrix of:
0 1 2 3 4 5 6 7 8is:
1 0 0 0 1 0 0 0 1
The provided function doesn't actually work. Your task is to complete this function.
You can assume the 2D array will always be square and only contain integers from 0 to 9.
The file also contains a main function and a print function which you can use to help test your make_identity() function. It has one simple test case.
This main function and the print function will not be marked -- you must write all of your code in the make_identity() function. You may modify the main function if you wish (e.g. to add further tests), but only the make_identity() function will be marked.
Once your program is working, the output from the provided test in the main function should be:
dcc -o identity_matrix identity_matrix.c ./identity_matrix 1 0 0 0 1 0 0 0 1
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest identity_matrix
identity_matrix.c
// identity_matrix.c
// Given a 2D array (or matrix), find the
// Corresponding identity matrix
// Liz Willer
// March 2020
#include <stdio.h>
#include <stdlib.h>
void make_identity(int size, int matrix[size][size]);
void print_matrix(int size, int matrix[size][size]);
int main(void){
int array2[2][2] = {{3, 1}, {4, 1}};
int array3[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
int array10[10][10] = {{0}};
make_identity(2, array2);
make_identity(3, array3);
make_identity(10, array10);
print_matrix(2, array2);
printf("\n");
print_matrix(3, array3);
printf("\n");
print_matrix(10, array10);
return 0;
}
void make_identity(int size, int matrix[size][size]) {
int i = 0;
while (i < size){
int j = 0;
while (j < size){
matrix[i][j] = 0;
j++;
}
i++;
}
i = 0;
while (i < size) {
matrix[i][i] = 1;
i++;
}
}
void print_matrix(int size, int matrix[size][size]) {
int i = 0;
while (i < size){
int j = 0;
while (j < size){
printf("%d ", matrix[i][j]);
j++;
}
printf("\n");
i++;
}
}
Exercise
(●●●)
:
Harder Refactoring Code
Download class_details.c here, or copy it to your CSE account using the following command:
cp -n /import/reed/A/dp1091/public_html/24T3/activities/class_details/class_details.c .
For this activity, you've been provided with a fully working program: class_details.c
.
While this code produces the correct output, it's code style is not very good.
In particular, class_detail.c
is full of magic numbers and repeating code,
and it's main function is more than 200 lines long!
Try running 1091 style class_details.c
to see even more of it's
style issues.
For this activity Your job is to go through and improve the readability of the code by
- Replacing magic numbers with enums and #defines,
- Breaking it up into small functions (less than 40 lines),
- Using those functions to remove unnecessary repetition,
- Writing some function comments to document the code.
Program description:
Below is a description of the program. Keep in mind that this has all already been implemented for you.
The provided program scans in and stores the details of students in a class. It first scans in the size of the class, and then scans in the details of each of the students including:
- zID
- Degree type (Undergraduate/Postgraduate)
- Major (if an Undergraduate)
- Assignments mark (Collated mark of assignments and labs)
- Exam mark
- Course grade
Once all student details have been scanned in, The program then loops and scans in commands. It doesn't stop looping until the QUIT
command is entered.
The program performs one of the following tasks:
- Command 0 Help: Display program instructions
- Command 1 (Display Student): Print the details of a specific student
- Command 2 (Display Class): Print the details of all students in a class
- Command 3 (Quit): Exit the program
./class_details Enter Class Size: 1 Student 1: Enter zID: 5111111 Select Degree Type: 0: Undergraduate 1: Postgraduate 0 Select Major: 0: Computer Science 1: Database Systems 2: eCommerce Systems 3: Artificial Intelligence 4: Programming Languages 5: Computer Networks 6: Embedded Systems 7: Security Engineering 8: None 2 Enter Assignments mark (out of 60): 35.5 Enter exam mark (out of 40): 30 Enter Command Number (0 for Help): 0 Enter a number corresponding to one of the following commands: 0 (Help): Display program instructions 1 (Display Student): Print the details of a specific student 2 (Display Class): Print the details of all students in a class 3 (Quit): Exit the program Enter Command Number (0 for Help): 1 Enter Student zID: 5222222 No student with that zID exists Enter Command Number (0 for Help): 1 Enter Student zID: 5111111 z5111111: { Degree Type: Undergraduate Major: eCommerce Systems Assignments Mark: 35.50/60 Exam Mark: 30.00/40 Course Grade: 65.50/100 } Enter Command Number (0 for Help): 100 Invalid Command Enter Command Number (0 for Help): 3 Exiting Program
./class_details Enter Class Size: 2 Student 1: Enter zID: 5111111 Select Degree Type: 0: Undergraduate 1: Postgraduate 0 Select Major: 0: Computer Science 1: Database Systems 2: eCommerce Systems 3: Artificial Intelligence 4: Programming Languages 5: Computer Networks 6: Embedded Systems 7: Security Engineering 8: None 6 Enter Assignments mark (out of 60): 35.5 Enter exam mark (out of 40): 30 Student 2: Enter zID: 5222222 Select Degree Type: 0: Undergraduate 1: Postgraduate 1 Enter Assignments mark (out of 60): 40.5 Enter exam mark (out of 40): 25.9 Enter Command Number (0 for Help): 2 Students: z5111111: { Degree Type: Undergraduate Major: Embedded Systems Assignments Mark: 35.50/60 Exam Mark: 30.00/40 Course Grade: 65.50/100 } z5222222: { Degree Type: Postgraduate Assignments Mark: 40.50/60 Exam Mark: 25.90/40 Course Grade: 66.40/100 } Enter Command Number (0 for Help): 1 Enter Student zID: 5222222 z5222222: { Degree Type: Postgraduate Assignments Mark: 40.50/60 Exam Mark: 25.90/40 Course Grade: 66.40/100 } Enter Command Number (0 for Help): 3 Exiting Program
Assumptions/Restrictions/Hints
- You should not change the functionality of the program in any way.
- If there are any edge cases not handled by the original code (e.g. students sharing zids), you do not need to modify the code to handle them.
- All inputs will positive, and be the correct type
When you think your program is working,
you can use autotest
to run some simple automated tests:
1091 autotest class_details
class_details.c
// Written June 2022
// By Enzo Lee Solano (z5258621)
//
// Interactive program to scan in and display the details of students in a
// class.
#include <stdio.h>
#define MAX_CLASS_SIZE 20
#define MAX_EXAM_MARK 40
#define MAX_ASSIGMENTS_MARK 60
#define NOT_FOUND -1
enum loop_sentinal { STOP_LOOPING, KEEP_LOOPING };
enum command {HELP, PRINT_STUDENT, PRINT_CLASS, QUIT, INVALID_COMMAND };
enum degree_type {UGRD, PGRD, INVALID_DEGREE};
enum major {
COMPA1,
COMPD1,
COMPE1,
COMPI1,
COMPJ1,
COMPN1,
COMPS1,
COMPY1,
NONE
};
struct student {
int z_id;
enum major major;
enum degree_type degree_type;
double assignments_mark;
double exam_mark;
double course_grade;
};
//Additional Helper Functions:
void print_degree_prompt(void);
void print_major_prompt(void);
double clamp_double(double n, double lower, double higher);
void print_class(int class_size, struct student class[MAX_CLASS_SIZE]);
int find_student_index(int z_id, int class_size,
struct student class[MAX_CLASS_SIZE]);
void print_help_prompt(void);
void find_and_print_student(int class_size,
struct student class[MAX_CLASS_SIZE]);
// Required Functions:
void print_degree_type(enum degree_type degree_type);
enum degree_type scan_degree(void);
void print_major(enum major major);
enum major scan_major(void);
struct student scan_student_details(void);
void print_student(struct student student);
enum command scan_command(void);
int main(void) {
int class_size;
printf("Enter Class Size: ");
scanf("%d", &class_size);
if (class_size <= 0 || class_size > MAX_CLASS_SIZE) {
printf("Class Size must be between 1 and %d\n", MAX_CLASS_SIZE);
// Exit the program early
return 0;
}
struct student class[MAX_CLASS_SIZE];
int i = 0;
while (i < class_size) {
printf("Student %d: \n", i + 1);
class[i] = scan_student_details();
i++;
}
enum loop_sentinal is_looping = KEEP_LOOPING;
while (is_looping) {
printf("Enter Command Number (0 for Help): ");
enum command command = scan_command();
if (command == HELP) {
print_help_prompt();
} else if (command == PRINT_STUDENT) {
find_and_print_student(class_size, class);
} else if (command == PRINT_CLASS) {
print_class(class_size, class);
} else if (command == QUIT) {
is_looping = STOP_LOOPING;
} else {
printf("Invalid Command\n");
}
}
printf("Exiting Program\n");
return 0;
}
// Given a `enum degree_type`, prints out the corresponding string.
void print_degree_type(enum degree_type degree_type) {
if (degree_type == UGRD) {
printf("Undergraduate\n");
} else if (degree_type == PGRD) {
printf("Postgraduate\n");
} else {
printf("INVALID\n");
}
}
// Prints the prompt which explains to the user how to input a degree_type.
void print_degree_prompt(void) {
printf("Select Degree Type: \n");
enum degree_type degree_type = UGRD;
while (degree_type <= PGRD) {
printf("%d: ", degree_type);
print_degree_type(degree_type);
degree_type++;
}
}
// Scans in a degree as an integer and maps it to the corresponding
// `enum degree_type`
// returns : INVALID_DEGREE, if the scanned integer does not correspond to a
// degree type,
// : else, the corresponding degree_type
enum degree_type scan_degree(void) {
int scanned_degree_type;
scanf("%d", &scanned_degree_type);
enum degree_type degree_type = INVALID_DEGREE;
if (scanned_degree_type == UGRD || scanned_degree_type == PGRD) {
degree_type = scanned_degree_type;
}
return degree_type;
}
// Given a `enum major`, prints out the corresponding string.
void print_major(enum major major) {
if (major == COMPA1) {
printf("Computer Science\n");
} else if (major == COMPD1) {
printf("Database Systems\n");
} else if (major == COMPE1) {
printf("eCommerce Systems\n");
} else if (major == COMPI1) {
printf("Artificial Intelligence\n");
} else if (major == COMPJ1) {
printf("Programming Languages\n");
} else if (major == COMPN1) {
printf("Computer Networks\n");
} else if (major == COMPS1) {
printf("Embedded Systems\n");
} else if (major == COMPY1) {
printf("Security Engineering\n");
} else {
printf("None\n");
}
}
// Prints the prompt which explains to the user how to input a major.
void print_major_prompt(void) {
printf("Select Major: \n");
enum major major = COMPA1;
while (major <= NONE) {
printf("%d: ", major);
print_major(major);
major++;
}
}
// Scans in a COMP/SCI major as an integer and maps it to the corresponding
// `enum major`
// returns : NONE, if the scanned integer does not correspond to a
// MAJOR,
// : else, the corresponding major
enum major scan_major(void) {
int scanned_major;
scanf("%d", &scanned_major);
enum major major = NONE;
if (scanned_major >= COMPA1 && scanned_major < NONE) {
major = scanned_major;
}
return major;
}
// Clamps n in the range lower <= n <= higher
// Parameters
// n : the number to clamp
// lower : the lower bound
// higher: the upper bound
//
// returns : the clamped value.
double clamp_double(double n, double lower, double higher) {
double clamped_n = n;
if (n > higher) {
clamped_n = higher;
} else if (n < lower) {
clamped_n = lower;
}
return clamped_n;
}
// Scans in all the details for a single student, and returns the details as a
// `struct student`.
//
// returns : the new struct student.
struct student scan_student_details(void) {
struct student new_student;
printf("Enter zID: ");
scanf("%d", &new_student.z_id);
print_degree_prompt();
new_student.degree_type = scan_degree();
new_student.major = NONE;
if (new_student.degree_type == UGRD) {
print_major_prompt();
new_student.major = scan_major();
}
printf("Enter Assignments mark (out of %d): ", MAX_ASSIGMENTS_MARK);
double assignments_mark;
scanf("%lf", &assignments_mark);
assignments_mark = clamp_double(assignments_mark, 0, MAX_ASSIGMENTS_MARK);
printf("Enter exam mark (out of %d): ", MAX_EXAM_MARK);
double exam_mark;
scanf("%lf", &exam_mark);
exam_mark = clamp_double(exam_mark, 0, MAX_EXAM_MARK);
new_student.assignments_mark = assignments_mark;
new_student.exam_mark = exam_mark;
new_student.course_grade = exam_mark + assignments_mark;
return new_student;
}
// Given a `struct student`, prints out the formatted details of the student.
void print_student(struct student student) {
printf("z%07d: {\n", student.z_id);
printf("\tDegree Type: ");
print_degree_type(student.degree_type);
if (student.degree_type == UGRD) {
printf("\tMajor: ");
print_major(student.major);
}
printf("\tAssignments Mark: %3.02lf/%d\n", student.assignments_mark,
MAX_ASSIGMENTS_MARK);
printf("\tExam Mark: %3.02lf/%d\n", student.exam_mark, MAX_EXAM_MARK);
printf("\tCourse Grade: %3.02lf/%d\n", student.course_grade,
MAX_ASSIGMENTS_MARK + MAX_EXAM_MARK);
printf("}\n");
}
// Given an array of `struct student`s, prints out the formatted details
// all students in the array.
void print_class(int class_size, struct student class[MAX_CLASS_SIZE]) {
printf("Students: \n");
int i = 0;
while (i < class_size) {
print_student(class[i]);
i++;
}
}
// Given a specific zID, finds and returns the index of the corresponding
// student.
// Parameters
// z_id : the zID of the student to find
// class_size : the number of students in the class
// class : an array of students
//
// returns : NOT_FOUND, if `z_id` does not correspond to a student in the array.
// : the index of the first occurance of a student with zID: `z_id`,
// otherwise.
int find_student_index(int z_id, int class_size,
struct student class[MAX_CLASS_SIZE]) {
int i = 0;
int student_index = NOT_FOUND;
while (i < class_size) {
if (class[i].z_id == z_id) {
student_index = i;
}
i++;
}
return student_index;
}
// Prints the prompt which explains to the user how to input different commands
void print_help_prompt(void) {
printf("Enter a number corresponding to one of the following commands: \n");
printf("0 (Help): Display program instructions\n");
printf("1 (Display Student): Print the details of a specific student\n");
printf("2 (Display Class): Print the details of all students in a class\n");
printf("3 (Quit): Exit the program\n");
}
// Scans in a command as an integer and maps it to the corresponding
// `enum command`
// returns : INVALID_COMMAND, if the scanned integer does not correspond to a
// command,
// : else, the corresponding command
enum command scan_command(void) {
int scanned_command;
scanf("%d", &scanned_command);
enum command command = INVALID_COMMAND;
if (scanned_command >= HELP && scanned_command <= QUIT) {
command = scanned_command;
}
return command;
}
// Scans in a zID and displays the details of the corresponding student in a
// given class.
//
// Parameters
// class_size : the number of students in the class
// class : an array of students
void find_and_print_student(int class_size, struct student class[MAX_CLASS_SIZE]) {
printf("Enter Student zID: ");
int z_id;
scanf("%d", &z_id);
int student_index = find_student_index(z_id, class_size, class);
if (student_index == NOT_FOUND) {
printf("No student with that zID exists\n");
} else {
print_student(class[student_index]);
}
}