calc reverse polish notation
parent
e23b6d4877
commit
d59a177dc2
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.gcss": "sass",
|
||||||
|
"*.gohtml": "html",
|
||||||
|
"stdlib.h": "c",
|
||||||
|
"opd_stack.h": "c",
|
||||||
|
"stdio.h": "c"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,58 @@
|
||||||
|
#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--;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef STACK_H
|
||||||
|
#define STACK_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#define MAX_STACK_SIZE 100
|
||||||
|
|
||||||
|
// Структура элемента стека
|
||||||
|
typedef struct {
|
||||||
|
char *str_ptr; // Указатель на строку
|
||||||
|
char type; // Тип операнда
|
||||||
|
} Element;
|
||||||
|
|
||||||
|
// Структура стека
|
||||||
|
typedef struct {
|
||||||
|
Element data[MAX_STACK_SIZE]; // Массив элементов
|
||||||
|
int top;
|
||||||
|
} Stack;
|
||||||
|
|
||||||
|
// Инициализация стека
|
||||||
|
void initStack(Stack *s);
|
||||||
|
|
||||||
|
// Проверка на пустоту
|
||||||
|
bool isEmpty(Stack *s);
|
||||||
|
|
||||||
|
// Проверка на переполнение
|
||||||
|
bool isFull(Stack *s);
|
||||||
|
|
||||||
|
// Добавление опаранда в стек (push),
|
||||||
|
// операндом может быть число или выражение с переменной
|
||||||
|
bool push(Stack *s, const char *value, char type);
|
||||||
|
|
||||||
|
// Извлечение элемента из стека (pop)
|
||||||
|
bool pop(Stack *s, Element *out);
|
||||||
|
|
||||||
|
// Просмотр верхнего элемента без извлечения (peek)
|
||||||
|
bool peek(Stack *s, Element *out);
|
||||||
|
|
||||||
|
// Очистка стека (освобождение памяти)
|
||||||
|
void clearStack(Stack *s);
|
||||||
|
|
||||||
|
#endif // STACK_H
|
|
@ -0,0 +1,133 @@
|
||||||
|
// калькулятор на основе обратной польской записи
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
2+2*(10-3)
|
2+2*(10-3)*(x-8)
|
Loading…
Reference in New Issue