division

Simple C Math Program

Blog tags: 

While writing an exercise for my book currently in editing, I wrote a quick utility for math operations on the CLI in Bash

/**
 * @file main.c
 * @author Ron Brash
 * @date Nov 16, 2017
 * @brief Create a simple math helper for CLI usage in Bash
 *
 * @note To compile:
 *      gcc -Wall -O2 -o mhelper main.c -lm
 */
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#include <math.h>

#define USAGE "%s <param1> <operation> <param2>\n"
#define TRUE 1
#define FALSE 0

// Function pointer for math operations
typedef void (*mathfpr_t) (double, double, uint8_t, uint8_t);

// Typedef of structure containing math operation function pointers
// think array of callbacks
typedef struct mathop_s {
        char op;
        mathfpr_t func;
} mathop_t;

// Forward function declarations
static void subtract(double a, double b, uint8_t a_type, uint8_t b_type);
static void addition(double a, double b, uint8_t a_type, uint8_t b_type);
static void divide(double a, double b, uint8_t a_type, uint8_t b_type);
static void multiply(double a, double b, uint8_t a_type, uint8_t b_type);
static inline int is_whole(double a);
static inline int has_decimal(char *a);

// Declared function pointer array
static mathop_t math_arr[] = { {'-', subtract}, {'+', addition}, {'*', multiply}, {'/', divide}, };

static inline int has_decimal(char *a)
{

        int len = 0;
        for (len = strlen(a); len > 0; len--) {
                if (a[len] == '.') {
                        return (TRUE);
                }
        }
        return (FALSE);
}

static inline int is_whole(double a)
{
        if (a == (int)a) {
                // true
                return (TRUE);
        }
        // false
        return (FALSE);
}

static inline void print_val(double a, int type)
{

        if (type == 0) {
                printf("%.2f\n", a);    // Only print out two decimal points
        } else {
                printf("%i\n", (int)a);
        }
}

static void subtract(double a, double b, uint8_t a_type, uint8_t b_type)
{

        double res = a - b;
        print_val(res, is_whole(res));
}

static void divide(double a, double b, uint8_t a_type, uint8_t b_type)
{

        double res = a / b;
        print_val(res, is_whole(res));
}

static void multiply(double a, double b, uint8_t a_type, uint8_t b_type)
{

        double res = a * b;
        print_val(res, is_whole(res));
}

static void addition(double a, double b, uint8_t a_type, uint8_t b_type)
{

        double res = a + b;
        print_val(res, is_whole(res));
}

static void set_param(char *param, double *val, int *type)
{

        char *tmp;
        if (has_decimal(param) > 0) {
                *val = strtof(param, NULL);
                *type = 1;
        } else {
                *val = strtoll(param, &tmp, 10);
        }

}

int main(int argc, char *argv[])
{

        /// Initialize function variables in the stack
        double a = 0, b = 0;
        int a_type = 0, b_type = 0;
        char op = '\0';

        /// There are four parameters including the binary itself on the CLI
        if (argc == 4) {

                /// Copy params to values
                strncpy(&op, argv[2], sizeof(char));

                /// Let's set &  check if it has a decimal (signify a float early)
                set_param(argv[1], &a, &a_type);
                set_param(argv[3], &b, &b_type);

                int i = 0;
                for (i = 0; i < sizeof(math_arr); i++) {
                        if (op == math_arr[i].op) {
                                math_arr[i].func(a, b, a_type, b_type);
                                return (TRUE);
                                break;
                        }
                }

        }

        printf(USAGE, argv[0]);
        return (FALSE);
}

Enjoy

Subscribe to RSS - division