128 lines
4.2 KiB
C
128 lines
4.2 KiB
C
#include "stack.h"
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
void initStack(Stack *s) {
|
||
s->top = -1;
|
||
}
|
||
|
||
bool isEmpty(Stack *s) {
|
||
return s->top == -1;
|
||
}
|
||
|
||
bool isFull(Stack *s) {
|
||
return s->top == MAX_STACK_SIZE - 1;
|
||
}
|
||
|
||
bool push(Stack *s, const char *value, char type) {
|
||
if (isFull(s)) {
|
||
fprintf(stderr, "Stack overflow!\n");
|
||
return false;
|
||
}
|
||
char *new_str = malloc(strlen(value) + 1);
|
||
if (new_str == NULL) {
|
||
fprintf(stderr, "Memory allocation failed!\n");
|
||
return false;
|
||
}
|
||
strcpy(new_str, value);
|
||
s->top++;
|
||
s->data[s->top].str_ptr = new_str;
|
||
s->data[s->top].type = type;
|
||
return true;
|
||
}
|
||
|
||
bool pop(Stack *s, Element *out) {
|
||
if (isEmpty(s)) {
|
||
fprintf(stderr, "Stack is empty!\n");
|
||
return false;
|
||
}
|
||
*out = s->data[s->top--];
|
||
return true;
|
||
}
|
||
|
||
bool peek(Stack *s, Element *out) {
|
||
if (isEmpty(s)) {
|
||
fprintf(stderr, "Stack is empty!\n");
|
||
return false;
|
||
}
|
||
*out = s->data[s->top];
|
||
return true;
|
||
}
|
||
|
||
void clearStack(Stack *s) {
|
||
while (s->top >= 0) {
|
||
free(s->data[s->top].str_ptr);
|
||
s->top--;
|
||
}
|
||
}
|
||
|
||
char* calulate(Element* tokens, int tokens_count) {
|
||
#define MAX_ELEMENT_STRING_SIZE 100
|
||
Stack s_operands;
|
||
initStack(&s_operands);
|
||
for (int i = 0; i < tokens_count; ++i) {
|
||
Element token = tokens[i];
|
||
if (token.type == 'n' || token.type == 'v') {
|
||
// если число или выражение с переменной - добавляю в стек
|
||
push(&s_operands, token.str_ptr, token.type);
|
||
} else {
|
||
// если оператор
|
||
char op = token.str_ptr[0];
|
||
|
||
// беру со стека 2 последних операнда
|
||
Element second_operand; pop(&s_operands, &second_operand);
|
||
Element first_operand; pop(&s_operands, &first_operand);
|
||
|
||
char result[MAX_ELEMENT_STRING_SIZE] = { 0 };
|
||
|
||
if (first_operand.type == 'n' && second_operand.type == 'n') {
|
||
// оба операнда - числа => вычисляю значение выражения и его закидываю в стек
|
||
int first_num = atoi(first_operand.str_ptr);
|
||
int second_num = atoi(second_operand.str_ptr);
|
||
|
||
switch (op) {
|
||
case '+': {
|
||
int result_num = first_num + second_num;
|
||
//printf("%i + %i = %i\n", first_num, second_num, result_num);
|
||
snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num);
|
||
push(&s_operands, result, 'n');
|
||
break;
|
||
}
|
||
case '-': {
|
||
int result_num = first_num - second_num;
|
||
//printf("%i - %i = %i\n", first_num, second_num, result_num);
|
||
snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num);
|
||
push(&s_operands, result, 'n');
|
||
break;
|
||
}
|
||
case '*': {
|
||
int result_num = first_num * second_num;
|
||
//printf("%i * %i = %i\n", first_num, second_num, result_num);
|
||
snprintf(result, MAX_ELEMENT_STRING_SIZE, "%d", result_num);
|
||
push(&s_operands, result, 'n');
|
||
break;
|
||
}
|
||
}
|
||
} else {
|
||
// хотя бы один операнд содержит переменную
|
||
|
||
snprintf(result, MAX_ELEMENT_STRING_SIZE, "(%s%c%s)", first_operand.str_ptr, op, second_operand.str_ptr);
|
||
//printf("%s %c %s = %s\n", first_operand.str_ptr, op, second_operand.str_ptr, result);
|
||
push(&s_operands, result, 'v'); // Помечаю как выражение с переменной
|
||
}
|
||
|
||
free(first_operand.str_ptr);
|
||
free(second_operand.str_ptr);
|
||
}
|
||
}
|
||
|
||
if (!isEmpty(&s_operands)) {
|
||
Element result;
|
||
pop(&s_operands, &result);
|
||
//printf("Result: %s\n", result.str_ptr);
|
||
return result.str_ptr;
|
||
}
|
||
|
||
return NULL;
|
||
} |