Add CT331 Programming Paradigms

This commit is contained in:
2023-12-07 01:33:53 +00:00
parent 38a012c323
commit 262614ce83
207 changed files with 4516 additions and 0 deletions

View File

@ -0,0 +1,15 @@
#include <stdio.h>
int main() {
int my_int;
int* my_int_pointer;
long my_long;
double * my_double_pointer;
char ** my_char_pointer_pointer;
printf("The size of my_int is %lu bytes\n", sizeof(my_int));
printf("The size of my_int_pointer is %lu bytes\n", sizeof(my_int_pointer));
printf("The size of my_long is %lu bytes\n", sizeof(my_long));
printf("The size of my_double_pointer is %lu bytes\n", sizeof(my_double_pointer));
printf("The size of my_char_pointer_pointer is %lu bytes\n", sizeof(my_char_pointer_pointer));
}

View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/question2.iml" filepath="$PROJECT_DIR$/.idea/question2.iml" />
</modules>
</component>
</project>

View File

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<module classpath="CMake" type="CPP_MODULE" version="4" />

View File

@ -0,0 +1,8 @@
#include <stdio.h>
#include "linkedList.h"
#include "tests.h"
int main(int argc, char* argv[]){
runTests();
return 0;
}

View File

@ -0,0 +1,162 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "linkedList.h"
typedef struct listElementStruct{
char* data;
size_t size;
struct listElementStruct* next;
} listElement;
//Creates a new linked list element with given content of size
//Returns a pointer to the element
listElement* createEl(char* data, size_t size){
listElement* e = malloc(sizeof(listElement));
if(e == NULL){
//malloc has had an error
return NULL; //return NULL to indicate an error.
}
char* dataPointer = malloc(sizeof(char)*size);
if(dataPointer == NULL){
//malloc has had an error
free(e); //release the previously allocated memory
return NULL; //return NULL to indicate an error.
}
strcpy(dataPointer, data);
e->data = dataPointer;
e->size = size;
e->next = NULL;
return e;
}
//Prints out each element in the list
void traverse(listElement* start){
listElement* current = start;
while(current != NULL){
printf("%s\n", current->data);
current = current->next;
}
}
//Inserts a new element after the given el
//Returns the pointer to the new element
listElement* insertAfter(listElement* el, char* data, size_t size){
listElement* newEl = createEl(data, size);
listElement* next = el->next;
newEl->next = next;
el->next = newEl;
return newEl;
}
//Delete the element after the given el
void deleteAfter(listElement* after){
listElement* delete = after->next;
listElement* newNext = delete->next;
after->next = newNext;
//need to free the memory because we used malloc
free(delete->data);
free(delete);
}
// returns the number of elements in the list
int length(listElement* list) {
int length = 0;
listElement* current = list;
// traversing the list and counting each element
while(current != NULL){
length++;
current = current->next;
}
return length;
}
// push a new element onto the head of a list and update the list reference using side effects
void push(listElement** list, char* data, size_t size) {
// create the new element
listElement* newElement = createEl(data, size);
// handle malloc errors
if (newElement == NULL) {
fprintf(stderr, "Memory allocation failed.\n");
exit(EXIT_FAILURE);
}
// make the the new element point to the current head of the list
newElement->next = *list;
// make the list reference to point to the new head element
*list = newElement;
}
// pop an element from the head of a list and update the list reference using side effects
// assuming that the desired return value here is the popped element, as is standard for POP operations
listElement* pop(listElement** list) {
// don't bother if list is non existent
if (*list == NULL) { return NULL; }
;
// getting reference to the element to be popped
listElement* poppedElement = *list;
// make the the second element the new head of the list -- this could be NULL, so the list would be NULL also
*list = (*list)->next;
// detach the popped element from the list
poppedElement->next = NULL;
return poppedElement;
}
// enque a new element onto the head of the list and update the list reference using side effects
// essentially the same as push
void enqueue(listElement** list, char* data, size_t size) {
// create the new element
listElement* newElement = createEl(data, size);
// handle malloc errors
if (newElement == NULL) {
fprintf(stderr, "Memory allocation failed.\n");
exit(EXIT_FAILURE);
}
// make the the new element point to the current head of the list
newElement->next = *list;
// make the list reference to point to the new head element
*list = newElement;
}
// dequeue an element from the tail of the list by removing the element from the list via side effects, and returning the removed item
// assuming that we want to return the dequeued element rather than the list itself, as enqueue returns nothing and uses side effects, so dequeue should also use side effects
listElement* dequeue(listElement* list) {
// there are three cases that we must consider: a list with 0 elements, a list with 1 element, & a list with >=2 elements
// don't bother if list is non existent
if (list == NULL) { return NULL; }
// if there is only one element in the list, i.e. the head element is also the tail element, just returning this element
// this means that the listElement pointer that was passed to this function won't be updated
// ideally, we would set it to NULL but we can't do that since `list` is a pointer that has been passed by value, so we can't update the pointer itself. we would need a pointer to a pointer to have been passed
if (list->next == NULL) {
return list;
}
// traversing the list to find the second-to-last element
listElement* current = list;
while (current->next->next != NULL) {
current = current->next;
}
// get reference to the element to be dequeued
listElement* dequeuedElement = current->next;
// make the penultimate element the tail by removing reference to the old tail
current->next = NULL;
return list;
}

View File

@ -0,0 +1,36 @@
#ifndef CT331_ASSIGNMENT_LINKED_LIST
#define CT331_ASSIGNMENT_LINKED_LIST
typedef struct listElementStruct listElement;
//Creates a new linked list element with given content of size
//Returns a pointer to the element
listElement* createEl(char* data, size_t size);
//Prints out each element in the list
void traverse(listElement* start);
//Inserts a new element after the given el
//Returns the pointer to the new element
listElement* insertAfter(listElement* after, char* data, size_t size);
//Delete the element after the given el
void deleteAfter(listElement* after);
// returns the number of elements in the list
int length(listElement* list);
// push a new element onto the head of a list and update the list reference using side effects
void push(listElement** list, char* data, size_t size);
// pop an element from the head of a list and update the list reference using side effects
listElement* pop(listElement** list);
// enque a new element onto the head of the list and update the list reference using side effects
void enqueue(listElement** list, char* data, size_t size);
// dequeue an element from the tail of the list
listElement* dequeue(listElement* list);
#endif

View File

@ -0,0 +1,57 @@
#include <stdio.h>
#include "tests.h"
#include "linkedList.h"
void runTests(){
printf("Tests running...\n");
listElement* l = createEl("Test String (1).", sizeof("Test String (1)."));
//printf("%s\n%p\n", l->data, l->next);
//Test create and traverse
traverse(l);
printf("\n");
//Test insert after
printf("Testing insertAfter()\n");
listElement* l2 = insertAfter(l, "another string (2)", sizeof("another test string(2)"));
insertAfter(l2, "a final string (3)", sizeof("a final string(3)"));
traverse(l);
printf("\n");
// test length function
printf("Testing length()\n");
int l_length = length(l);
printf("The length of l is %d\n\n", l_length);
// test push
printf("Testing push()\n");
push(&l, "yet another test string", sizeof("yet another test string"));
traverse(l);
printf("\n\n");
// test pop
printf("Testing pop()\n");
listElement* popped = pop(&l);
traverse(l);
printf("\n\n");
// Test delete after
printf("Testing deleteAfter()\n");
deleteAfter(l);
traverse(l);
printf("\n");
// test enqueue
printf("Testing enqueue()\n");
enqueue(&l, "enqueued test string", sizeof("enqueued test string"));
traverse(l);
printf("\n");
// test dequeue
printf("Testing dequeue()\n");
dequeue(l);
traverse(l);
printf("\n");
printf("\nTests complete.\n");
}

View File

@ -0,0 +1,6 @@
#ifndef CT331_ASSIGNMENT_TESTS
#define CT331_ASSIGNMENT_TESTS
void runTests();
#endif

View File

@ -0,0 +1,8 @@
#include <stdio.h>
#include "genericLinkedList.h"
#include "tests.h"
int main(int argc, char* argv[]){
runTests();
return 0;
}

View File

@ -0,0 +1,167 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "genericLinkedList.h"
typedef struct listElementStruct{
void* data;
void (*printFunction)(void*);
size_t size;
struct listElementStruct* next;
} listElement;
//Creates a new linked list element with given content of size
//Returns a pointer to the element
listElement* createEl(void* data, size_t size, void (*printFunction)(void*)) {
listElement* e = malloc(sizeof(listElement));
if(e == NULL){
//malloc has had an error
return NULL; //return NULL to indicate an error.
}
void* dataPointer = malloc(sizeof(void)*size);
if(dataPointer == NULL){
//malloc has had an error
free(e); //release the previously allocated memory
return NULL; //return NULL to indicate an error.
}
strcpy(dataPointer, data);
e->data = dataPointer;
e->printFunction = printFunction;
e->size = size;
e->next = NULL;
return e;
}
//Prints out each element in the list
void traverse(listElement* start){
listElement* current = start;
while(current != NULL){
current->printFunction(current->data);
// printf("%s\n", current->data);
current = current->next;
}
}
//Inserts a new element after the given el
//Returns the pointer to the new element
listElement* insertAfter(listElement* el, void* data, size_t size, void (*printFunction)(void*)){
listElement* newEl = createEl(data, size, printFunction);
listElement* next = el->next;
newEl->next = next;
el->next = newEl;
return newEl;
}
//Delete the element after the given el
void deleteAfter(listElement* after){
listElement* delete = after->next;
listElement* newNext = delete->next;
after->next = newNext;
//need to free the memory because we used malloc
free(delete->data);
free(delete);
}
// returns the number of elements in the list
int length(listElement* list) {
int length = 0;
listElement* current = list;
// traversing the list and counting each element
while(current != NULL){
length++;
current = current->next;
}
return length;
}
// push a new element onto the head of a list and update the list reference using side effects
void push(listElement** list, void* data, size_t size, void (*printFunction)(void*)) {
// create the new element
listElement* newElement = createEl(data, size, printFunction);
// handle malloc errors
if (newElement == NULL) {
fprintf(stderr, "Memory allocation failed.\n");
exit(EXIT_FAILURE);
}
// make the the new element point to the current head of the list
newElement->next = *list;
// make the list reference to point to the new head element
*list = newElement;
}
// pop an element from the head of a list and update the list reference using side effects
// assuming that the desired return value here is the popped element, as is standard for POP operations
listElement* pop(listElement** list) {
// don't bother if list is non existent
if (*list == NULL) { return NULL; }
;
// getting reference to the element to be popped
listElement* poppedElement = *list;
// make the the second element the new head of the list -- this could be NULL, so the list would be NULL also
*list = (*list)->next;
// detach the popped element from the list
poppedElement->next = NULL;
return poppedElement;
}
// enque a new element onto the head of the list and update the list reference using side effects
// essentially the same as push
void enqueue(listElement** list, void* data, size_t size, void (*printFunction)(void*)) {
// create the new element
listElement* newElement = createEl(data, size, printFunction);
// handle malloc errors
if (newElement == NULL) {
fprintf(stderr, "Memory allocation failed.\n");
exit(EXIT_FAILURE);
}
// make the the new element point to the current head of the list
newElement->next = *list;
// make the list reference to point to the new head element
*list = newElement;
}
// dequeue an element from the tail of the list by removing the element from the list via side effects, and returning the removed item
// assuming that we want to return the dequeued element rather than the list itself, as enqueue returns nothing and uses side effects, so dequeue should also use side effects
listElement* dequeue(listElement* list) {
// there are three cases that we must consider: a list with 0 elements, a list with 1 element, & a list with >=2 elements
// don't bother if list is non existent
if (list == NULL) { return NULL; }
// if there is only one element in the list, i.e. the head element is also the tail element, just returning this element
// this means that the listElement pointer that was passed to this function won't be updated
// ideally, we would set it to NULL but we can't do that since `list` is a pointer that has been passed by value, so we can't update the pointer itself. we would need a pointer to a pointer to have been passed
if (list->next == NULL) {
return list;
}
// traversing the list to find the second-to-last element
listElement* current = list;
while (current->next->next != NULL) {
current = current->next;
}
// get reference to the element to be dequeued
listElement* dequeuedElement = current->next;
// make the penultimate element the tail by removing reference to the old tail
current->next = NULL;
return list;
}

View File

@ -0,0 +1,35 @@
#ifndef CT331_ASSIGNMENT_LINKED_LIST
#define CT331_ASSIGNMENT_LINKED_LIST
typedef struct listElementStruct listElement;
//Creates a new linked list element with given content of size
//Returns a pointer to the element
listElement* createEl(void* data, size_t size, void (*printFunction)(void*));
//Prints out each element in the list
void traverse(listElement* start);
//Inserts a new element after the given el
//Returns the pointer to the new element
listElement* insertAfter(listElement* after, void* data, size_t size, void (*printFunction)(void*));
//Delete the element after the given el
void deleteAfter(listElement* after);
// returns the number of elements in the list
int length(listElement* list);
// push a new element onto the head of a list and update the list reference using side effects
void push(listElement** list, void* data, size_t size, void (*printFunction)(void*));
// pop an element from the head of a list and update the list reference using side effects
listElement* pop(listElement** list);
// enque a new element onto the head of the list and update the list reference using side effects
void enqueue(listElement** list, void* data, size_t size, void (*printFunction)(void*));
// dequeue an element from the tail of the list
listElement* dequeue(listElement* list);
#endif

View File

@ -0,0 +1,79 @@
#include <stdio.h>
#include "tests.h"
#include "genericLinkedList.h"
// functions to print out different data types
// a more professional design might be to put these in the genericLinkedList header file but i only need these for testing purposes
void printChar(void* data) {
printf("%c\n", *(char*) data);
}
void printStr(void* data) {
printf("%s\n", (char*) data);
}
void printInt(void* data) {
printf("%d\n", *(int*) data);
}
void runTests(){
printf("Tests running...\n");
listElement* l = createEl("Test String (1).", sizeof("Test String (1)."), printStr);
//printf("%s\n%p\n", l->data, l->next);
//Test create and traverse
traverse(l);
printf("\n");
//Test insert after
printf("Testing insertAfter()\n");
listElement* l2 = insertAfter(l, "another string (2)", sizeof("another string (2)"), printStr);
insertAfter(l2, "a final string (3)", sizeof("a final string (3)"), printStr);
traverse(l);
printf("\n");
// test length function
printf("Testing length()\n");
int l_length = length(l);
printf("The length of l is %d\n\n", l_length);
// test push
printf("Testing push()\n");
push(&l, "yet another test string", sizeof("yet another test string"), printStr);
traverse(l);
printf("\n\n");
// test pop
printf("Testing pop()\n");
listElement* popped = pop(&l);
traverse(l);
printf("\n\n");
// Test delete after
printf("Testing deleteAfter()\n");
deleteAfter(l);
traverse(l);
printf("\n");
// test enqueue
printf("Testing enqueue()\n");
enqueue(&l, "enqueued test string", sizeof("enqueued test string"), printStr);
traverse(l);
printf("\n");
// test dequeue
printf("Testing dequeue()\n");
dequeue(l);
traverse(l);
printf("\n");
printf("Testing pushing different data types\n");
int myint = 42;
push(&l, &myint, sizeof(myint), printInt);
char mychar = 'c';
push(&l, &mychar, sizeof(mychar), printChar);
traverse(l);
printf("\n\n");
printf("\nTests complete.\n");
}

View File

@ -0,0 +1,6 @@
#ifndef CT331_ASSIGNMENT_TESTS
#define CT331_ASSIGNMENT_TESTS
void runTests();
#endif