티스토리 뷰
[계산기 처리 과정]
- 중위표기법 수식 → ConvToRPNExp 함수(후위표기법으로 변환) → EvalRPNExp 함수(후위표기법 계산) → 연산 결과
[소스 코딩]
※ 스택은 이전에 '연결 리스트 기반으로 구현된 스택' 소스를 활용
※ 후위표기법으로 변환 처리는 이전에 'InfixToPostfix' 소스를 활용
※ 후위표기법 계산 처리는 이전에 'PostCalculator' 소스를 활용
■ ListBaseStack.h
#ifndef __LB_STACK_H__ #define __LB_STACK_H__ #define TRUE 1 #define FALSE 0 typedef int Data; // 사용자 정의 int형 Data 선언 typedef struct _node // 사용자 정의 구조체 'Node' 정의 { Data data; // 입력 받은 데이터를 저장할 data 선언 struct _node * next; // 다음 노드를 가리킬 노드 포인터 next 선언 } Node; typedef struct _listStack // 사용자 정의 구조체 'ListStack' 정의 { Node * head; // ListStack에 노드 포인터 'head' 선언 } ListStack; typedef ListStack Stack; // ListStack 이름을 'Stack'으로 변경 void StackInit(Stack * pstack); // 스택을 초기화 하는 함수 int SIsEmpty(Stack * pstack); // 스택에 데이터가 비어있는지 확인하는 함수 void SPush(Stack * pstack, Data data); // 스택에 데이터를 삽입하는 함수 Data SPop(Stack * pstack); // 스택에서 데이터를 추출하는 함수 Data SPeek(Stack * pstack); // 스택의 데이터를 확인하는 함수 #endif | cs |
■ ListBaseStack.c
#include <stdio.h> #include <stdlib.h> #include "ListBaseStack.h" // 스택을 초기화 하는 함수 // void StackInit(Stack * pstack) { pstack->head = NULL; } // 스택에 데이터가 비어있는지 확인하는 함수 // int SIsEmpty(Stack * pstack) { if(pstack->head == NULL) return TRUE; else return FALSE; } // 스택에 데이터를 삽입하는 함수 // void SPush(Stack * pstack, Data data) { Node * newNode = (Node*)malloc(sizeof(Node)); newNode->data = data; newNode->next = pstack->head; pstack->head = newNode; } // 스택에서 데이터를 추출하는 함수 // Data SPop(Stack * pstack) { Data rdata; Node * rnode; if(SIsEmpty(pstack)) { printf("Stack Memory Error!"); exit(-1); } rdata = pstack->head->data; rnode = pstack->head; pstack->head = pstack->head->next; free(rnode); return rdata; } // 스택의 데이터를 확인하는 함수 // Data SPeek(Stack * pstack) { if(SIsEmpty(pstack)) { printf("Stack Memory Error!"); exit(-1); } return pstack->head->data; } | cs |
■ InfixToPostfix.h
#ifndef __INFIX_TO_POSTFIX_H__ #define __INFIX_TO_POSTFIX_H__ // 사용자에게 입력 받은 중위표기법 수식을 후위표기법 수식으로 변경하는 함수 // void ConvToRPNExp(char exp[]); #endif | cs |
■ InfixToPostfix.c
#include <string.h> // malloc, strlen, strcpy 함수를 사용하기 위함 #include <stdlib.h> // malloc, memset 함수를 사용하기 위함 #include <ctype.h> // isdigit 함수를 사용하기 위함 #include "ListBaseStack.h" // 연산자의 우선순위 정보를 반환해주는 함수 // int GetOpPrec(char op) { switch(op) { case '*': case '/': return 5; case '+': case '-': return 3; case '(': return 1; } return -1; } // 두 연산자의 우선순위를 비교하여 그 결과를 반환하는 함수 // int WhoPrecOp(char op1, char op2) { int op1Prec = GetOpPrec(op1); int op2Prec = GetOpPrec(op2); if(op1Prec > op2Prec) return 1; else if(op1Prec < op2Prec) return -1; else return 0; } // 사용자에게 입력 받은 중위표기법 수식을 후위표기법 수식으로 변경하는 함수 // void ConvToRPNExp(char exp[]) { Stack stack; int expLen = strlen(exp); char * convExp = (char*)malloc(expLen+1); int i, idx = 0; char tok, popOp; memset(convExp, 0, sizeof(char) * expLen+1); StackInit(&stack); for(i=0; i<expLen; i++) { tok = exp[i]; if(isdigit(tok)) { convExp[idx++] = tok; } else { switch(tok) { case '(': SPush(&stack, tok); break; case ')': while(1) { popOp = SPop(&stack); if(popOp == '(') break; convExp[idx++] = popOp; } break; case '+': case '-': case '*': case '/': while(!SIsEmpty(&stack) && WhoPrecOp(SPeek(&stack), tok) >= 0) convExp[idx++] = SPop(&stack); SPush(&stack, tok); break; } } } while(!SIsEmpty(&stack)) convExp[idx++] = SPop(&stack); strcpy(exp, convExp); free(convExp); } | cs |
■ PostCalculator.h
#ifndef POSTCALCULATOR_H_ #define POSTCALCULATOR_H_ // 후위표기법 수식을 계산하는 함수 // int EvalRPNExp(char exp[]); #endif | cs |
■ PostCalculator.c
#include <string.h> // strlen 함수를 사용하기 위함 #include <ctype.h> // isdigit 함수를 사용하기 위함 #include "ListBaseStack.h" // 후위표기법 수식을 계산하는 함수 // int EvalRPNExp(char exp[]) { Stack stack; int expLen = strlen(exp); int i; char tok, op1, op2; StackInit(&stack); for(i=0; i<expLen; i++) { tok = exp[i]; if(isdigit(tok)) { SPush(&stack, tok - '0'); } else { op2 = SPop(&stack); op1 = SPop(&stack); switch(tok) { case '+': SPush(&stack, op1 + op2); break; case '-': SPush(&stack, op1 - op2); break; case '*': SPush(&stack, op1 * op2); break; case '/': SPush(&stack, op1 / op2); break; } } } return SPop(&stack); } | cs |
■ InfixCalculator.h
#ifndef INFIXCALCULATOR_H_ #define INFIXCALCULATOR_H_ // '중위표기법→후위표기법 변환→연산'처리하는 함수 // int EvalInfixExp(char exp[]); #endif | cs |
■ InfixCalculator.c
#include <string.h> // strlen, strcpy 함수를 사용하기 위함 #include <stdlib.h> // malloc 함수를 사용하기 위함 #include "InfixToPostfix.h" #include "PostCalculator.h" // '중위표기법→후위표기법 변환→연산'처리하는 함수 // int EvalInfixExp(char exp[]) { int len = strlen(exp); int ret; char * expcpy = (char*)malloc(len+1); strcpy(expcpy, exp); ConvToRPNExp(expcpy); ret = EvalRPNExp(expcpy); free(expcpy); return ret; } | cs |
■ 사용되는 함수 설명
int len = strlen(exp); int ret; char * expcpy = (char*)malloc(len+1); strcpy(expcpy, exp); | cs |
- 'len'에 'exp 배열 인자의 길이'만큼 저장
- 변수 ret 선언
※ 최종 결과 값을 저장할 공간
- 문자형 포인터 변수 'expcpy'에 'len+1 길이'만큼 메모리 공간 생성(동적 메모리 할당)
※ 변환된 수식을 담을 공간. 호출된 exp 값을 건드리지 않게 임시 공간을 사용
- exp에 저장된 값을 expcpy에 복사
※ strcpy 함수: 오른쪽 인자에 저장된 값을 왼쪽 인자에 복사
ConvToRPNExp(expcpy); ret = EvalRPNExp(expcpy); free(expcpy); return ret; | cs |
- 'expcpy'에 저장된 중위표기법 수식을 후위표기법으로 변환
- 'ret'에 'expcpy'수식의 계산된 결과를 저장
- 'expcpy' 메모리 공간 제거
- 'ret'에 저장된 값을 반환
■ InfixCalculatorMain.c
#include <stdio.h> #include "InfixCalculator.h" int main(void) { char exp1[] = "8-6/3*2"; char exp2[] = "(2+6)/2+1"; char exp3[] = "((5+4)/3)*(3-1)"; printf("%s = %d \n", exp1, EvalInfixExp(exp1)); printf("%s = %d \n", exp2, EvalInfixExp(exp2)); printf("%s = %d \n", exp3, EvalInfixExp(exp3)); return 0; } | cs |
- 문자형 배열 'exp1'에 '8-6/3*2' 수식을 저장
- 문자형 배열 'exp2'에 '(2+6)/2+1' 수식을 저장
- 문자형 배열 'exp3'에 '((5+4)/3)*(3-1)' 수식을 저장
- 배열 'exp1, exp2, exp3'을 후위표기법 수식으로 변환, 계산, 출력
■ 실행결과
'자료구조' 카테고리의 다른 글
[ch 07-2] 큐의 배열 기반 구현_1(데이터 저장/반환, 원형 큐 개념) (2) | 2016.04.08 |
---|---|
[ch 07-1] 큐의 이해와 ADT 정의 (0) | 2016.04.07 |
[ch 06-4] 계산기 프로그램 구현_4(후위표기법 수식 계산 구현) (0) | 2016.04.06 |
[ch 06-4] 계산기 프로그램 구현_3(후위표기법 수식 계산 개념) (0) | 2016.04.06 |
[ch 06-4] 계산기 프로그램 구현_2(중위표기법->후위표기법 변환 구현) (3) | 2016.04.06 |
- Total
- Today
- Yesterday
- tdataset
- System
- 독해
- java
- 문법
- 일기
- wfd
- SysUtils
- 말하기
- 작문
- Reference
- 여행영어 100일의 기적
- 정렬
- 자료구조
- 상황
- 스택
- 대상
- 설명
- RA
- 계산기
- VCL
- 알고리즘
- 응용
- ADODB
- Delphi
- SWT
- 영어
- 교육센터
- 왕초보 영어회화 100일의 기적
- Pte
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |