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(); //마지막 연산 결과는 스택에 } |