일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 독립기념관
- 추천
- C++
- 산책하기 좋은 곳
- 파이썬
- 표준 라이브러리 함수
- 소켓 통신
- 실습으로 다지는 c#
- 캡슐화
- 강의
- 충남 천안
- 표준 입출력
- 실습
- 동영상
- 프로젝트
- c언어
- 졸업 작품 소재
- Windows Forms
- 유튜브 동영상 강의
- 알고리즘
- 언제나 휴일
- 언제나휴일
- 안드로이드 앱 개발
- 무료 동영상 강의
- 소스 코드
- c#
- 동영상 강의
- 클래스 다이어그램
- 네트워크 프로그래밍
- 원격 제어 프로그램
Archives
- Today
- Total
프로그래밍 언어 및 기술 [언제나휴일]
파서 트리를 이용한 계산기 [C++] 본문
안녕하세요. 언제나 휴일에 언휴예요.
이번에는 파서 트리를 이용한 계산기를 구현하는 실습이예요.
23+8*9-7 과 같은 수식을 계산하면 8*9를 먼저 계산하고 23+(8*9)-7 순으로 계산합니다.
이처럼 수식을 연산자 우선 순위에 맞게 계산하기 위해 여기에서는 파서 트리를 이용할 거예요.
파서 트리를 이용한 계산기에 관한 이론적인 내용은 자료구조와 알고리즘 C++ 9.3 수식 파서 트리를 참고하세요.
#include
#include
using namespace std;
class Calculator
{
string expr;
public:
Calculator(string expr)
{
this->expr = expr;
tcnt = 0;
}
void Run()
{
cout<<expr<<"을 계산합니다. ..."<<endl;
if(Lexical())
{
if(Syntax())
{
Parsing();
PostOrderView();
cout<<expr<<"="<<Calculate()<<endl;
}
else
{
cout<<"수식에 사용한 표현이 문법에 맞지 않습니다."<<endl;
}
}
else
{
cout<<"사용할 수 없는 기호가 있습니다."<<endl;
}
cout<<endl;
}
private:
bool Lexical()
{
int i = 0;
while(expr[i])
{
if(IsOperator(expr[i]))
{
i = MakeOperator(i);
}
else
{
if(IsDigit(expr[i]))
{
i = MakeOperand(i);
}
else
{
return false;
}
}
}
return true;
}
bool IsOperator(char ch)
{
return (ch =='+')||(ch=='-')||(ch=='*')||(ch=='/');
}
bool IsDigit(char ch)
{
return (ch>='0')&&(ch<='9');
}
struct Token
{
int priority;
virtual void View()=0;
bool MoreThanPriority(Token *token)
{
return priority>=token->priority;
}
};
struct Operator:public Token
{
char ch;
Operator(char ch)
{
this->ch = ch;
if((ch=='+')||(ch=='-'))
{
priority = 1;
}
else
{
priority = 2;
}
}
void View()
{
cout<<ch<<" ";
}
};
Token *tokens[100];
int tcnt;
int MakeOperator(int i)
{
tokens[tcnt] = new Operator(expr[i]);
tcnt++;
return i+1;
}
struct Operand:public Token
{
int value;
Operand(int value)
{
this->value = value;
priority = 3;
}
void View()
{
cout<<value<<" ";
}
};
int MakeOperand(int i)
{
int value = 0;
while(IsDigit(expr[i]))
{
value = value*10 + expr[i] - '0';
i++;
}
tokens[tcnt] = new Operand(value);
tcnt++;
return i;
}
bool Syntax()
{
if(tcnt%2==0)
{
return false;
}
if(tokens[0]->priority !=3)
{
return false;
}
for(int i = 1; i<tcnt; i+=2)
{
if(tokens[i]->priority==3)
{
return false;
}
if(tokens[i+1]->priority != 3)
{
return false;
}
}
return true;
}
struct ParserTree
{
struct Node
{
Token *token;
Node *lc;
Node *rc;
Node(Token *token)
{
this->token = token;
lc = rc = 0;
}
};
Node *root;
ParserTree(Token *token)
{
root = new Node(token);
}
void Add(Token *token)
{
Node *now = new Node(token);
Token *st = root->token;
if(st->MoreThanPriority(token))
{
now->lc = root;
root = now;
}
else
{
if(token->priority !=3)
{
now->lc = root->rc;
root->rc = now;
}
else
{
Node *pa = root;
while(pa->rc)
{
pa = pa->rc;
}
pa->rc = now;
}
}
}
void View()
{
PostOrder(root);
cout<<endl;
}
void PostOrder(Node *sr)
{
if(sr)
{
PostOrder(sr->lc);
PostOrder(sr->rc);
sr->token->View();
}
}
int Calculate()
{
return PostOrderCalculate(root);
}
int PostOrderCalculate(Node *sr)
{
if(sr->lc)
{
int lvalue = PostOrderCalculate(sr->lc);
int rvalue = PostOrderCalculate(sr->rc);
Operator *op = dynamic_cast(sr->token);
switch(op->ch)
{
case '+': return lvalue + rvalue;
case '-': return lvalue - rvalue;
case '*': return lvalue * rvalue;
case '/':
if(rvalue)
{
return lvalue / rvalue;
}
cout<<"divide zero error"<<endl;
return 0;
}
throw "정의하지 않은 연산자입니다.";
}
Operand *op = dynamic_cast(sr->token);
return op->value;
}
};
ParserTree *ps;
void Parsing()
{
ps = new ParserTree(tokens[0]);
for(int i = 1; i<tcnt;i++)
{
ps->Add(tokens[i]);
}
}
void PostOrderView()
{
ps->View();
}
int Calculate()
{
return ps->Calculate();
}
};
int main()
{
string tc_exprs[6]=
{
"2+3-5*5+6/2",
"23*5/2+4*6",
"2+4*5#6",
"2+3*5+",
"3+36+-7",
"45+3*5-2+5/2*7",
};
for(int i = 0; i<6; i++)
{
Calculator *cal = new Calculator(tc_exprs[i]);
cal->Run();
delete cal;
}
return 0;
}
언제나휴일 여행 및 산책
'C & C++ > C++ 예제 및 소스' 카테고리의 다른 글
[C언어 소스] 연결리스트를 이용하여 구현한 큐 (0) | 2025.01.09 |
---|---|
[C언어 소스] 부분 문자열 비교하는 함수 만들기 (0) | 2025.01.09 |
[C언어 소스] 문자열 길이를 계산하는 함수 만들기 (0) | 2025.01.08 |
Queue를 이용한 스케쥴러 시뮬레이션 [C++] (0) | 2025.01.08 |
함수 개체, 회원 및 회원 컬렉션 구현[C++] (0) | 2025.01.08 |
개체 출력자 실습 – 회원 클래스 및 쉬프트 연산자 중복 정의 [C++] (0) | 2025.01.08 |
다형성 실습 – 오케스트라, 음악가, 피아니스트, 드러머 [C++] (0) | 2025.01.08 |
상품과 할인 상품 – 상속 실습 [C++] (0) | 2025.01.08 |