-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcalculator.cpp
157 lines (146 loc) · 3.68 KB
/
calculator.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
#include "calculator.h"
#include <iostream>
#include <string>
using namespace std;
int isOp(char op)
{
if (op == '+' || op == '-' || op == '*' || op == '/')
return 1;
return 0;
}
node *init(char *value, float isop)
{
// armazena a memória para o nodo
node *n = (node *)malloc(sizeof(node));
if (isop) // verifica se é uma operação para deixar o flag da struct marcado
{
n->is_op = true;
n->value.op = value[0];
} else /// converte a string para float e atribui ela à variavel
n->value.number = atof((const char *)value);
n->left = NULL;
n->right = NULL;
return n;
}
node *buildtree(char *str, int *i)
{
node *node = NULL;
// a cada "(", um novo nodo é criado para armazenar o próximo número ou operação
if (str[*i] == '(')
{
char *number; // string provissória
number = (char *)malloc(30 * sizeof(char));
int num = 0;
(*i)++;
if (isOp(str[*i]) && ((str[(*i) + 1] == ')') || (str[(*i) + 1] == '(')))
{ // se for uma operação, e o proximo caractere não for um número, quer dizer que é uma operação e não um número negativo por exemplo
number[0] = str[*i];
node = init(number, true);
(*i)++;
} else
{ // caso contrário, é um número, então armazena cada caractere numa string até se achar o final dado por ")"
for (; str[*i] != ')'; (*i)++)
{
number[num] = str[*i];
num++;
}
node = init(number, false);
}
node->left = buildtree(str, i);
node->right = buildtree(str, i);
(*i)++;
free(number);
number = NULL;
}
return node;
}
void delete_tree(node *no)
{
if (no != NULL)
{
delete_tree(no->left);
delete_tree(no->right);
free(no);
}
}
float operation(char op, float left, float right)
{
switch (op)
{
case '+':
return (left + right);
break;
case '-':
return (left - right);
break;
case '*':
return (left * right);
break;
case '/':
return (left / right);
break;
default:
return 0;
break;
}
}
void print_expression(node *no)
{
if (no != NULL)
{ // se for uma operação, isola ela com parenteses para respeitar a ordem da conta
if (no->is_op)
{
cout << '(';
print_expression(no->left);
cout << no->value.op;
print_expression(no->right);
cout << ')';
} else
{
print_expression(no->left);
cout << no->value.number;
print_expression(no->right);
}
}
}
node *calculate(node *no)
{
// o calculate só é chamado com nodos que são operações, então não é necessário que se verifique isso
if (no != NULL)
{
// verifica se há operações para serem feitas antes
if (no->left->is_op)
calculate(no->left);
if (no->right->is_op)
calculate(no->right);
// imprime a operação que está sendo feita
cout << no->left->value.number << no->value.op << no->right->value.number;
// atribui o numero à operação, abaixa a flag e imprime o resultado ao lado da operação
no->value.number = operation(no->value.op, no->left->value.number, no->right->value.number);
no->is_op = false;
cout << " = " << no->value.number;
cout << '\n';
}
free(no->right);
no->right = NULL;
free(no->left);
no->left = NULL;
return no;
}
char *read(char *s)
{
int size = 0, i = 0;
int ch, base = 5;
while (ch != '\n')
{
ch = getc(stdin);
if (size <= i)
{
size += base;
s = (char *)realloc(s, size);
}
s[i] = ch;
i++;
}
return s;
}