From bd0772bb4a1950b3f438d7b9d8a82daac796f59d Mon Sep 17 00:00:00 2001 From: "Douglas B. Rumbaugh" Date: Mon, 6 Jan 2025 12:41:54 -0500 Subject: Added first version of a cumulative sum program --- src/cumsum.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 src/cumsum.c (limited to 'src/cumsum.c') diff --git a/src/cumsum.c b/src/cumsum.c new file mode 100644 index 0000000..5648661 --- /dev/null +++ b/src/cumsum.c @@ -0,0 +1,159 @@ +/* + * + */ + + +#include "cumsum.h" + +/* + * Global configuration variables. These are set based on command-line + * arguments, and read-only beyond that point. + */ +static bool ARG_FP_INPUT = false; +static bool ARG_UINT_INPUT = false; +static bool ARG_HELP = false; + +static int parse_options(int argc, char*const* argv) { + int arg_index = 0; + int arg; + bool error = false; + + while ((arg = getopt(argc, argv, "frhu")) != -1) { + switch (arg) { + case 'f': + ARG_FP_INPUT = true; + break; + case 'u': + ARG_UINT_INPUT = true; + case 'h': + ARG_HELP = true; + break; + case '?': + if (isprint(optopt)) { + fprintf(stderr, "Unknown option `-%c`.\n", optopt); + } else { + fprintf(stderr, "Unknown option character `\\x%x`.\n", optopt); + } + error = true; + break; + default: + error = true; + break; + } + } + + if (ARG_UINT_INPUT && ARG_FP_INPUT) { + fprintf(stderr, "Error: the -u and -f flags are mutually exclusive.\n"); + error = true; + } + + if (!error) { + arg_index = optind; + } + + return arg_index; +} + +static void help() { + fprintf(stderr, "Usage:\ncumsum [-f|-u] [filename]\n"); +} + +void print_sum(Number sum) { + if (ARG_FP_INPUT) { + fprintf(stdout, "%lf\n", sum.d); + } else if (ARG_UINT_INPUT) { + fprintf(stdout, "%ld\n", sum.u); + } else { + fprintf(stdout, "%ld\n", sum.i); + } +} + +static int read_data_fp(FILE *file, Number *num) { + double val; + while (fscanf(file, "%lf ", &val) != EOF) { + num->d += val; + } + + return 1; +} + +static int read_data_int(FILE *file, Number *num) { + int64_t val; + while (fscanf(file, "%ld ", &val) != EOF) { + num->i += val; + } + + return 1; +} + +static int read_data_uint(FILE *file, Number *num) { + uint64_t val; + while (fscanf(file, "%ld ", &val) != EOF) { + num->u += val; + } + + return 1; +} + +static int process_data(FILE *file) { + int rc = 1; + + Number sum = {}; + + /* FIXME: this could probably use a type-based macro to collapse the + if statements into a single macro call + */ + if (ARG_FP_INPUT) { + rc = read_data_fp(file, &sum); + } else if (ARG_UINT_INPUT) { + rc = read_data_uint(file, &sum); + } else { + rc = read_data_int(file, &sum); + } + + if (rc) { + print_sum(sum); + } + +process_data_end: + return rc; +} + + +int main(int argc, char **argv) { + int rc = EXIT_SUCCESS; + int file_index = 0; + if (!(file_index = parse_options(argc, argv))) { + help(); + rc = EXIT_FAILURE; + goto program_exit; + } + + /* if the -h argument is supplied, print usage and exit successfully */ + if (ARG_HELP) { + help(); + goto program_exit; + } + + /* open the input file, if one is specified, otherwise default to stdin */ + FILE *input_file; + if (file_index < argc && strcmp(argv[file_index], "-") != 0) { + if (!(input_file = fopen(argv[file_index], "r"))) { + fprintf(stderr, "Error: Unable to open input file %s\n", argv[file_index]); + rc = EXIT_FAILURE; + goto program_exit; + } + } else { + input_file = stdin; + } + + if (!process_data(input_file)) { + rc = EXIT_FAILURE; + } + +close_file: + fclose(input_file); + +program_exit: + exit(rc); +} -- cgit v1.2.3