46 fputs(
"1. Manage Stock Levels\n"
47 "2. Generate Reports\n"
48 "3. Quit the Program\n\n"
49 "Please enter your selection: ",
65 fputs(
"Invalid option.\n\n", stderr);
70 while ((ch = getchar()) !=
'\n' && ch != EOF)
84static size_t get_input_line(
char *
const buffer,
const size_t buffer_size, FILE *
const stream)
87 if (!fgets(buffer, buffer_size - 1, stream))
91 fputs(
"Could not get line of input: ", stderr);
92 fputs(strerror(errno), stderr);
96 const size_t input_length = strlen(buffer);
100 if (buffer[input_length - 1] ==
'\n')
101 buffer[input_length - 1] =
'\0';
103 if (buffer[input_length] !=
'\0') {
104 fputs(
"Could not get line of input: too long.\n", stderr);
121 const unsigned long value = strtoul(buffer, &end, 10);
123 if (errno != 0 || value >= UINT_MAX || *end !=
'\0') {
129 return (
unsigned int) value;
142 const long value = strtol(buffer, &end, 10);
144 if (errno != 0 || value <= INT_MIN || value >= INT_MAX || *end !=
'\0') {
162 int quantity_modifier;
165 fputs(
"Please Enter a Unique Product Number : ", stdout);
168 unsigned int product_id;
169 bool error_flag =
get_input_line(buffer,
sizeof(buffer) /
sizeof(buffer[0]), stdin) < 1;
175 fputs(
"That is not a valid product ID.\n", stderr);
181 fputs(
"A product with that number does not exist!\n", stderr);
190 fputs(
"Please Enter A Stock Level Adjustment Value : ", stdout);
193 bool error_flag =
get_input_line(buffer,
sizeof(buffer) /
sizeof(buffer[0]), stdin) < 1;
198 fputs(
"That is not a valid quantity modifier.\n", stderr);
205 fputs(
"There is insufficient stock to allow that.\n", stderr);
219 char path_buffer[PATH_MAX + 1];
221 fputs(
"Enter a destination filename for the report : ", stdout);
224 FILE *
const destination =
get_input_line(path_buffer,
sizeof(path_buffer) /
sizeof(path_buffer[0]), stdin)
225 ? fopen(path_buffer,
"w+")
229 fprintf(stderr,
"Error writing to report file: file error %d.\n", ferror(destination));
231 if (destination != stdout)
245 unsigned int product_id = 0;
247 while (
get_input_line(name_buffer,
sizeof(name_buffer) /
sizeof(name_buffer[0]), stock_file)) {
248 if (!
get_input_line(quantity_buffer,
sizeof(name_buffer) /
sizeof(name_buffer[0]), stock_file)) {
249 fprintf(stderr,
"Missing quantity for product \"%s\"\n", name_buffer);
257 fprintf(stderr,
"Quantity for product \"%s\" is invalid.\n", name_buffer);
262 if (new_product == NULL) {
263 fprintf(stderr,
"Could not create new product \"%s\": %s\n", name_buffer, strerror(errno));
269 fprintf(stderr,
"Could not create new product \"%s\": %s\n", name_buffer, strerror(errno));
285 FILE *
const fp = fopen(filename,
"r+");
289 fputs(
"could not open stock data file : ", stdout);
292 fputs(strerror(errno), stdout);
293 fputs(
" : ", stdout);
297 fputs(
"using stock data file : ", stdout);
313 fprintf(stderr,
"Error writing to stock data file: file error %d.\n", ferror(datafile));
322int main(
const int argc,
const char **
const argv)
324 fputs(
"Stock Control Program Started - ", stdout);
325 FILE *stock_file =
open_stock_file(argc > 1 ? argv[1] :
"stock_data.txt");
326 if (stock_file == NULL)
336 bool continue_running =
true;
337 while (continue_running) {
347 continue_running =
false;
int pool_serialise_report(const struct Pool *const this, FILE *const buffer)
bool pool_insert_element(struct Pool *const this, struct Product *const product)
struct Product * pool_get_product_by_index(const struct Pool *const this, const unsigned int index)
void pool_delete(struct Pool **const this)
struct Pool * pool_create(const unsigned int initial_capacity, const float growth_factor)
int pool_serialise_stock_file(const struct Pool *const this, FILE *const buffer)
Pool class specification.
struct Product * product_create(const unsigned int id, const char *const name, const unsigned int quantity)
void product_delete(struct Product **this)
bool product_modify_quantity(struct Product *this, const int modifier)
Product class specification.
#define MAX_NAME_LENGTH
Maximum number of bytes for a Product name, excluding the NULL-terminator.
static void save_inventory(FILE *const datafile, const struct Pool *const pool)
Save the inventory in the stock file format to the given file buffer.
static FILE * open_stock_file(const char *const filename)
Open the stock file with the given file name for reading, reporting errors as encountered.
static void manage_stock(const struct Pool *const pool)
Interactively queries the user for a Product ID and an amount by which to modify the stock level.
MenuOption
Represents all menu options on the interactive menu.
@ MENU_QUIT
Quit the Program option.
@ MENU_MANAGE_STOCK
Manage Stock option.
@ MENU_GENERATE_REPORT
Generate Report option.
@ MENU_INVALID
Placeholder invalid menu state.
static void generate_reports(const struct Pool *const pool)
Interactively query the user for an output file, and write a report to the chosen destination.
static enum MenuOption get_menu_selection()
Presents the user with a menu and interactively retrieves the selection.
static bool load_inventory(FILE *const stock_file, struct Pool *const pool)
Parse the inventory from the given stock file into the given Pool.
static unsigned int convert_to_uint(const char *const buffer, bool *error)
Converts the string in the given buffer to an unsigned integer.
int main(const int argc, const char **const argv)
The application entry point for interactive control of the Stock Control System.
static size_t get_input_line(char *const buffer, const size_t buffer_size, FILE *const stream)
Gets a single line of input from the given input and writes to the given buffer.
static int convert_to_sint(const char *const buffer, bool *error)
Converts the string in the given buffer to a signed integer.
An ordered expandable collection of dynamically allocated Product records.
The Product represents a single product with a unique numerical identifier, human-readable name,...
unsigned int quantity
Non-negative number of Product items in stock.