diff --git a/#vendorInfo# b/#vendorInfo# new file mode 100755 index 0000000..6b3e969 Binary files /dev/null and b/#vendorInfo# differ diff --git a/#vendorInfo.c# b/#vendorInfo.c# new file mode 100644 index 0000000..db1ddc9 --- /dev/null +++ b/#vendorInfo.c# @@ -0,0 +1,437 @@ +/* + * vendorInfo.c + * + * SEN-102 Intro to Programming - Pre-Assessment + * Program that simulates a market containing vendors. + * + * Created by Win (Thanawin Pattanaphol), 28th August 2024 + */ + +#include +#include +#include +#include + +#define MAX_VENDORS 20 +#define MAX_FILENAME_LENGTH 4096 + +/* STRUCTURES */ +typedef struct vendor +{ + char vendor_name[20]; + char merchandise[15]; + int inventory_count; + int item_price_baht; + int revenue; + int duplicate; +} vendor; + +// Return type for search function +typedef struct search_r +{ + int status; + int item_id; +} search_r; + +// Return type for purchase function +typedef struct purchase_r +{ + int status; + char vendor_name[20]; + int price_owe_baht; +} purchase_r; + +vendor vendors[MAX_VENDORS]; + +/* FUNCTION DECLARATION */ +int getstr(char str[], size_t n); +char *strnlower(char *s, size_t n); + +search_r search +( + char query[], + vendor vendors[MAX_VENDORS], + int total_vendors +); + +purchase_r purchase +( + int item_id, + int amount, + vendor vendors[MAX_VENDORS] +); + +int check_vendors(vendor vendors[MAX_VENDORS], int total_vendors); + +int main() +{ + char file_name[MAX_FILENAME_LENGTH]; + printf("Enter name of input file: "); + getstr(file_name, MAX_FILENAME_LENGTH); + + FILE *fp; + if ((fp = fopen(file_name, "r")) == NULL) + { + printf("%s cannot be opened.\n", file_name); + exit(EXIT_FAILURE); + } + + // Calculate the file size + fseek(fp, 0, SEEK_END); + unsigned long file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + // Dynamically allocate buffer for file content + char *file_buffer = (char *) malloc(file_size); + int index = 0; + + // Reading the file with fgets and formatting them using strtok + while ((fgets(file_buffer, 50, fp) != NULL) && (index <= MAX_VENDORS - 1)) + { + char *token = strtok(file_buffer, " "); + strncpy(vendors[index].vendor_name, token, strlen(token) + 1); + + token = strtok(NULL, " "); + strncpy(vendors[index].merchandise, token, strlen(token) + 1); + + token = strtok(NULL, " "); + vendors[index].inventory_count = atoi(token); + + token = strtok(NULL, " "); + vendors[index].item_price_baht = atoi(token); + + index++; + } + + if (ferror(fp)) + { + printf(""); + } + + int total_vendors = index; + printf("\n>>> Read %d vendors from file %s\n", total_vendors, file_name); + + // Print out each vendor's info - excluding duplicates. + for (int i = 0; i <= (total_vendors - 1); i++) + { + /* + This is similar to a linear search algorithm + i = the current item + j = the item next to i + + i is being compared to j: + - if i == j then mark both i and j as duplicates + - if not, move on to the next two items + */ + for (int j = i + 1; j < total_vendors; j++) + { + if ((strcmp(vendors[i].merchandise, vendors[j].merchandise)) == 0) + { + vendors[j].duplicate = 1; + } + + if ((strcmp(vendors[i].vendor_name, vendors[j].vendor_name)) == 0) + { + vendors[j].duplicate = 1; + } + } + + if (vendors[i].duplicate == 0) + { + char vendor_info[200]; + sprintf(vendor_info, "%s sells %s for %d each", + vendors[i].vendor_name, + vendors[i].merchandise, + vendors[i].item_price_baht + ); + + char vendor_stock[50]; + sprintf(vendor_stock, "Inventory %d items", + vendors[i].inventory_count + ); + + printf("%-50s %s\n", vendor_info, vendor_stock); + } + else + { + printf("\e[31m%s\e[m\n", "Duplicate record detected!"); + } + } + + printf("\n"); + + while (1) + { + if(check_vendors(vendors, total_vendors) == 0) + { + break; + }; + + char user_query[100]; + printf("What do you want to buy? (DONE to end) "); + getstr(user_query, 100); + + if ( + (strcmp(user_query, "DONE") == 0) || + (strcmp(user_query, "done") == 0) + ) + { + break; + } + + if (strcmp(user_query, "") == 0) + { + printf("Please enter an item name\n"); + } + else + { + // convert string to lowercase - each character one by one + int user_query_length = strlen(user_query); + strnlower(user_query, user_query_length); + + struct search_r item = search(user_query, vendors, total_vendors); + if(item.status == 0) + { + char input[10]; + + printf("How many do you want to buy? "); + getstr(input, 10); + + // If a character of a string was sent, the return value would always be 0 + // If a negative number was sent, the return value will always be negative. + + if(atoi(input) > 0) + { + int item_amount = atoi(input); + purchase_r response = purchase(item.item_id, item_amount, vendors); + + if (response.status == 0) + { + printf("You owe %s a total of %d baht.\n", + response.vendor_name, + response.price_owe_baht + ); + } + else + { + printf("\e[31m%s -- %s %s\e[m\n", + "Sorry", + response.vendor_name, + "does not have enough items available" + ); + } + } + else + { + printf("\e[31m%s\e[m\n", + "You must enter a positive whole number for the number of items" + ); + } + + } + else if (item.status == 2) + { + printf("\e[31m%s\e[m\n", + "This item has duplicate records, please choose another item" + ); + } + else + { + printf("\e[31m%s %s\e[m\n", + "No vendor in this market sells", + user_query + ); + } + } + } + + printf("\n>>> End of day details\n"); + + // Print out remaining inventory + for (int i = 0; i <= (total_vendors - 1); i++) + { + if (vendors[i].duplicate == 0) + { + char vendor_info[200]; + sprintf(vendor_info, "%s made %d baht today", + vendors[i].vendor_name, + vendors[i].revenue + ); + + char vendor_stock[50]; + sprintf(vendor_stock, "Remaining inventory %d items", + vendors[i].inventory_count + ); + + printf("%-50s %s\n", vendor_info, vendor_stock); + } + } + + fclose(fp); + free(file_buffer); + return 0; +}; + +/* + getstr: Custom read input function + + Parameters: + - str = string itself + - n = max amount of characters that the function is able to read into buffer + + Reads one character at a time into buffer and adds a null terminator when finish reading +*/ +int getstr(char str[], size_t n) +{ + int ch, i = 0; + + while ((ch = getchar()) != '\n') + { + if (i < (int)n) + { + str[i++] = ch; + } + } + + str[i] = '\0'; + return i; +}; + +/* + strnlower: Convert string to lowercase + + Parameters: + - s: String + - n: Length of string + + Return values: + - (char *): Lowercased version of the string. +*/ +char *strnlower(char *s, size_t n) +{ + for (int i = 0; i < (int) n; i++) + { + s[i] = tolower(s[i]); + }; +} + +/* + Search function + + Parameters: + - (string) query: search query + - (vendor) vendors: the vendor table + - (int) total_vendors: the amount of vendors + + Return values: + (search_r) response: + - status: 0 (Found item) + - status: 1 (No results) + - status: 2 (Found duplicate item) +*/ + +search_r search(char query[], vendor vendors[MAX_VENDORS], int total_vendors) +{ + int i; + for (i = 0; i < total_vendors; i++) + { + // First, check if duplicate + if (strcmp(query, vendors[i].merchandise) == 0) + { + if (vendors[i].duplicate == 0) + { + search_r response; + response.status = 0; + response.item_id = i; + + return (response); + break; + } + else + { + search_r response; + response.status = 2; + return (response); + } + } + }; + + if (i == total_vendors) + { + search_r response; + response.status = 1; + response.item_id = 0; + return (response); + } +}; + +/* + purchase: Purchase function + + Parameters: + - item_id: The item id that the user is purchasing + - amount: How many items that the user is purchasing + - vendors: vendor table + + Return values: + (purchase_r) response: + - status: 0 (Purchase successful) + - status: 1 (Vendor does not have enough items) +*/ + +purchase_r purchase(int item_id, int amount, vendor vendors[MAX_VENDORS]) +{ + if(amount <= vendors[item_id].inventory_count) + { + // Decrease vendor inventory + vendors[item_id].inventory_count = vendors[item_id].inventory_count - amount; + + purchase_r response; + + response.status = 0; + strcpy(response.vendor_name, vendors[item_id].vendor_name); + response.price_owe_baht = vendors[item_id].item_price_baht * amount; + + vendors[item_id].revenue = vendors[item_id].item_price_baht * amount; + + return response; + } + else + { + purchase_r response; + response.status = 1; + strcpy(response.vendor_name, vendors[item_id].vendor_name); + + return response; + } +}; + +/* + check_vendors: Custom function to check if all vendors are empty. + + Parameters: + - vendors[MAX_VENDORS]: (vendor) All of the vendors. + - total_vendors: (integer) Total vendors in market. + + Return values: + - (int) 0: All vendors are empty. + - (int) 1: There are still items left. +*/ + +int check_vendors(vendor vendors[MAX_VENDORS], int total_vendors) +{ + int i; + for (i = 0; i < total_vendors; i++) + { + // Condition: Vendors that are not empty (Check if not marked as duplicates) + if (vendors[i].inventory_count != 0 && vendors[i].duplicate == 0) + { + return 1; + } + } + + if (i == total_vendors) + { + return 0; + } +}; diff --git a/vendor2.data b/vendor2.data index e16e365..01a02f3 100644 --- a/vendor2.data +++ b/vendor2.data @@ -8,6 +8,7 @@ Oat watches 9 120 Lila jackets 7 380 Mary toys 17 39 Kitty dishes 11 67 +Win books 30 165 Pat comics 22 18 Jay shoes 22 300 Mark dvds 10 200 diff --git a/vendorInfo b/vendorInfo index 2131c0b..520f6d0 100755 Binary files a/vendorInfo and b/vendorInfo differ diff --git a/vendorInfo.c b/vendorInfo.c index 27fa157..4388dba 100644 --- a/vendorInfo.c +++ b/vendorInfo.c @@ -72,7 +72,7 @@ int main() FILE *fp; if ((fp = fopen(file_name, "r")) == NULL) { - printf("%s cannot be opened.\n", file_name); + perror("Error opening file"); exit(EXIT_FAILURE); } @@ -103,6 +103,12 @@ int main() index++; } + // Error handling + if (ferror(fp)) + { + printf("An error occured while reading the file.\n"); + } + int total_vendors = index; printf("\n>>> Read %d vendors from file %s\n", total_vendors, file_name); @@ -122,13 +128,11 @@ int main() { if ((strcmp(vendors[i].merchandise, vendors[j].merchandise)) == 0) { - vendors[i].duplicate = 1; vendors[j].duplicate = 1; } if ((strcmp(vendors[i].vendor_name, vendors[j].vendor_name)) == 0) { - vendors[i].duplicate = 1; vendors[j].duplicate = 1; } } diff --git a/vendorsmall.data b/vendorsmall.data index 710411e..199d1cc 100644 --- a/vendorsmall.data +++ b/vendorsmall.data @@ -2,3 +2,4 @@ Win phone 1 50 Peter books 1 70 Amy teeshirts 5 100 Deez computers 5 80 +kjflkfdl lkdfjlkslkfslklk sdfdsjf dslkfjdslfkjs