Untitled

 avatar
unknown
c_cpp
2 years ago
5.8 kB
4
Indexable
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>

//Maximum array size
#define MAX 100

//Prototypes to create a Top-Down program
double       run_calculator(bool);
void         init_input(char*);
void         scan_data(char*, double*, bool);
double       do_next_op(char, double, double*, bool);
bool         confirm_binary_operator(char);
bool         confirm_unary_operator(char);

//Mandatory variables
bool         is_input_empty;
char         user_operator_input;
double       user_operand_input;
double       accumulator = 0.0;

//Operator arrays
const char   binary_operators[5] = {'+', '-', '*', '/', '^'};
const char   unary_operators[4]  = {'#', '%', '!', 'q'};

int main(void) {
    printf("Final result is: %lf", run_calculator(false));
    return 0;
}

double run_calculator(bool finish) {
    while (true){
        if (finish)
            break;

        char temp_input[MAX] = {0};

        printf("Enter operator, and an optional operand> ");
        fgets(temp_input, sizeof temp_input, stdin);

        init_input(temp_input);

        printf("Result so far is %lf\n", accumulator);
    }

    return accumulator;
}

void init_input(char *user_input){
    char    newString[MAX][MAX] = {0};
    int     j = 0, ctr = 0;

    // https://www.w3resource.com/c-programming-exercises/string/c-string-exercise-31.php
    // C Programming: Split string by space into words
    for(int i = 0; i <= strlen(user_input); i++)
    {
        //if space or NULL found, assign NULL into newString[ctr]
        if(user_input[i] == ' ' || user_input[i] == '\0')
        {
            newString[ctr][j] = '\0';
            ctr++;  //for next word
            j=0;    //for next word, init index to 0
        }
        else
        {
            newString[ctr][j] = user_input[i];
            j++;
        }
    }

    bool temp_invalid_operator =
            (!confirm_binary_operator(*newString[0]) && !confirm_unary_operator(*newString[0])) ? true : false;

    switch(ctr){
        case 1:
            if (temp_invalid_operator)
                scan_data(NULL, NULL, true);
            else{
                user_operator_input = *newString[0];
                scan_data(&user_operator_input, NULL, false);
            }
            break;

        case 2:
            if (temp_invalid_operator || isdigit(*newString[1]) == 0) {
                //printf("%c & %c & %d & %d\n", *newString[0], *newString[1], temp_invalid_operator, isdigit(*newString[1]));
                scan_data(NULL, NULL, true);
            }else{
                user_operator_input = *newString[0];
                user_operand_input  = atof(newString[1]);
                printf("%c & %lf\n", user_operator_input, user_operand_input);
                scan_data(&user_operator_input, &user_operand_input, false);
            }
            break;

        default:
            scan_data(NULL, NULL, true);
    }
}

void scan_data(char *operator_output, double *operand_output, bool INPUT_EMPTY_FLAG){
    is_input_empty = INPUT_EMPTY_FLAG;

    if (INPUT_EMPTY_FLAG)
        return;

    if ((double*) operand_output != (double*)0 &&
        !confirm_binary_operator(*operator_output)){

         *operand_output = 0.0;

        for (int i = 0; i < strlen(unary_operators); i++){
            if (*operator_output == unary_operators[i])
                *operator_output = unary_operators[i];
        }

        do_next_op(*operator_output, *operand_output, &accumulator, false);
        return;
    }else if ((double*) operand_output != (double*)0 &&
              confirm_binary_operator(*operator_output)){

        do_next_op(*operator_output, *operand_output, &accumulator, true);
        return;
    }else{
        exit(EXIT_FAILURE);
    }
}

double do_next_op(char operator_input, double operand_input,
                  double *accumulator_variable, bool BINARY_OPERATOR_FLAG){

    if (is_input_empty)
        return 0;

    //TODO: Implement all the accumulative operations
    if (BINARY_OPERATOR_FLAG) {
        switch(operator_input){
            case '+':
                return (*accumulator_variable += operand_input);
            case '-':
                return (*accumulator_variable -= operand_input);
            case '*':
                return (*accumulator_variable *= operand_input);
            case '/':
                return (*accumulator_variable /= operand_input);
            case '^':
                return (pow(*accumulator_variable, operand_input));
            default:
                exit(EXIT_FAILURE);
        }
    }else{
        switch(operator_input){
            case '#':
                return (sqrt(*accumulator_variable));
            case '%':
                return (-*accumulator_variable);
            case '!':
                return (1 / *accumulator_variable);
            case 'q':
                run_calculator(true);
                break;
            default:
                exit(EXIT_FAILURE);
        }
    }
    return 0;
}

bool confirm_binary_operator(char operator){
    //size_t size_of_binary_arr = sizeof(binary_operators) / sizeof(*binary_operators);
    //size_t size_of_unary_arr = sizeof(unary_operators) / sizeof(*unary_operators);

    for (int i = 0; i < strlen(binary_operators); i++){
        if (binary_operators[i] == operator){
            return true;
        }
    }

    return false;
}

bool confirm_unary_operator(char operator){
    //size_t size_of_binary_arr = sizeof(binary_operators) / sizeof(*binary_operators);
    //size_t size_of_unary_arr = sizeof(unary_operators) / sizeof(*unary_operators);

    for (int i = 0; i < strlen(unary_operators); i++){
        if (unary_operators[i] == operator){
            return true;
        }
    }

    return false;
}
Editor is loading...