-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathHW2_2018203055.cpp
More file actions
199 lines (183 loc) · 5.01 KB
/
HW2_2018203055.cpp
File metadata and controls
199 lines (183 loc) · 5.01 KB
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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// 김진구 2018203055
#include <iostream>
#include <stack>
using namespace std;
void read_and_evaluate(istream& ins);
void evaluate_stack(stack<double>& numbers, stack<char>& operations);
int main(void) {
double result;
while (true) {
cout << ">> ";
read_and_evaluate(cin); // 입력스트림이 인자이기 때문에
cin.ignore();
}
return 0;
}
void read_and_evaluate(istream& ins) {
const char DECIMAL = '.';
stack<double> numbers;
stack<char> operations;
double number;
char symbol;
bool first_input = true; // EOI가 입력되었을 때 EOI의 앞부분에 입력이 있는지 확인
while (ins && ins.peek() != '\n') {
if (ins.peek() == 'E' && first_input) {
ins.ignore();
if (ins.peek() == 'O') {
ins.ignore();
if (ins.peek() == 'I') {
ins.ignore();
if (ins.peek() == '\n') { // EOI의 뒷 부분에 다른 문자가 없는지 확인
cout << "프로그램을 종료합니다." << endl;
exit(1);
}
}
}
}
first_input = false;
if (isdigit(ins.peek()) || ins.peek() == DECIMAL) {
ins >> number;
numbers.push(number);
}
else if (strchr("+-*/", ins.peek()) != NULL) {
while (!operations.empty()) {
if (strchr("+-", ins.peek()) != NULL && strchr("([{", operations.top()) == NULL) {
// 연산 우선순위에 따라 operations에 이미 값이 있다면 왼쪽괄호가 아닐경우 스택안의 값을 연산
evaluate_stack(numbers, operations);
}
else {
// */일 경우 */ 라면 스택안의 값을 연산
if (strchr("*/", operations.top()) != NULL) {
evaluate_stack(numbers, operations);
}
// +-와 왼쪽 괄호일 경우 연산을 먼저하지 않는다.
else break;
}
}
ins >> symbol;
operations.push(symbol);
}
else if (strchr("([{", ins.peek()) != NULL) { // 왼쪽 괄호는 무조건 push
ins >> symbol;
operations.push(symbol);
}
else if (strchr(")]}", ins.peek()) != NULL) {
// 오른쪽괄호에서 왼쪽괄호가 나올 때 까지 혹은 operations가 비어있지 않을 때까지 연산한다
ins >> symbol;
while (!operations.empty() && strchr("([{", operations.top()) == NULL) {
evaluate_stack(numbers, operations);
}
if (!operations.empty()) {
// 맞는 괄호가 오게 되면 pop하고 다른 괄호가 오면
// 에러메세지를 출력하고 오류로 인식하기 위해 값을 비워준다.
switch (operations.top())
{
case '(':
if (symbol == ')')
operations.pop();
else {
cout << "Error!: unbalanced parentheses" << endl;
while (!numbers.empty())
numbers.pop();
while (!operations.empty())
operations.pop();
while (ins.peek() != '\n')
ins.ignore();
}
break;
case '[':
if (symbol == ']')
operations.pop();
else {
cout << "Error!: unbalanced parentheses" << endl;
while (!numbers.empty())
numbers.pop();
while (!operations.empty())
operations.pop();
while (ins.peek() != '\n')
ins.ignore();
}
break;
case '{':
if (symbol == '}')
operations.pop();
else {
cout << "Error!: unbalanced parentheses" << endl;
while (!numbers.empty())
numbers.pop();
while (!operations.empty())
operations.pop();
while (ins.peek() != '\n')
ins.ignore();
}
break;
}
}
else {
// 끝까지 연산을 하였는데도 왼쪽괄호가 나오지 않는 경우
// 에러메세지를 출력하고 오류로 인식하기 위해 값을 비워준다.
cout << "Error!: unbalanced parentheses" << endl;
while (!numbers.empty())
numbers.pop();
while (!operations.empty())
operations.pop();
while (ins.peek() != '\n')
ins.ignore();
}
}
else {
ins.ignore();
}
}
while (!operations.empty()) {
if (strchr("([{", operations.top()) != NULL) {
// 왼쪽 괄호만 남아있는 경우 에러 메세지를 출력하고 오류로 인식하기 위해 값을 비워준다
cout << "Error!: unbalanced parentheses" << endl;
while (!numbers.empty())
numbers.pop();
while (!operations.empty())
operations.pop();
while (ins.peek() != '\n')
ins.ignore();
}
else {
// 사칙연산 기호가 남아있다면 비어있을 때 까지 연산한다
evaluate_stack(numbers, operations);
}
}
if (!numbers.empty()) {
// 오류로 인식되어 값이 비어 있지 않다면 결과를 출력한다
cout << numbers.top() << endl;
}
}
void evaluate_stack(stack<double>& numbers, stack<char>& operations) {
// numbers 스택에 값이 2개이상 존재하지 않으면 연산이 이루어지지 않으므로
// operations 스택을 비워주고 함수에서 나간다
if (numbers.size() < 2) {
while (!operations.empty())
operations.pop();
return;
}
double operand1, operand2;
operand2 = numbers.top();
numbers.pop();
operand1 = numbers.top();
numbers.pop();
switch (operations.top()) { // 기호에 따라 사칙연산을 진행한다.
case '+': numbers.push(operand1 + operand2); break;
case '-': numbers.push(operand1 - operand2); break;
case '*': numbers.push(operand1 * operand2); break;
case '/':
if (operand2 == 0) {
// 0으로 나누는 경우 에러메세지를 출력하고 오류로 인식하기 위해 값을 비워준다.
cout << "Error!: divide by zero" << endl;
while (!numbers.empty())
numbers.pop();
}
else {
numbers.push(operand1 / operand2);
}
break;
}
operations.pop();
}