/* * vendorInfo.c * * Program that * * * Created by Win (Thanawin Pattanaphol), 28th August 2024 */ #include #include #include #include #define MAX_VENDORS 20 #define MAX_FILENAME_LENGTH 4096 /* STRUCTURES */ struct vendor { char vendor_name[20]; char merchandise[15]; int inventory_count; int item_price_baht; int revenue; int duplicate; } vendors[MAX_VENDORS]; struct search_r { int status; int item_id; }; struct purchase_r { int status; char vendor_name[20]; int price_owe_baht; }; /* FUNCTION DECLARATION */ void reset_output(); int read_input(char str[], size_t n); char *strnlower(char *s, size_t n); struct search_r search ( char query[], struct vendor vendors[MAX_VENDORS], int total_vendors ); struct purchase_r purchase ( int item_id, int amount, struct vendor vendors[MAX_VENDORS] ); int check_vendors(struct vendor vendors[MAX_VENDORS], int total_vendors); int main() { char file_name[MAX_FILENAME_LENGTH]; printf("Enter name of input file: "); read_input(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 file size fseek(fp, 0, SEEK_END); unsigned long file_size = ftell(fp); fseek(fp, 0, SEEK_SET); // read file to buffer char *file_buffer = (char *) malloc(file_size); int index = 0; 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++; } int total_vendors = index; printf("\n>>> Read %d vendors from file %s\n", total_vendors, file_name); // print out each vendor's info for (int i = 0; i <= (total_vendors - 1); i++) { for (int j = i + 1; j < total_vendors; j++) { 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; } } 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("\033[0;31mDuplicate record detected!\n"); reset_output(); } } printf("\n"); while (1) { // CHECK IF ALL MERCHANDISE ARE EMPTY if(check_vendors(vendors, total_vendors) == 0) { break; }; char user_query[100]; printf("What do you want to buy? (DONE to end) "); read_input(user_query, 100); if (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? "); read_input(input, 10); if(atoi(input) > 0) { int item_amount = atoi(input); struct 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("\033[0;31mSorry -- %s does not have enough items available\n", response.vendor_name ); reset_output(); } } else { printf("\033[0;31mYou must enter a positive whole number for the number of items\n"); reset_output(); } } else if (item.status == 2) { printf("\033[0;31mThis item has duplicate records, please choose another item\n"); reset_output(); } else { printf("\033[0;31mNo vendor in this market sells %s\n", user_query); reset_output(); } } } 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; }; /* Output color reset */ void reset_output() { printf("\033[0m"); }; /* read_input: Custom read input function 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 read_input(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 */ char *strnlower(char *s, size_t n) { for (int i = 0; i < (int) n; i++) { s[i] = tolower(s[i]); }; } /* Search function Parameters: - query: search query - vendors: the vendor table - total_vendors: the amount of vendors Return values: - i: Item Number - 0: No results found */ /* TO-DO IMPLEMENT RESPONSE STRUCT */ struct search_r search(char query[], struct 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) { struct search_r response; response.status = 0; response.item_id = i; return (response); break; } else { struct search_r response; response.status = 2; return (response); } } }; if (i == total_vendors) { struct search_r response; response.status = 1; response.item_id = 0; return (response); } }; /* 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: - */ struct purchase_r purchase(int item_id, int amount, struct 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; struct 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 { struct purchase_r response; response.status = 1; strcpy(response.vendor_name, vendors[item_id].vendor_name); return response; } }; /* Check function Parameters: */ int check_vendors(struct vendor vendors[MAX_VENDORS], int total_vendors) { int i; for (i = 0; i < total_vendors; i++) { // If there are any items left if (vendors[i].inventory_count != 0 && vendors[i].duplicate == 0) { return 1; } } // There aren't any if (i == total_vendors) { return 0; } };