대학교 과제로 Java를 이용해 간단한 사칙연산을 계산하는 프로그램을 개발했습니다. Infix(중위표기법)로 수식을 입력받아 Postfix(후위표기법)로 변환 후, 계산 결과를 출력하는 프로그램입니다.
import java.util.EmptyStackException;
import java.util.Scanner;
public class MyCalculator {
MyStack mySt;
String[] postfix;
boolean isError;
public MyCalculator(int arrLen){
mySt = new MyStack();
postfix = new String[arrLen];
isError = false;
}
public int getPriority(String ch){
//연산자의 우선순위를 반환해주는 함수
//+, -는 1, *, /는 2를 반환.
int answer=0;
if(ch.equals("+") || ch.equals("-"))
answer=1;
if(ch.equals("*") || ch.equals("/"))
answer=2;
return answer;
}
public void setPostfixLength(){
//변환한 postfix가 저장된 배열의 길이를 경우에 따라 조정하는 함수
int idx=0;
while(idx != postfix.length && postfix[idx] != null)
idx++;
if(postfix.length != idx){
String[] newPostfix = new String[idx];
System.arraycopy(postfix, 0, newPostfix, 0, idx);
postfix = newPostfix;
}
}
public void printPostfix(){
//후위표기법으로 변환한 결과를 출력하는 함수
int idx=0;
System.out.print("후위표기법 변환결과: ");
for(int i=0;i<postfix.length;i++)
System.out.print(postfix[i]+" ");
System.out.println();
}
public void printWrongExp(){
postfix[0] = "잘못된 수식입니다.";
isError = true;
for(int j=1;j<postfix.length;j++)
postfix[j]=null;
setPostfixLength();
}
public boolean isOperator(String exp){
//입력받은 exp 문자열이 연산자(+, -, *, /)라면 true 리턴
if(exp.equals("+") || exp.equals("-") ||
exp.equals("*") || exp.equals("/")){
return true;
}
else
return false;
}
public double simpleCalc(double n1, double n2, String operator){
//입력받은 n1, n2를 operator에 맞게 계산해주는 함수
double result = 0.0;
if(operator.equals("+"))
result = n1 + n2;
else if(operator.equals("-"))
result = n1 - n2;
else if(operator.equals("*"))
result = n1 * n2;
else
result = n1 / n2;
return result;
}
public void infix2Postfix(String[] infix) {
int idx=0;
if(isOperator(infix[0])) //수식의 첫 글자가 연산자인 경우
printWrongExp(); //에러 출력
for(int i=0;i<infix.length;i++){
if(Character.isDigit(infix[i].charAt(0))){ //숫자인 경우, postfix 배열에 추가
if(i!=0 && Character.isDigit(infix[i-1].charAt(0))){
printWrongExp();
return;
}
postfix[idx++] = infix[i];
}
else if(isOperator(infix[i])){ //연산자인 경우,
if(i==0 || isOperator(infix[i-1])){ //연산자를 중복하여 입력한 경우
printWrongExp(); //에러 출력
return;
}
else if(mySt.isStrStackEmpty()) //연산자 스택이 비어있는 경우,
mySt.push(infix[i]); //스택에 push
else{
if(getPriority(mySt.strPeek()) < getPriority(infix[i])){
mySt.push(infix[i]);
//현재 스택의 top이 위치한 연산자와 입력받은 연산자의 우선순위를 비교
//입력받은 연산자의 우선순위가 더 크다면 그냥 스택에 push
}
else{
postfix[idx++] = mySt.strPop();
mySt.push(infix[i]);
//그렇지 않다면, 스택에 있는 연산자를 pop하여 postfix 배열에 넣고
//입력받은 연산자를 push
}
}
}
else if(infix[i].equals("(")) {
mySt.push(infix[i]);
} //여는 괄호인 경우, 연산자 스택에 push
else if(infix[i].equals(")")){
//닫는 괄호인 경우,
try {
while (!mySt.strPeek().equals("(")) {
postfix[idx++] = mySt.strPop();
} //여는 괄호가 나올때까지, pop하여 postfix 배열에 넣음.
mySt.strPop(); //스택에 있는 여는 괄호도 pop함.
}
catch (ArrayIndexOutOfBoundsException e) {
printWrongExp();
return;
//만약, 여는 괄호 개수보다 닫는 괄호가 많다면 에러 출력
}
}
else{
printWrongExp();
return;
//Operand, Operator 간의 띄어쓰기를 제대로 안하거나
//잘못된 입력을 했을 경우, 에러 출력
}
}
while(!mySt.isStrStackEmpty()){
postfix[idx++] = mySt.strPop();
} //스택에 남아있는 연산자를 postfix 배열에 추가
setPostfixLength(); //변환된 후위표기식에 맞는 길이로 배열 크기 변환
for(int i=0;i<postfix.length;i++){
if(postfix[i].equals("(")){
printWrongExp();
return;
}
}
//만약, 변환 완료된 후위표기식에 "("가 있다면 에러 출력
}
public void calculatePostfix(){
int result;
for(int i=0;i<postfix.length;i++){
if(Character.isDigit(postfix[i].charAt(0))){
mySt.push(Double.parseDouble(postfix[i]));
} //숫자라면 number stack에 push
else if(isOperator(postfix[i])){
double num2 = mySt.intPop();
double num1 = mySt.intPop();
double temp_result=simpleCalc(num1, num2, postfix[i]);
mySt.push(temp_result);
} //만약 연산자라면 number stack에서 2번 pop해서
//해당 연산자와 계산하고 그 결과값을 push
}
System.out.println("계산결과: "+String.format("%.3f", mySt.intPeek()));
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("========= 계산기 =========");
System.out.println("*주의*, 수식은 각각 띄어쓰기 해야합니다.");
System.out.println("예시: 1 * ( 2 + 3 )");
System.out.println("=========================");
System.out.print("수식을 입력하세요: ");
String exp = scanner.nextLine();
String[] infix = exp.split(" ");
MyCalculator MyCal = new MyCalculator(infix.length);
MyCal.infix2Postfix(infix);
MyCal.printPostfix();
if(!MyCal.isError)
MyCal.calculatePostfix();
}
}
class MyStack {
int num_top, str_top;
String[] str_data;
double[] num_data;
public MyStack(){
this.num_top = 0;
this.str_top = 0;
str_data = new String[30];
num_data = new double[30];
}
public void push(String data){
this.str_data[str_top++] = data;
}
public void push(double data){
this.num_data[num_top++] = data;
}
public String strPop(){
if(str_top == 0)
throw new EmptyStackException();
String answer = str_data[--str_top];
return answer;
}
public double intPop(){
if(num_top == 0)
throw new EmptyStackException();
double answer = num_data[--num_top];
return answer;
}
public String strPeek(){
return this.str_data[str_top-1];
}
public double intPeek(){
return this.num_data[num_top-1];
}
public boolean isStrStackEmpty(){
if(str_top == 0)
return true;
else
return false;
}
public boolean isIntStackEmpty(){
if(num_top == 0)
return true;
else
return false;
}
}
'Development' 카테고리의 다른 글
[프로그래머스] 주식가격 (0) | 2021.05.16 |
---|---|
[프로그래머스] 기능개발 (0) | 2021.05.16 |
대학교 채용공지 크롤링 서비스 개발 (0) | 2021.03.21 |
"버스 vs 지하철" 개발일지 - 1 (0) | 2021.01.19 |
BOJ 11650 (좌표 정렬하기) (0) | 2021.01.16 |