flex-bison-in-action/analyzers/polynomials/stacks/stack/stack_test.c

133 lines
5.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// калькулятор на основе обратной польской записи
// gcc stack_test.c stack.c -o stack_test.exe
#include "stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Тестирование сценария:
// Токен: 2 -> Стек: [2]
// Токен: 2 -> Стек: [2, 2]
// Токен: 10 -> Стек: [2, 2, 10]
// Токен: 3 -> Стек: [2, 2, 10, 3]
// Токен: - -> Берем 3 и 10: 10-3=7 -> Стек: [2, 2, 7]
// Токен: * -> Берем 7 и 2: 2*7=14 -> Стек: [2, 14]
// Токен: x -> Стек: [2, 14, x]
// Токен: 8 -> Стек: [2, 14, x, 8]
// Токен: - -> Берем 8 и x: x-8 -> Стек: [2, 14, (x-8)]
// Токен: * -> Берем (x-8) и 14: 14*(x-8) -> Стек: [2, (14*(x-8))]
// Токен: + -> Берем (14*(x-8)) и 2: 2+(14*(x-8)) -> Стек: [(2+(14*(x-8)))]
// Ответ: (2+(14*(x-8)))
// P.S. и еще нескольких
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;
}
int main() {
char* res;
Element tokens[100];
tokens[0].str_ptr = "2"; tokens[0].type = 'n'; // number
tokens[1].str_ptr = "2"; tokens[1].type = 'n'; // number
tokens[2].str_ptr = "10"; tokens[2].type = 'n'; // number
tokens[3].str_ptr = "3"; tokens[3].type = 'n'; // number
tokens[4].str_ptr = "-"; tokens[4].type = 'o'; // operator
tokens[5].str_ptr = "*"; tokens[5].type = 'o'; // operator
tokens[6].str_ptr = "x"; tokens[6].type = 'v'; // variable
tokens[7].str_ptr = "8"; tokens[7].type = 'n'; // number
tokens[8].str_ptr = "-"; tokens[8].type = 'o'; // operator
tokens[9].str_ptr = "*"; tokens[9].type = 'o'; // operator
tokens[10].str_ptr = "+"; tokens[10].type = 'o'; // operator
res = calulate(tokens, 11);
printf("Result: %s\n", res);
free(res);
tokens[0].str_ptr = "2"; tokens[0].type = 'n';
tokens[1].str_ptr = "2"; tokens[1].type = 'n';
tokens[2].str_ptr = "+"; tokens[2].type = 'o';
res = calulate(tokens, 3);
printf("Result: %s\n", res);
free(res);
tokens[0].str_ptr = "2"; tokens[0].type = 'n';
tokens[1].str_ptr = "2"; tokens[1].type = 'n';
tokens[2].str_ptr = "+"; tokens[2].type = 'o';
tokens[3].str_ptr = "x"; tokens[3].type = 'v';
tokens[4].str_ptr = "*"; tokens[4].type = 'o';
res = calulate(tokens, 5);
printf("Result: %s\n", res);
free(res);
return 0;
}