Instructions
Requirements and Specifications
- Start by allowing the entry of the current stock in the store, which it will save and update during the day.
- Switch to sales mode where it will act like a cash register and allow customers to purchase things. It will update the inventory as items are sold and will produce an itemized receipt for the customer.
- At the end of the day, print a summary of the sales, the inventory remaining and the top sellers in each category.
- produce
- bakery
- meat
- dairy
- baking
- house wares
- miscellaneous
- main.c which is the main for the program. This means that you will need to implement the data structures it uses and the functions it uses in the files stock.h and stock.c. You SHOULD create additional functions, other than the ones called from main, to create a highly modular, well-designed program. Your code will be tested against this main.c and your code must work and produce the expected output.
- A sample execution of the program to which your program’s output should look very similar.
- Sample data which can be cut and pasted into the program for final testing. This is the data which generated the sample output.
- Place a comment at the top of both stock.h and stock.c listing the names of every member of the group.
- Individually write a reflection based on the questions below and submit it on Blackboard. This means that a group of 3 students will need to submit 3 different reflections.
- BONUS: (5%) if you read the existing stock from a file containing the test data with the errors fixed. You will need to correct the errors in the data and place it in a file. Then, you can read it from the file without the error checking that is done with the manually typed version. You can change the value of the constant STOCK_FROM_STDIN declared in main to allow you to read from a file. Note that the sales will continue to be read from stdin, it is only the initial stock which will be read from the file. This will change the output to show the initial prompt for stock followed immediately the summary of the opening stock. The typing of the stock will vanish as it is being read from a file.
- This is a highly modular program consisting of multiple functions. For each function you personally wrote, describe what it does and why it deserves to be a function. Be sure to include the functions you added which were not called directly from main.
- The input for the program is different from what you are accustomed to seeing. Rather than prompting for each individual value, it prompts for several values at once. What benefit does this provide? How does it complicate the reading of the input? How were you able to handle the commas separating the input values?
- Finding the top sellers in each category requires the development of an algorithm. Describe how you went about developing this algorithm. Then, describe how your algorithm works.
You are required to:
Source Code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "stock.h"
char* categories[] = {"produce", "bakery", "meat", "dairy", "baking", "house wares", "miscellaneous"};
void readLine(FILE* f, char *line) {
if (f == NULL) {
fgets(line, 256, stdin);
}
else {
fgets(line, 256, f);
}
}
int readStockItems(struct StockRecord *stockRecord, int size, int useStdIn) {
char defaultInputFilename[] = "input.txt";
FILE *f = NULL;
if (useStdIn == 0) {
f = fopen(defaultInputFilename, "r");
if (f == NULL) {
printf("Can not open input file\n");
return 0;
}
}
char line[256];
int count = 0;
while(1) {
readLine(f, line);
char *pch = strtok(line, ",");
struct StockRecord *current = &(stockRecord[count]);
current->amount = atof(pch);
current->initAmount = current->amount;
if (current->amount == 0) {
break;
}
pch = strtok(NULL, ",");
while (1) {
current->category = atoi(pch);
if (current->category < 1 || current->category > 7) {
printf("Invalid Category - Enter a number between 1 and 7: ");
readLine(f, line);
pch = strtok(line, ",");
continue;
}
break;
}
pch = strtok(NULL, ",");
current->price = atof(pch);
pch = strtok(NULL, ",");
while (1) {
current->byWeight = atoi(pch);
if (current->byWeight < 0 || current->byWeight > 1) {
printf("Invalid soldByWeight - Enter a number between 0 and 1: ");
readLine(f, line);
pch = strtok(line, ",");
continue;
}
break;
}
current->name = malloc(256*sizeof(char));
strcpy(current->name,strtok(NULL, "\n"));
current->id = count;
count++;
}
printf("%s\n", stockRecord[0].name);
if (useStdIn == 0) {
fclose(f);
}
return count;
}
void centreText(int len, char c, char* s) {
int sLen = strlen(s);
int firstPart = (len - sLen) / 2;
int secondPart = (len - sLen + 1) / 2;
for (int i = 0; i<firstPart; i++) {
printf("%c", c);
}
printf("%s", s);
for (int i = 0; i<secondPart; i++) {
printf("%c", c);
}
printf("\n");
}
void printStockReport(struct StockRecord *stockRecord, int size) {
printf("%4s%31s%16s%8s%9s\n", "ID", "Product", "Category", "Price", "Quantity");
for (int i = 0; i<size; i++) {
struct StockRecord *current = &(stockRecord[i]);
printf("%4d%31s%16s %6.2f%9.0f\n", (i+1), current->name, categories[current->category-1],
current->price, current->amount);
}
}
int readSale(struct StockRecord *stockRecord, int size, struct SalesRecord *salesRecord) {
char line[256];
int count = 0;
while(1) {
printf("Enter a product ID to purchase, and the quantity (0 to stop): ");
readLine(NULL, line);
char *pch = strtok(line, ",");
struct SalesRecord *current = &(salesRecord[count]);
int id = atoi(pch);
if (id == 0) {
break;
}
if (id < 1 || id > size) {
printf("Invalid Product - Enter a number between 1 and %d: ", size);
continue;
}
current->id = id;
pch = strtok(NULL, ",");
double quantity = atof(pch);
if (quantity < 0.1 || quantity > 100) {
printf("Invalid quantity - Enter a number between 0.10 and 100.00: ");
continue;
}
current->quantity = quantity;
count++;
}
return count;
}
double printSalesReport(struct StockRecord *stockRecord, struct SalesRecord *salesRecord, int size) {
double overall = 0.0;
double tax = 0.0;
centreText(70, '*', " Seneca Groceries ");
printf("\n");
centreText(70, '=', "");
printf("\n");
for (int i = 0; i<size; i++) {
struct SalesRecord *sales = &(salesRecord[i]);
struct StockRecord *stock = &(stockRecord[sales->id-1]);
double q = sales->quantity > stock->amount ? stock->amount : sales->quantity;
stock->amount -= q;
double total = q * stock->price;
overall += total;
int category = stock->category;
if (category == 6 || category == 7) {
tax += 0.13 * total;
}
printf("%35s%10.2f%10.2f\n", stock->name, stock->price, total);
}
printf("%-35s %10.2f\n", "Purchase Total", overall);
printf("%-35s %10.2f\n", "Tax", tax);
printf("%-35s %10.2f\n", "Total", (tax + overall));
printf("Thank you for shopping at Seneca!\n");
return overall;
}
void getTopSellers(struct StockRecord *stockRecord, int size, struct SalesRecord *salesRecord, int top, int cat) {
struct StockRecord *copy[size];
int catCount = 0;
for (int i = 0; i<size; i++) {
if (stockRecord[i].category-1 == cat && stockRecord[i].initAmount > stockRecord[i].amount) {
copy[catCount] = &(stockRecord[i]);
catCount++;
}
}
for (int i = 0; i<catCount; i++) {
for (int j = i+1; j<catCount; j++) {
double di = copy[i]->initAmount - copy[i]->amount;
double dj = copy[j]->initAmount - copy[j]->amount;
if (dj > di) {
struct StockRecord *sw = copy[j];
copy[j] = copy[i];
copy[i] = sw;
}
}
}
for (int i = 0; i<top; i++) {
if (i < catCount) {
salesRecord[i].id = copy[i]->id;
salesRecord[i].quantity = copy[i]->initAmount - copy[i]->amount;
}
else {
salesRecord[i].id = -1;
salesRecord[i].quantity = 0.0;
}
}
}
void printTopSellers(struct StockRecord *stockRecord, struct SalesRecord *salesRecord, int top, int cat) {
char title[70];
sprintf(title, " Top %d sellers in %s", top, categories[cat]);
centreText(70, '-', title);
printf("%4s%31s%16s\n", "Rank", "Product", "Sales");
for (int i = 0; i<top; i++) {
if (salesRecord[i].id == -1) {
printf("%4d%31s%13.2f\n", (i+1), "<none>", 0.0);
}
else {
printf("%4d%31s%13.2f\n", (i+1), stockRecord[salesRecord[i].id].name, salesRecord[i].quantity);
}
}
}