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
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
#include <stdio.h>
#include <stdlib.h>
#include <iostream> //c++에서 파일 입력 출력을 할수있게 한다
#include <math.h> //수학 연산함수 포함하는 헤더
 
using namespace std; //c++에서 쓰는이름공간
 
#define MAX 100 //스택의 최대 사이즈
#define RD(X) (X)*M_PI/180 //삼각 함수 구하는 공식
#define M_PI 3.141592
 
typedef enum {SIN, COS, TAN};
 
int stack[MAX]; //전역변수 stack[] 선언
int stack_top;  //전역변수 stack_top 선언
 
void init_stack(void); //스택의 초기화 함수
char push(char t); //스택의 맨위에 자료 요소를 삽입한다
char pop(void); // 스택의 맨 위에 있는 자료 요소를 꺼낸다
int get_stack_top(void); // 스택의 top값을 얻어오는 함수
int is_stack_empty(void); // 스택이 비었는지 아닌지 확인한다
double precedence(int op); //수식 선행자와 연산자 사이를 확인한다
int is_pos(char *postfix); //후위식을 표현한다
void postfix(char *dst, char *src); //후위식을 불러오는 함수
double cal(char *post); //계산기 후위식의 표현
double is_operator(int op); //수식 연산자를 선언한다
bool is_numbers(char *op); // 소수점 리턴하는 함수
bool is_parenthesis(char *op); //괄호 리턴하는 함수
void token(char input[]); //토큰을 분리하는 함수
 
void main(int) //메인함수
{
    double result=0; //수식결과값
    char exp[256]; //문자열로 exp와 infix의 크기 선정
    char input[100]; //입력값의 크기를 잡아준다
     
    cout<<"//======================================//"<<endl;
    cout<<"//           계산기                     //"<<endl;
    cout<<"//           알파벳p눌렀을시에 강제종료 //"<<endl<<endl<<endl;; //수식을 입력한다
    cout<<"//======================================//"<<endl;
     
    while(1) //무한 루프
    {
        if(input[0]=='p') break; //강제종료
 
        cout<<"//===============================//"<<endl;
        cout<<"//           수식입력            //"<<endl;
        cout<<"//           수식을 입력하시오   //"<<endl; //수식을 입력한다
        cin>>input; //수식 입력
         
        cout<<"//===============================//"<<endl;
        cout<<"//           토큰출력            //"<<endl;
        cout<<"//===============================//"<<endl; //토큰출력하는 곳
        token(input); //토큰분리하는 함수
         
        postfix(exp, input); //후위식 함수를 호출한다
        cout<<"//===============================//"<<endl;
        cout<<"//           후위식출력          //"<<endl;
        cout<<"//===============================//"<<endl; //후위식출력하는 곳
        cout<<"Postfix :"<<exp<<endl; //후위식을 콘솔창에 표현한다
         
        if(!is_pos(exp)) //후위식 표현
        {
            cout<<"수식이 틀렸습니다"<<endl; //식의 조건에 맞지않는 문자가 들어가면 틀렸다고 알려준다
            continue; // while 조건문으로 다시 되돌려준다
        }
         
        result = cal(exp);  // 계산결과값 후위식 함수 호출
        cout<<"//=================================//"<<endl;
        cout<<"//             결과값              //"<<endl; //결과값 출력하는곳
        cout<<"//=================================//"<<endl;
        cout<<"결과값 :   "<<result<<endl;  //결과값을 저장하고 나타낸다
        cout<<endl; //줄 띠우기
    }
}
 
void token(char input[]) //토큰분리하는 함수
{
    int len = strlen(input);         //input 입력받는거
     
    for(int i=0 ; i<len ; i++)       //입력한 input 끝까지 반복
    {
        if(((int)input[i]-'0'>=0 && (int)input[i+1]-'0'>=0) ||
            ((int)input[i]-'0'>=0 && input[i+1]=='.') || (input[i]=='.' && (int)input[i+1]-'0'>=0))
        {  
            cout << input[i];
            continue;  
        }
        else if((int)input[i]-'0'>=0 && (int)input[i+1]-'0'<0)
        {  
            cout << input[i] << endl;
        }
        else if((int)input[i]-'0'<0)
        {  
            cout << input[i] << endl;
        }
         
    } //input한 값만큼 0을 빼서 그보다 크거나 같거나 작을때 일일히 하나씩 때어내서 출력한다
}
 
void init_stack(void) // 스택 초기화
{
    stack_top = -1;
}
 
char push(char t) //push 함수
{
    if (stack_top >= MAX - 1) //스택탑이 맥스에서1을 뺸거보다 크거나 같을때
    {
        cout<<"스택에서 오버플로우"<<endl; // 에러났을때
        exit(1); //프로그램 종료
    }
    stack[++stack_top] = t; //아닐경우 스택탑을 증가시킨다
    return t; //다시 리턴
}
 
char pop(void) //pop 함수
{
    if (stack_top < 0) //스택탑이 0보다 작을때
    {
        cout<<"스택에서 오버플로우"<<endl;   // 에러났을때
        exit(1); //프로그램 종료
    }
    return stack[stack_top--]; //감소를 리턴한다
}
 
int get_stack_top(void//스택의 top값을 리턴한다
{
    return (stack_top < 0) ? -1 : stack[stack_top]; //-1이랑 스택탑이랑 비교해서 작은수를 스택탑에 넣고 리턴한다
}
 
int is_stack_empty(void) // 스택이 비었는지 아닌지 확인한다
{
    return (stack_top < 0); //비었으면 스택탑을 0보다 작은값으로 리턴한다
}
 
double is_operator(int op)  // 연산자 리턴하는 함수
{
    return (op == '+' || op == '-' || op == '*' || op == '/'); //연산자 리턴
}
 
bool is_parenthesis(char op)  // 괄호 리턴하는 함수
{
    if(op == '(' || op == ')') return true; //괄호 리턴
     
    return false; //괄호리턴이 안되면 false 실행
}
 
bool is_numbers(char *op)  //소수점 리턴하는 함수
{
    int len = strlen(op); //문자열을 인수로 전달받아 준자열이 길이를 반환해 준다
     
    for(int i = 0; i < len; i++)
    {
        if(op[i] >= '0' && op[i] <= '9')
            continue;
        else if(op[i] == '.') continue;
        else return false;
    }
    return true;
}
 
double precedence(int op)  //연산자의 우선순위 변환
{
    switch(op)
    {
    case'*':
        return 5;  //곱하기연산
    case '/':
        return 5; //나누기 연산
    case '+':
        return 4; //더하기 연산
    case '-':
        return 4; //빼기 연산
    case 's':
        return SIN;
    case 'c':  
        return COS;
    case 't':
        return TAN;
    }
    return 0; //리턴
}
 
int is_pos(char *postfix)   //후위식을 표현한다
{
    int result = 0; //결과값 초기화
    while (*postfix) // 후위식포인터 반복문
    {
        while (*postfix == ' ')     //후위식표현할때 공간을 띄운다
            postfix++; //후위식을 증가시킨다
        if (is_operator(*postfix)) //만약에 연산자에 후위식이 들어갔을때
            result--; //결과값은 감소한다
        else //만약에 들어가지 않았을때
        {
            result++; //결과값 증가한다
            while (*postfix != ' '//후위식표현할때 공간을 띄운다
                postfix++; //후위식을 증가시킨다
        }
        if (result < 1) break; //만약에 결과값이 1보다 작을때
        postfix++; //후위식 증가
    }
    return (result == 1); //결과값이 1일때 리턴한다
}
 
void postfix(char *dst, char *src)   //전위식을 후위식으로 바꾸면서 표현한다
{
    init_stack(); //스택에서 초기화한다
    while (*src)
    {
        if (*src == '('//(를 만나면
        {
            push(*src); //스택에 push
            src++; //증가
        }
        else if (*src == ')') //)를 만나면 스택나올때까지 pop
        {
            while (get_stack_top() != '(') //최상위스택값을 얻지못했을때 (를 초훌
            {
                *dst++ = pop(); //스택에 pop
                *dst++ = ' '; //공간띠움
            }
            pop(); //pop호출
            src++; //증가
            if ((get_stack_top() == 's') || (get_stack_top() == 'c') || (get_stack_top() == 't') )
            { // 괄호가 끝이난후 삼각함수의 연산자가 들어 있는지 검사
                *dst++ = pop(); // true일경우 팝
                *dst++ = ' ';
            }
            else;
        }
        else if (is_operator(*src)) //연산자일때
        {
            if ((get_stack_top() == 's') || (get_stack_top() == 'c') || (get_stack_top() == 't') )
            {// 스택의 탑이 삼각함수인지 검사. 이유 괄호다음의 우선순위는 삼각함수이다.
                *dst++ = pop();
                *dst++ = ' ';
            }
            while (!is_stack_empty() && precedence(get_stack_top()) >= precedence(*src))
            {                       //그 자체보다 더 높은 우선순위 팝을 나타낸다
                *dst++ = pop();//스택에 pop
                *dst++ = ' ';//공간띠움
            }
            push(*src);//스택에 push
            src++;//증가
        }
        else if (*src >= '0' && *src <= '9') //피연산자는 그냥 출력
        {
            do
            {
                *dst++ = *src++; //숫자는 그냥 증가
            }
            while (*src >= '0' && *src <= '9' &&  *src == '.');
            *dst++ = ' ';
        }
        else if ( *src == '.' )
            *dst++ = *src++;
        else if ( *src == 's' ) // sin을 만날경우 첫문자가 's'임으로 검사
        {
            push(*src);
            src = src+3; // sin글씨 세게의 다음으로 이동
        }
        else if ( *src == 'c' )
        {
            push(*src);
            src = src+3;
        }
        else if ( *src == 't' )
        {
            push(*src);
            src = src+3;
        }
        else
            src++;
    }
    while (!is_stack_empty())   //모두 끝났으면 스택에 있는
    {
        *dst++ = pop(); //모든 내용을 pop
        *dst++ = ' ';
    }
    dst--;
    *dst = '\0';
}
 
double cal(char *post)   //계산기의 후위식표현
{
    int i;
    init_stack(); //스택 초기화
    while (*post)
    {
        if (*post >= '0' && *post <= '9') //숫자로된 문자열 호출
        {
            i = 0;
            do
            {
                i = i * 10 + *post - '0'; //숫자로 된 문자열을 숫자로 변환
                post++; //하나씩 증가
            }
            while (*post >= '0' && *post <= '9'); //피연산자 호출
            push(i); //피연산자는 스택에 push
        }
        else if (*post == '+') //연산자를 만나면
        {
            push(pop() + pop());//스택에서 pop하여 push
            post++;
        }
        else if (*post == '*') //연산자를 만나면
        {
            push(pop() * pop()); //스택에서 pop하여 push
            post++;
        }
        else if (*post == '-') //교환법칙이 성립하지 않는다
        {
            i = pop();
            push(pop() - i);
            post++;
        }
        else if (*post == '/'//교환법칙이 성립하지 않는다
        {
            i = pop();
            push(pop() / i);
            post++;
        }
        else if ( (*post == SIN) || (*post == COS) || (*post == TAN) )
        {
            *post = pop();//맨위의 숫자를 연산한다.
            switch (i) // 삼각함수 연산시
            {
            case SIN
                : push(sin(RD(i)));
                break;
            case COS
                : push(cos(RD(i)));
                break;
            case TAN
                : push(tan(RD(i)));
                break;
            }
        }
        else
            post++;
    }
    return pop();  //마지막 연산 결과는 스택에
}

'Study > C++' 카테고리의 다른 글

볼링게임  (0) 2011.09.29
스택과 큐  (0) 2011.09.29
퍼즐게임  (0) 2011.09.29
tic tac toe 게임  (0) 2011.09.29
지뢰 찾기  (0) 2011.09.29
Posted by 코딩하는 야구쟁이
,