diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..14c0050 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,33 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "(gdb) Launch", + "type": "cppdbg", + "request": "launch", + "program": "${workspaceFolder}/customer_list", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ] + } + + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..08d9005 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: gcc build active file", + "command": "/usr/bin/gcc", + "args": [ + "-fdiagnostics-color=always", + "-g", + "${file}", + "-o", + "${fileDirname}/${fileBasenameNoExtension}" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/customer_list.c b/customer_list.c index a58f2b3..643d0d9 100644 --- a/customer_list.c +++ b/customer_list.c @@ -1,6 +1,6 @@ /*---------------------------------------------------------- * HTBLA-Leonding, 2. JG - * */ your name /* + * Marc Tismonar * --------------------------------------------------------- * Description: * Implementation of customer_list.h. @@ -11,4 +11,242 @@ #include #include #include +#include "customer_list.h" +//redefine NULL, bc Mr. Schraml said that its not safe +#ifdef NULL +#undef NULL +#define NULL 0 +#endif + +struct CustomerListEntryData { + int id; + const char* name; + int revenue; +}; + +struct CustomerListData { + int length; + CustomerListEntry customers[MAX_LIST_ENTRIES]; +}; + +static CustomerList staticCl; + + +CustomerList init_customer_list() { + staticCl = (CustomerList)calloc(1, sizeof(struct CustomerListData)); //using calloc :) it initializes the memory with 0 + return staticCl; +} + +int get_length(const CustomerList cl) { + if (cl == 0) { + return -1; + } + return cl->length; +} + +CustomerListEntry create_customer(int id, const char* customer_name, int revenue) { + if (id < 0 || customer_name == 0 || revenue < 0) { + return 0; + } + + CustomerListEntry new_customer = (CustomerListEntry)calloc(1, sizeof(struct CustomerListEntryData)); + if (new_customer == 0) { + return 0; + } + new_customer->id = id; + new_customer->name = customer_name; + new_customer->revenue = revenue; + return new_customer; +} + +bool add_customer(CustomerList cl, int id, const char* customer_name, int revenue) { + if (cl == 0 || id < 0 || customer_name == 0 || revenue < 0) { + return false; + } + + //check if the customer list is full + if (cl->length >= MAX_LIST_ENTRIES) { + return false; + } + + //check if its already in the list + for (int i = 0; i < cl->length; i++) { + if (cl->customers[i]->id == id) { + return false; + } + } + + CustomerListEntry new_customer = create_customer(id, customer_name, revenue); + if (new_customer == 0) { + return false; + } + cl->customers[cl->length] = new_customer; + cl->length++; + return true; +} + +bool add_customers(CustomerList cl, CustomerListEntry e[], int n) { + if (cl == 0 || e == 0 || n < 0) { + return false; + } + + //check if customer list is full + if (cl->length + n > MAX_LIST_ENTRIES) { + return false; + } + + for (int i = 0; i < n; i++) { + // null check + if (e[i] == 0) { + return false; + } + + //duplication check + for (int j = 0; j < cl->length; j++) { + if (cl->customers[j]->id == e[i]->id) { + return false; + } + } + cl->customers[cl->length] = e[i]; + cl->length++; + } + return true; +} + +CustomerListEntry get_customer_with_index(const CustomerList cl, int index) { + if (cl == 0 || index < 0 || index >= cl->length) { + return 0; + } + return cl->customers[index]; +} + +CustomerListEntry get_customer_with_id(const CustomerList cl, int id) { + if (cl == 0 || id < 0) { + return 0; + } + + for (int i = 0; i < cl->length; i++) { + if (cl->customers[i]->id == id) { + return cl->customers[i]; + } + } + return 0; +} + +int get_customers_with_revenue(const CustomerList cl, int lower_bound, int upper_bound, CustomerListEntry result_list[], int result_len) { + if (cl == 0 || lower_bound < 0 || upper_bound < 0 || lower_bound > upper_bound || result_list == 0 || result_len < 0) { + return 0; + } + int result_count = 0; + + //go through customer list & check if revenue is in bounds + for (int i = 0; i < cl->length; i++) { + if (cl->customers[i]->revenue >= lower_bound && cl->customers[i]->revenue <= upper_bound) { + if (result_count < result_len) { + result_list[result_count] = cl->customers[i]; + } + result_count++; + } + } + return result_count; +} + +CustomerListEntry get_customer_with_highest_revenue(const CustomerList cl) { + if (cl == 0) { + return 0; + } + CustomerListEntry highest_revenue_customer = cl->customers[0]; + + //go through customer list & return with highest revenue + for (int i = 1; i < cl->length; i++) { + if (cl->customers[i]->revenue > highest_revenue_customer->revenue) { + highest_revenue_customer = cl->customers[i]; + } + } + return highest_revenue_customer; +} + +CustomerListEntry get_customer_with_lowest_revenue(const CustomerList cl) { + if (cl == 0) { + return 0; + } + CustomerListEntry lowest_revenue_customer = cl->customers[0]; + + //go through customer list & return with lowest revenue + for (int i = 1; i < cl->length; i++) { + if (cl->customers[i]->revenue < lowest_revenue_customer->revenue) { + lowest_revenue_customer = cl->customers[i]; + } + } + return lowest_revenue_customer; +} + +int get_top_n_customers_revenue(const CustomerList cl, int n, CustomerListEntry result_list[]) { + if (cl == 0 || n <= 0 || result_list == 0) { + return 0; + } + + // make a copy of customer list + CustomerListEntry temp_list[MAX_LIST_ENTRIES]; + for (int i = 0; i < cl->length; i++) { + temp_list[i] = cl->customers[i]; + } + + // sort the copy of customer list descending + for (int i = 0; i < cl->length - 1; i++) { + for (int j = i + 1; j < cl->length; j++) { + if (temp_list[i]->revenue < temp_list[j]->revenue) { + CustomerListEntry temp = temp_list[i]; + temp_list[i] = temp_list[j]; + temp_list[j] = temp; + } + } + } + + // copy the n top customers to result_list + int result_count = n < cl->length ? n : cl->length; + for (int i = 0; i < result_count; i++) { + result_list[i] = temp_list[i]; + } + + return result_count; +} + +int get_bottom_n_customers_revenue(const CustomerList cl, int n, CustomerListEntry result_list[]) { + if (cl == 0 || n <= 0 || result_list == 0) { + return 0; + } + + // make a copy of customer list + CustomerListEntry temp_list[MAX_LIST_ENTRIES]; + for (int i = 0; i < cl->length; i++) { + temp_list[i] = cl->customers[i]; + } + + // sort the copy of customer list ascending + for (int i = 0; i < cl->length - 1; i++) { + for (int j = i + 1; j < cl->length; j++) { + if (temp_list[i]->revenue > temp_list[j]->revenue) { + CustomerListEntry temp = temp_list[i]; + temp_list[i] = temp_list[j]; + temp_list[j] = temp; + } + } + } + + // copy the n bottom customers to result_list + int result_count = n < cl->length ? n : cl->length; + for (int i = 0; i < result_count; i++) { + result_list[i] = temp_list[i]; + } + + return result_count; +} + +int get_customer_id(const CustomerListEntry customer) { + if (customer == 0) { + return -1; + } + return customer->id; +} \ No newline at end of file diff --git a/customer_list.h b/customer_list.h index 7fe865b..19eddc1 100644 --- a/customer_list.h +++ b/customer_list.h @@ -1,12 +1,13 @@ /*---------------------------------------------------------- * HTBLA-Leonding, 2. JG - * */ your name /* + * Marc Tismonar * --------------------------------------------------------- * Defines an abstract data type for managing a list of customers. * ---------------------------------------------------------- */ -// TODO Don't miss the include guards! +#ifndef __CUSTOMER_LIST_H +#define __CUSTOMER_LIST_H #include @@ -15,14 +16,13 @@ * number of list entries. */ -// TODO: Define a symbolic constant named 'MAX_LIST_ENTRIES' for 13 customers +#define MAX_LIST_ENTRIES 13 /** * A CustomerListEntry consists of a unique customer ID, a name, * and the revenue (in €1000) associated with this customer. */ - -// TODO Declare the 'public' data type of the list entry +typedef struct CustomerListEntryData* CustomerListEntry; /** * The CustomerList stores the number of currently saved customer list @@ -30,20 +30,19 @@ * @remark Memory for the customer list entries must be provided by the caller. * The `customers` array only manages references to customer list entries. */ - -// TODO Declare the 'public' data type of the list entry +typedef struct CustomerListData* CustomerList; /** * Provides the initialized empty instance of the customer list. * @return The customer list instance. */ - init_customer_list(); +CustomerList init_customer_list(); /** * @param cl The customer list data. * @return The number of entries in `cl` or a value less than zero if the list is invalid. */ - get_length(); +int get_length(const CustomerList cl); /** * Creates an entry for a single customer. @@ -52,7 +51,7 @@ * @param revenue The revenue generated by that customer, in units of € 1000,-- (k€). * @return The entry if it could be created, else a null-entry (0). */ - create_customer(); +CustomerListEntry create_customer(int id, const char* customer_name, int revenue); /** * Adds an entry to the customer list. If the list is already full OR a customer @@ -65,7 +64,7 @@ * @return `true` if the addition was successful, `false` otherwise. * @see add_customers */ - add_customer(); +bool add_customer(CustomerList cl, int id, const char* customer_name, int revenue); /** * Adds `n` entries to the customer list. If the customer list cannot accommodate @@ -81,7 +80,7 @@ * included in the list. * @see add_customer */ - add_customers(); +bool add_customers(CustomerList cl, CustomerListEntry e[], int n); /** * Provides the customer with a specific index within the list. @@ -89,7 +88,7 @@ * @param index The index of the requested customer. * @return The entry of the customer with the given index or null. */ - get_customer_with_index(); +CustomerListEntry get_customer_with_index(const CustomerList cl, int index); /** * Searches for a customer with a specific ID. @@ -97,7 +96,7 @@ * @param id The unique customer ID to search for. * @return The entry of the customer with the given ID or null. */ - get_customer_with_id(); +CustomerListEntry get_customer_with_id(const CustomerList cl, int id); /** * Searches for customers within specific revenue bounds and returns them in the @@ -109,7 +108,7 @@ * @param result_len The maximum number of entries that can be stored in the result list. * @return The number of entries found. */ - get_customers_with_revenue(); +int get_customers_with_revenue(const CustomerList cl, int lower_bound, int upper_bound, CustomerListEntry result_list[], int result_len); /** * Finds the customer with the highest revenue. If multiple customers have the @@ -117,7 +116,7 @@ * @param cl The customer list data. * @return The customer with the highest revenue. */ - get_customer_with_highest_revenue(); +CustomerListEntry get_customer_with_highest_revenue(const CustomerList cl); /** * Finds the customer with the lowest revenue. If multiple customers have the @@ -125,7 +124,7 @@ * @param cl The customer list data. * @return The customer with the lowest revenue. */ - get_customer_with_lowest_revenue(); +CustomerListEntry get_customer_with_lowest_revenue(const CustomerList cl); /** * Finds the `n` customers with the highest revenue. If multiple customers satisfy @@ -140,7 +139,7 @@ * @warning It is not verified whether `result_list` has sufficient size. If the size * of `result_list` is smaller than `n`, the function may crash due to memory issues. */ - get_top_n_customers_revenue(); +int get_top_n_customers_revenue(const CustomerList cl, int n, CustomerListEntry result_list[]); /** * Finds the `n` customers with the lowest revenue. If multiple customers satisfy @@ -155,7 +154,7 @@ * @warning It is not verified whether `result_list` has sufficient size. If the size * of `result_list` is smaller than `n`, the function may crash due to memory issues. */ - get_bottom_n_customers_revenue(); +int get_bottom_n_customers_revenue(const CustomerList cl, int n, CustomerListEntry result_list[]); /** * @brief Provides the ID of the given customer. @@ -163,4 +162,6 @@ * @return The ID of this customer or a value less than 0, * if the given customer is invalid. */ - get_customer_id(); +int get_customer_id(const CustomerListEntry customer); + +#endif diff --git a/makefile b/makefile index 67ecc6a..3361a03 100644 --- a/makefile +++ b/makefile @@ -1,8 +1,8 @@ CC = g++ CCLINK = g++ LIBS = -CCOPTIONS = -Wall -pedantic -g -LDOPTIONS = +CCOPTIONS = -Wall -pedantic -g -O0 +LDOPTIONS = -g -O0 HDRS = customer_list.h test_customer_list.h TEST = customer_list @@ -68,5 +68,5 @@ assignmentfolder: rm ../assignment/*.assignment make cleanall -%.o: %.cpp $(HDRS) +%.o: %.c $(HDRS) $(CC) $(CCOPTIONS) -c $<