From 677f222fee6c356bb24b08426374a21203f5aa94 Mon Sep 17 00:00:00 2001 From: VyacheslavIurevich Date: Wed, 17 Jul 2024 13:56:00 +0300 Subject: [PATCH] feat: addition of old solution Signed-off-by: VyacheslavIurevich --- calculator | Bin 0 -> 21040 bytes src/calculator.c | 964 ++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 961 insertions(+), 3 deletions(-) create mode 100755 calculator diff --git a/calculator b/calculator new file mode 100755 index 0000000000000000000000000000000000000000..54d4ae0da8c67ec8b568b4a49966b0f14a968da1 GIT binary patch literal 21040 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 literal 0 HcmV?d00001 diff --git a/src/calculator.c b/src/calculator.c index 7791fbb..fea6d22 100644 --- a/src/calculator.c +++ b/src/calculator.c @@ -1,6 +1,964 @@ +#include +#include +#include #include +#include +#include +#define EXITCODE_ALL_FINE 0 +#define EXITCODE_COMMANDLINE_ARGS_ERROR 1 +#define EXITCODE_NO_INFIX 2 +#define EXITCODE_NO_DIVISION 3 +#define EXITCODE_INPUT_ERROR 4 +#define EXITCODE_OTHER_ERRORS 5 +#define QUEUE_CAPACITY 5000 +#define DLLIST_CAPACITY 300 +#define SIGN_NOT_SET -2 +#define BASE \ + 9 // my numerical system base is 10^9, if you change it nothing will work +#define TEN_POWER_BASE 1000000000 +#define DEPTH 25 -int main() { - printf("Hello world!\n"); - return 0; +typedef struct num_node_s { + uint64_t digit; + struct num_node_s *next; + struct num_node_s *prev; +} num_node_t; + +typedef struct { + num_node_t *first; + num_node_t *last; + int8_t sign; // sign is -2 if sign isn't set, -1 if number < 0, 0 if number == + // 0, 1 if number > 0 + size_t size; + size_t capacity; +} num_dllist_t; + +typedef struct { + num_dllist_t *res[DEPTH]; + uint8_t top; +} results_stack_t; + +typedef struct digits_node_s { + uint8_t decimal_digit; + struct digits_node_s *next; +} digits_node_t; + +typedef struct { + digits_node_t *head; + digits_node_t *tail; + size_t size; + size_t capacity; +} digits_queue_t; + +static num_dllist_t *dllist_init(uint8_t *exit_code) { + num_dllist_t *dllist = (num_dllist_t *)malloc(sizeof(num_dllist_t)); + + if (dllist == NULL) { + fprintf(stderr, "Cannot initialize double linked list\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + return NULL; + } + + dllist->first = NULL; + dllist->last = NULL; + dllist->sign = SIGN_NOT_SET; + dllist->size = 0; + dllist->capacity = DLLIST_CAPACITY; + + return dllist; +} + +static void dllist_clear(num_dllist_t *dllist, uint8_t *exit_code) { + num_node_t *temp; + + if (dllist == NULL) { + fprintf(stderr, "Cannot clear double linked list\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + while (dllist->first != NULL) { + temp = dllist->first; + dllist->first = temp->next; + free(temp); + } + + dllist->first = NULL; + dllist->last = NULL; + dllist->sign = SIGN_NOT_SET; + dllist->size = 0; + dllist->capacity = 0; + + free(dllist); +} + +static void dllist_add_start(num_dllist_t *dllist, uint64_t element, + uint8_t *exit_code) { + num_node_t *node = (num_node_t *)malloc(sizeof(num_node_t)); + + if ((node == NULL) || (dllist == NULL)) { + fprintf(stderr, "Cannot add element in the start of double linked list\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + if (dllist->size == dllist->capacity) { + fprintf(stderr, "Cannot add element in the start of double linked list " + "because it is full\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + node->digit = element; + node->next = dllist->first; + node->prev = NULL; + + if (dllist->first) { + dllist->first->prev = node; + } + dllist->first = node; + + if (dllist->last == NULL) { + dllist->last = node; + } + + ++dllist->size; +} + +static void dllist_add_end(num_dllist_t *dllist, uint64_t element, + uint8_t *exit_code) { + num_node_t *node = (num_node_t *)malloc(sizeof(num_node_t)); + + if ((node == NULL) || (dllist == NULL)) { + fprintf(stderr, + "Cannot add element to the end of the double linked list\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + if (dllist->size == dllist->capacity) { + fprintf(stderr, "Cannot add element to the end of the double linked list, " + "because it is full\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + node->digit = element; + node->next = NULL; + node->prev = dllist->last; + + if (dllist->last) { + dllist->last->next = node; + } + dllist->last = node; + + if (dllist->first == NULL) { + dllist->first = node; + } + + ++dllist->size; +} + +static void dllist_print(num_dllist_t *dllist, uint8_t *exit_code) { + num_node_t *temp = dllist->first; + bool flag = false; + + if (dllist == NULL) { + fprintf(stderr, "Cannot print answer \n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + if (dllist->sign == -1) + printf("-"); + + while (temp) { + if (flag) { + printf("%09lu", temp->digit); + } else { + printf("%ld", temp->digit); + flag = true; + } + temp = temp->next; + } + printf("\n"); +} + +static results_stack_t *stack_init(uint8_t *exit_code) { + results_stack_t *stack = (results_stack_t *)malloc(sizeof(results_stack_t)); + + if (stack == NULL) { + fprintf(stderr, "Cannot initialize stack\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + return NULL; + } + + stack->top = 0; + + return stack; +} + +static void stack_push(results_stack_t *stack, num_dllist_t *element, + uint8_t *exit_code) { + if ((stack == NULL) || (element == NULL)) { + fprintf(stderr, "Cannot push element to stack\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + if (stack->top < DEPTH) { + stack->res[stack->top] = element; + ++stack->top; + } else { + fprintf(stderr, "Stack is full, cannot push element\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } +} + +static num_dllist_t *stack_pop(results_stack_t *stack, uint8_t *exit_code) { + num_dllist_t *elem; + if (stack->top) { + --stack->top; + elem = stack->res[stack->top]; + return elem; + } else { + fprintf(stderr, "Cannot pop from empty stack\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + return NULL; + } +} + +static void stack_clear(results_stack_t *stack, uint8_t *exit_code) { + num_dllist_t *temp; + + if (stack == NULL) { + fprintf(stderr, "Cannot clear stack\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + while (stack->top) { + temp = stack_pop(stack, exit_code); + dllist_clear(temp, exit_code); + } + + free(stack); +} + +static digits_queue_t *queue_init(uint8_t *exit_code) { + digits_queue_t *queue = (digits_queue_t *)malloc(sizeof(digits_queue_t)); + + if (queue == NULL) { + fprintf(stderr, "Cannot initialize queue\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + return NULL; + } + + queue->head = NULL; + queue->tail = NULL; + queue->size = 0; + queue->capacity = QUEUE_CAPACITY; + + return queue; +} + +static void queue_clear(digits_queue_t *queue, uint8_t *exit_code) { + digits_node_t *temp; + + if (queue == NULL) { + fprintf(stderr, "Cannot clear queue\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + while (queue->head != NULL) { + temp = queue->head; + queue->head = queue->head->next; + free(temp); + } + + queue->tail = NULL; + queue->size = 0; + queue->capacity = 0; + + free(queue); +} + +static void queue_add(digits_queue_t *queue, uint8_t element, + uint8_t *exit_code) { + digits_node_t *node = (digits_node_t *)malloc(sizeof(digits_node_t)); + + if (node == NULL) { + fprintf(stderr, "Cannot create queue node\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + if (queue->size == queue->capacity) { + fprintf(stderr, "Queue is full, cannot add new node\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + node->decimal_digit = element; + node->next = NULL; + + if (queue->head == NULL) { + // we had an empty queue and now the queue consists of 1 node + queue->head = node; + queue->tail = node; + ++queue->size; + } else { + queue->tail->next = node; + queue->tail = node; + ++queue->size; + } +} + +static bool is_bigger(num_dllist_t *first_num, num_dllist_t *second_num, + uint8_t *exit_code) { + num_node_t *temp_first = first_num->first, *temp_second = second_num->first; + + if ((first_num == NULL) || (second_num == NULL)) { + fprintf(stderr, "Cannot compare numbers\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + } + + if (first_num->size > second_num->size) + return true; + else if (first_num->size < second_num->size) + return false; + else { + while ((temp_first) && (temp_second)) { + if (temp_first->digit > temp_second->digit) + return true; + else if (temp_first->digit < temp_second->digit) + return false; + else { + temp_first = temp_first->next; + temp_second = temp_second->next; + } + } + return false; + } +} + +static num_dllist_t *zero(uint8_t *exit_code) { + num_dllist_t *result = dllist_init(exit_code); + dllist_add_start(result, 0, exit_code); + result->sign = 0; + return result; +} + +static num_dllist_t *addition(num_dllist_t *first_num, num_dllist_t *second_num, + bool negative, uint8_t *exit_code) { + num_dllist_t *result = dllist_init(exit_code); + num_node_t *temp_first = first_num->last, *temp_second = second_num->last; + uint64_t digit_sum; + uint8_t add_to_digit = 0; + size_t first_size = first_num->size, second_size = second_num->size, + size_diff; + + if ((first_num == NULL) || (second_num == NULL)) { + fprintf(stderr, "Cannot add numbers\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + return NULL; + } + + if (first_size < second_size) { + for (size_diff = second_size - first_size; size_diff; --size_diff) { + dllist_add_start(first_num, 0, exit_code); + } + } else if (first_size > second_size) { + for (size_diff = first_size - second_size; size_diff; --size_diff) { + dllist_add_start(second_num, 0, exit_code); + } + } + + while ((temp_first) && (temp_second)) { + digit_sum = temp_first->digit + temp_second->digit + add_to_digit; + if (digit_sum >= TEN_POWER_BASE) { + add_to_digit = 1; + digit_sum -= TEN_POWER_BASE; + } else + add_to_digit = 0; + dllist_add_start(result, digit_sum, exit_code); + temp_first = temp_first->prev; + temp_second = temp_second->prev; + } + if (add_to_digit) + dllist_add_start(result, 1, exit_code); + + result->sign = ((negative) ? -1 : 1); + + return result; +} + +static num_dllist_t *subtraction(num_dllist_t *first_num, + num_dllist_t *second_num, bool negative, + uint8_t *exit_code) { + num_dllist_t *result = dllist_init(exit_code); + num_node_t *temp_first = first_num->last, *temp_second = second_num->last, + *search_node; + uint64_t first_digit = temp_first->digit, second_digit = temp_second->digit, + search_digit, digit_diff; + uint8_t changed_digits = 0; + bool to_reduce = false; + if ((first_num == NULL) || (second_num == NULL)) { + fprintf(stderr, "Cannot subtract numbers\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + return NULL; + } + + if (first_num->size > second_num->size) { + for (size_t size_diff = first_num->size - second_num->size; size_diff; + --size_diff) { + dllist_add_start(second_num, 0, exit_code); + } + } + + while ((temp_first) && (temp_second)) { + first_digit = temp_first->digit; + second_digit = temp_second->digit; + if ((first_digit == 0) && (changed_digits > 0)) { + first_digit = TEN_POWER_BASE - 1; + --changed_digits; + } else if ((first_digit > 0) && (to_reduce)) { + --first_digit; + to_reduce = false; + } + if (first_digit >= second_digit) + digit_diff = first_digit - second_digit; + else { + search_node = temp_first->prev; + search_digit = search_node->digit; + while (search_digit == 0) { + ++changed_digits; + search_node = temp_first->prev; + search_digit = search_node->digit; + } + to_reduce = true; + digit_diff = first_digit + TEN_POWER_BASE - second_digit; + } + dllist_add_start(result, digit_diff, exit_code); + temp_first = temp_first->prev; + temp_second = temp_second->prev; + } + + result->sign = ((negative) ? -1 : 1); + if ((result->size == 1) && (result->first->digit == 0)) + result->sign = 0; + return result; +} + +static num_dllist_t *multiplication(num_dllist_t *first_num, + num_dllist_t *second_num, int8_t sign, + uint8_t *exit_code) { + num_dllist_t *cur_num, *result = dllist_init(exit_code), *temp; + num_node_t *temp_first = first_num->last, *temp_second; + uint64_t first_digit, second_digit, partial = 0, remainder = 0, + digits_product; + uint16_t indent = 0, indent_idx; + if ((first_num == NULL) || (second_num == NULL)) { + fprintf(stderr, "Cannot multiplicate numbers\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + return NULL; + } + + dllist_add_end(result, 0, exit_code); + + while (temp_first) { + first_digit = temp_first->digit; + temp_second = second_num->last; + cur_num = dllist_init(exit_code); + cur_num->sign = 1; + if (indent) { + for (indent_idx = 0; indent_idx < indent; ++indent_idx) { + dllist_add_start(cur_num, 0, exit_code); + } + } + while (temp_second) { + second_digit = temp_second->digit; + digits_product = first_digit * second_digit + partial; + remainder = digits_product % TEN_POWER_BASE; + partial = digits_product / TEN_POWER_BASE; + dllist_add_start(cur_num, remainder, exit_code); + temp_second = temp_second->prev; + } + if (partial) { + dllist_add_start(cur_num, partial, exit_code); + partial = 0; + } + temp = addition(result, cur_num, false, exit_code); + dllist_clear(result, exit_code); + result = temp; + ++indent; + dllist_clear(cur_num, exit_code); + temp_first = temp_first->prev; + } + + result->sign = sign; + + return result; +} + +static num_dllist_t *calculate_operation_result(num_dllist_t *first_num, + num_dllist_t *second_num, + char operation, + uint8_t *exit_code) { + if ((first_num == NULL) || (second_num == NULL)) { + fprintf(stderr, "Cannot calculate operation result\n"); + *exit_code = EXITCODE_OTHER_ERRORS; + return NULL; + } else if (operation == '+') { + if (first_num->sign == 1) { + if (second_num->sign != -1) + return addition(first_num, second_num, false, exit_code); + else { + if (is_bigger(first_num, second_num, exit_code)) + return subtraction(first_num, second_num, false, exit_code); + else + return subtraction(second_num, first_num, true, exit_code); + } + } else if (first_num->sign == 0) { + if (second_num->sign != 0) + return addition(first_num, second_num, + ((second_num->sign == 1) ? false : true), exit_code); + else + return zero(exit_code); + } else { + if (second_num->sign == 1) { + if (is_bigger(first_num, second_num, exit_code)) + return subtraction(first_num, second_num, true, exit_code); + else + return subtraction(second_num, first_num, false, exit_code); + } else if (second_num->sign == 0) + return addition(first_num, second_num, true, exit_code); + else + return addition(first_num, second_num, true, exit_code); + } + } else if (operation == '-') { + if (first_num->sign == 1) { + if (second_num->sign == 1) { + if (is_bigger(first_num, second_num, exit_code)) + return subtraction(first_num, second_num, false, exit_code); + else + return subtraction(second_num, first_num, true, exit_code); + } else + return addition(first_num, second_num, false, exit_code); + } else if (first_num->sign == 0) { + if (second_num->sign != 0) + return addition(second_num, first_num, + ((second_num->sign == 1) ? true : false), exit_code); + else + return zero(exit_code); + } else if (first_num->sign == -1) { + if (second_num->sign == 1) + return addition(first_num, second_num, true, exit_code); + else if (second_num->sign == 0) + return addition(first_num, second_num, true, exit_code); + else { + if (is_bigger(first_num, second_num, exit_code)) + return subtraction(first_num, second_num, true, exit_code); + else + return subtraction(second_num, first_num, false, exit_code); + } + } + } else if (operation == '*') { + if (first_num->sign == 1) { + if (second_num->sign == 1) + return multiplication(first_num, second_num, 1, exit_code); + else if (second_num->sign == 0) + return zero(exit_code); + else + return multiplication(first_num, second_num, -1, exit_code); + } else if (first_num->sign == 0) + return zero(exit_code); + else { + if (second_num->sign == 1) + return multiplication(first_num, second_num, -1, exit_code); + else if (second_num->sign == 0) + return zero(exit_code); + else + return multiplication(first_num, second_num, 1, exit_code); + } + } + return NULL; +} + +static bool isoperation(char ch) { + return ((ch == '+' || ch == '-' || ch == '*')); +} + +static void parse_commandline_args(int argc, char **argv, uint8_t *exit_code) { + if (argc == 2) { + if (strcmp(argv[1], "--revpol") != 0) { + if (strcmp(argv[1], "--infix") == 0) { + fprintf(stderr, "This app doesn't support infix notation\n"); + *exit_code = EXITCODE_NO_INFIX; + } else { + fprintf(stderr, "Incorrect command line argument\n"); + *exit_code = EXITCODE_COMMANDLINE_ARGS_ERROR; + } + } + } else { + if (argc > 2) + fprintf(stderr, "Too much command line arguments entered\n"); + else + fprintf(stderr, "No command line arguments entered\n"); + *exit_code = EXITCODE_COMMANDLINE_ARGS_ERROR; + } +} + +static void parse_input(uint8_t *exit_code) { + char cur_ch, prev_ch; + bool convert_flag; + uint64_t cur_num; + uint8_t digits_count, add_digit = 0; + digits_queue_t *temp = NULL; + digits_node_t *cur_node; + num_dllist_t *cur_num_ns = NULL, *result = NULL, *first = NULL, + *second = NULL; + results_stack_t *results_stack = stack_init(exit_code); + + do { + cur_ch = getchar(); + } while (cur_ch == ' '); + + if (cur_ch == '\n' || cur_ch == EOF) { + fprintf(stderr, "Empty input\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } + + prev_ch = cur_ch; + if (!isdigit(cur_ch) && (cur_ch != '-') && (cur_ch != '\n') && + (cur_ch != EOF)) { + fprintf(stderr, + "Input must start with a digit, a minus or with a blank space\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } else { + while (*exit_code == EXITCODE_ALL_FINE && (cur_ch = getchar()) != '\n' && + cur_ch != EOF) { + if (cur_ch == '/') { + if ((cur_num_ns) && (!results_stack)) { + dllist_clear(cur_num_ns, exit_code); + cur_num_ns = NULL; + } + if (temp) { + queue_clear(temp, exit_code); + temp = NULL; + } + if (result) { + dllist_clear(result, exit_code); + result = NULL; + } + if (results_stack) { + stack_clear(results_stack, exit_code); + results_stack = NULL; + } + fprintf(stderr, "Division is not supported\n"); + *exit_code = EXITCODE_NO_DIVISION; + } + + if (isdigit(prev_ch)) { + if (isdigit(cur_ch)) { + if ((prev_ch == '0') && ((!temp) || (temp->size == 1))) { + if ((cur_num_ns) && (!results_stack)) { + dllist_clear(cur_num_ns, exit_code); + cur_num_ns = NULL; + } + if (temp) { + queue_clear(temp, exit_code); + temp = NULL; + } + if (result) { + dllist_clear(result, exit_code); + result = NULL; + } + if (results_stack) { + stack_clear(results_stack, exit_code); + results_stack = NULL; + } + fprintf(stderr, "A number can't start with a 0\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } else { + if (!temp) { + temp = queue_init(exit_code); + cur_num_ns = dllist_init(exit_code); + cur_num_ns->sign = 1; + add_digit = (uint8_t)(prev_ch - '0'); + queue_add(temp, add_digit, exit_code); + } + add_digit = (uint8_t)(cur_ch - '0'); + queue_add(temp, add_digit, exit_code); + } + } else if (isoperation(cur_ch)) { + if (cur_num_ns) { + dllist_clear(cur_num_ns, exit_code); + cur_num_ns = NULL; + } + if (temp) { + queue_clear(temp, exit_code); + temp = NULL; + } + if (result) { + dllist_clear(result, exit_code); + result = NULL; + } + if (results_stack) { + stack_clear(results_stack, exit_code); + results_stack = NULL; + } + fprintf(stderr, "Missing space between number and operation\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } else if (cur_ch == ' ') { + if (!temp) { + temp = queue_init(exit_code); + cur_num_ns = dllist_init(exit_code); + cur_num_ns->sign = ((prev_ch == '0') ? 0 : 1); + add_digit = (uint8_t)(prev_ch - '0'); + queue_add(temp, add_digit, exit_code); + } + // convert into 10^9 NS + if (temp->size == 1) + dllist_add_end(cur_num_ns, temp->head->decimal_digit, exit_code); + else { + cur_node = temp->head; + cur_num = 0; + convert_flag = true; + digits_count = (9 - temp->size % 9) % 9; + while (convert_flag) { + if (cur_node->next == NULL) + convert_flag = false; + if (digits_count < BASE) { + cur_num *= 10; + cur_num += cur_node->decimal_digit; + ++digits_count; + } + if (digits_count == BASE) { + dllist_add_end(cur_num_ns, cur_num, exit_code); + digits_count = 0; + cur_num = 0; + } + if (cur_node->next) + cur_node = cur_node->next; + } + } + stack_push(results_stack, cur_num_ns, exit_code); + queue_clear(temp, exit_code); + temp = NULL; + } else if (cur_ch != '/') { + if ((cur_num_ns) && (!results_stack->top)) { + dllist_clear(cur_num_ns, exit_code); + cur_num_ns = NULL; + } + if (temp) { + queue_clear(temp, exit_code); + temp = NULL; + } + if (result) { + dllist_clear(result, exit_code); + result = NULL; + } + if (results_stack) { + stack_clear(results_stack, exit_code); + results_stack = NULL; + } + fprintf(stderr, "Incorrect characters in input\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } + } else if (isoperation(prev_ch)) { + if (isdigit(cur_ch)) { + if (prev_ch != '-') { + if ((cur_num_ns) && (!results_stack)) { + dllist_clear(cur_num_ns, exit_code); + cur_num_ns = NULL; + } + if (temp) { + queue_clear(temp, exit_code); + temp = NULL; + } + if (result) { + dllist_clear(result, exit_code); + result = NULL; + } + if (results_stack) { + stack_clear(results_stack, exit_code); + results_stack = NULL; + } + fprintf(stderr, "Missing space between number and operation\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } else { + temp = queue_init(exit_code); + cur_num_ns = dllist_init(exit_code); + add_digit = (uint8_t)(cur_ch - '0'); + queue_add(temp, add_digit, exit_code); + cur_num_ns->sign = ((cur_ch != '0') ? -1 : 0); + } + } else if (isoperation(cur_ch)) { + if ((cur_num_ns) && (!results_stack)) { + dllist_clear(cur_num_ns, exit_code); + cur_num_ns = NULL; + } + if (temp) { + queue_clear(temp, exit_code); + temp = NULL; + } + if (result) { + dllist_clear(result, exit_code); + result = NULL; + } + if (results_stack) { + stack_clear(results_stack, exit_code); + results_stack = NULL; + } + fprintf(stderr, "Missing space between operations\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } else if (cur_ch == ' ') { + if (results_stack->top > 1) { + first = stack_pop(results_stack, exit_code); + second = stack_pop(results_stack, exit_code); + result = + calculate_operation_result(second, first, prev_ch, exit_code); + dllist_clear(first, exit_code); + dllist_clear(second, exit_code); + stack_push(results_stack, result, exit_code); + } else { + if (temp) { + queue_clear(temp, exit_code); + temp = NULL; + } + if (result) { + dllist_clear(result, exit_code); + result = NULL; + } + fprintf(stderr, "Missing numbers in input\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } + } else if ((cur_ch != '/') && (cur_ch != ' ')) { + if ((cur_num_ns) && (!results_stack)) { + dllist_clear(cur_num_ns, exit_code); + cur_num_ns = NULL; + } + if (temp) { + queue_clear(temp, exit_code); + temp = NULL; + } + if (result) { + dllist_clear(result, exit_code); + result = NULL; + } + if (results_stack) { + stack_clear(results_stack, exit_code); + results_stack = NULL; + } + fprintf(stderr, "Incorrect characters in input\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } + } else if (prev_ch == ' ') { + if (isdigit(cur_ch)) { + temp = queue_init(exit_code); + cur_num_ns = dllist_init(exit_code); + add_digit = (uint8_t)(cur_ch - '0'); + queue_add(temp, add_digit, exit_code); + cur_num_ns->sign = ((cur_ch == '0') ? 0 : 1); + } else if ((cur_ch != ' ') && (cur_ch != '/') && + (!isoperation(cur_ch))) { + if ((cur_num_ns) && (!results_stack)) { + dllist_clear(cur_num_ns, exit_code); + cur_num_ns = NULL; + } + if (temp) { + queue_clear(temp, exit_code); + temp = NULL; + } + if (result) { + dllist_clear(result, exit_code); + result = NULL; + } + if (results_stack) { + stack_clear(results_stack, exit_code); + results_stack = NULL; + } + fprintf(stderr, "Incorrect characters in input\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } + } + prev_ch = cur_ch; + } + } + if ((isdigit(prev_ch)) && (*exit_code == EXITCODE_ALL_FINE)) { + if (!temp) { + temp = queue_init(exit_code); + cur_num_ns = dllist_init(exit_code); + cur_num_ns->sign = ((prev_ch == '0') ? 0 : 1); + add_digit = (uint8_t)(prev_ch - '0'); + queue_add(temp, add_digit, exit_code); + } + if (temp->size == 1) + dllist_add_end(cur_num_ns, temp->head->decimal_digit, exit_code); + else { + cur_node = temp->head; + cur_num = 0; + convert_flag = true; + digits_count = (9 - temp->size % 9) % 9; + while (convert_flag) { + if (cur_node->next == NULL) + convert_flag = false; + if (digits_count < BASE) { + cur_num *= 10; + cur_num += cur_node->decimal_digit; + ++digits_count; + } + if (digits_count == BASE) { + dllist_add_end(cur_num_ns, cur_num, exit_code); + digits_count = 0; + cur_num = 0; + } + if (cur_node->next) + cur_node = cur_node->next; + } + } + stack_push(results_stack, cur_num_ns, exit_code); + } + if ((isoperation(prev_ch)) && (results_stack)) { + if (results_stack->top > 1) { + first = stack_pop(results_stack, exit_code); + second = stack_pop(results_stack, exit_code); + result = calculate_operation_result(second, first, prev_ch, exit_code); + dllist_clear(first, exit_code); + dllist_clear(second, exit_code); + stack_push(results_stack, result, exit_code); + } else { + if (cur_num_ns) { + dllist_clear(cur_num_ns, exit_code); + cur_num_ns = NULL; + } + if (temp) { + queue_clear(temp, exit_code); + temp = NULL; + } + if (result) { + dllist_clear(result, exit_code); + result = NULL; + } + fprintf(stderr, "Missing numbers in input\n"); + *exit_code = EXITCODE_INPUT_ERROR; + } + } + if (results_stack) { + if (results_stack->top == 1) { + result = stack_pop(results_stack, exit_code); + if (*exit_code == EXITCODE_ALL_FINE) + dllist_print(result, exit_code); + if (result) + dllist_clear(result, exit_code); + stack_clear(results_stack, exit_code); + } else if (results_stack->top > 1) { + fprintf(stderr, "Not enough operations\n"); + *exit_code = EXITCODE_INPUT_ERROR; + stack_clear(results_stack, exit_code); + } else + stack_clear(results_stack, exit_code); + } + if (temp) + queue_clear(temp, exit_code); +} + +int main(int argc, char **argv) { + uint8_t exit_code = EXITCODE_ALL_FINE; + + parse_commandline_args(argc, argv, &exit_code); + if (exit_code == EXITCODE_ALL_FINE) + parse_input(&exit_code); + + return exit_code; }