Currently, I am interested in programming. I have programmed a calculator in C. Everything works, but I do not feel completely confident in my solution.
Are there any logic or efficiency issues with my code?
Supported operations: \$+\$, \$-\$, \$*\$, and \$/\$.
Algorithm: Flowchart
main.c
#include "practice.h"
int main() {
char arr[100];
char c;
int length = 0;
int result;
while((c=(getchar())) != '\n')
arr[length++] = c;
result = EquationToQueue(arr,length);
printf("%d", result);
}
practice.c
#include "practice.h"
queue* make_queue(size_t capacity, enum data_type type) {
queue* new_queue;
new_queue = (queue*)malloc(sizeof(queue));
new_queue->top = 0;
new_queue->bottom = 0;
new_queue->capacity = capacity;
new_queue->type = type;
new_queue->element = (queue_element*)malloc(sizeof(queue_element) * capacity);
return new_queue;
}
void push_queue(queue* object_queue, enum data_type type, ...) {
va_list ap;
va_start(ap,type);
if(object_queue->top >= object_queue->capacity) {
printf("Over %d is impossible!", object_queue->capacity);
exit(0);
}
switch(type) {
case queue_INT :
object_queue->element[object_queue->top++].data.val_i = va_arg(ap,int);
break;
case queue_CHAR :
object_queue->element[object_queue->top++].data.val_c = (char)va_arg(ap,int);
break;
default :
printf("Unknown type in push_queue()\n");
exit(0);
}
va_end(ap);
}
void pop_queue(queue* object_queue, void *return_val) {
if (object_queue->top == object_queue->bottom) {
printf("queue is empty!\n");
exit(0);
}
switch(object_queue->type) {
case queue_INT :
*(int*)return_val = object_queue->element[object_queue->bottom++].data.val_i;
break;
case queue_CHAR :
*(char*)return_val = object_queue->element[object_queue->bottom++].data.val_c;
break;
default :
printf("Unknown type in pop_queue()\n");
exit(0);
}
}
void delete_queue(queue* object_queue) {
free(object_queue->element);
free(object_queue);
}
int calculate(int num1, char op, int num2) {
switch(op) {
case '+' :
return num1+num2;
case '-' :
return num1-num2;
case '*' :
return num1*num2;
case '/' :
return num1/num2;
default :
printf("operation is incorrect in calculate()!\n");
exit(0);
}
}
int EquationToQueue(char* arr, int length) {
queue* i_queue;
queue* c_queue;
int i;
int before = 0;
int num1;
int num2;
char op;
char op_tmp;
int num_tmp;
int result;
i_queue = make_queue(50, queue_INT);
c_queue = make_queue(50, queue_CHAR); //make two queues;
for (i=0;i<length;i++) {
switch(arr[i]) {
case '+' :
case '-' :
case '*' :
case '/' :
push_queue(i_queue, queue_INT, before);
push_queue(c_queue, queue_CHAR, arr[i]);
before = 0;
break;
default :
before = before*10 + arr[i] - '0';
break;
}
}
push_queue(i_queue, queue_INT, before); //save numbers in int queue and operations in char queue.
pop_queue(i_queue, &num1);
pop_queue(c_queue, &op);
pop_queue(i_queue, &num2); //initialize num1, op, num2;
while(i_queue->top != i_queue->bottom) {
pop_queue(c_queue, &op_tmp);
switch(op_tmp) {
case '+':
case '-':
num1 = calculate(num1, op, num2);
op = op_tmp;
pop_queue(i_queue, &num2);
break;
case '*':
case '/':
pop_queue(i_queue, &num_tmp);
num2 = calculate(num2, op_tmp, num_tmp);
break;
default :
printf("operation is incorrect in EquationToqueue()!\n");
exit(0);
}
}
result = calculate(num1, op, num2);// calculate algorithm.
return result;
}
practice.h
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
enum data_type {
queue_INT,
queue_CHAR
};
typedef struct {
union {
int val_i;
char val_c;
} data;
}queue_element;
typedef struct {
size_t top;
size_t bottom;
size_t capacity;
queue_element *element;
enum data_type type;
} queue;
queue* make_queue(size_t capacity, enum data_type type);
void push_queue(queue* object_queue, enum data_type type, ...);
void pop_queue(queue* object_queue, void *return_val);
void delete_queue(queue* object_queue);
int calculate(int num1, char op, int num2);
int EquationToQueue(char* arr, int length);