javascript 로 짜기 전에 만든 java version의 공학용 계산기다.
본래 jsp 파일을 view 로 만들고, java에서 controller&service&dto 등 mvc 패턴을 적용하여 만들려고 하였으나...
피드백 주신 사수 분이 javascript 를 배워야한다고 말씀하시어... 중간에 유기된 프로젝트... 미안하다...
괄호에 대한 사칙연산의 후위식 계산을 포함하며, 삼각함수-괄호에 대한 오류 처리 등 세부 기능은 전무하다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.StringTokenizer;
import org.springframework.stereotype.Controller;
@Controller
public class MainController {
public static void main(String[] args) throws IOException{
// BufferedReader 로 문자열을 자유롭게 삽입
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String input = br.readLine();
br.close();
// StringTokenizer을 통해 공백에 따라 문자열 자르기
StringTokenizer str = new StringTokenizer(input, " ");
System.out.println("(1) 입력값 stringtokenizer : " + str + "\n");
// 각 요소 삽입을 위한 배열 생성
List<String> arr = new ArrayList<String>();
// 저장 배열
ArrayList<String> arrSplit = new ArrayList<>();
// 연산자 stack
Stack<String> stackOp = new Stack<>();
// 계산 stack
Stack<String> stackCal = new Stack<>();
// 공백이 없을 때 까지 배열에 넣기 반복
while(str.hasMoreElements()) {
arr.add(str.nextToken());
}
System.out.println("(2) arr 배열값 : " + arr + "\n");
// stack 에서 arr로 넘어간 후로 error 발생
// 괄호 이후에 * 이 안 넘어감
for(int i=0; i < arr.size(); i++) {
classifi(arr, arrSplit, i, stackOp);
System.out.println("[classifi " + i + "]" + arrSplit);
System.out.println("[classifi " + i + "]" + stackOp);
if(arr.get(i).equals(")")) {
int j = 0;
// stackOp to arrSplit 연산자 이동
stackToArr(arr, arrSplit, j, stackOp);
System.out.println("\n" + "[stack >>> " + "]" + stackOp);
System.out.println("[>>> Arr " + "]" + arrSplit + "\n");
}
}
System.out.println("(3-1) arrSplit 배열 : " + arrSplit);
System.out.println(" stackOp 스택 : " + stackOp + "\n");
// 계산식 parsing 완료 후 stack의 모든 연산자를 배열에 저장
while(true) {
for(int i=0; i < stackOp.size(); i++) {
arrSplit.add(stackOp.get(stackOp.size() - 1));
stackOp.pop();
}
if(stackOp.isEmpty()) {
break;
}
}
System.out.println("(3-2) arrSplit 배열 : " + arrSplit);
System.out.println(" stackOp 스택 : " + stackOp + "\n");
// 후위식 배열에서 순서대로 숫자를 꺼내, 연산자가 나올 때까지 stackCal에 저장
moveCal(arrSplit, stackCal);
System.out.println("(3-3) arrSplit 배열 : " + arrSplit);
System.out.println(" stackCal 스택 : " + stackCal + "\n");
// 계산 값을 옮기는 가운데 임시 저장 목적의 메신져 변수 result.
int result = 0;
String rst = "";
// distinction(arrSplit)
// arrSplit 과 stackCal 사이의 계산
while(true) {
// arrSplit 배열의 index(0) 이 연산자면 stackCal 의 요소와
// 연동하여 계산 후, stackCal 에 add 한다.
if (distinction(arrSplit)) {
// stackCal 의 마지막 요소 및 끝에서 2번째 요소를 빼내고, 계산하기 위해
// int 로 type 변환
int numSec = Integer.parseInt(stackCal.get(stackCal.size() - 1));
stackCal.pop();
int numFir = Integer.parseInt(stackCal.get(stackCal.size() - 1));
stackCal.pop();
switch (arrSplit.get(0)) {
case "+":
result = numFir + numSec;
arrSplit.remove(0);
break;
case "-":
result = numFir - numSec;
arrSplit.remove(0);
break;
case "*":
result = numFir * numSec;
arrSplit.remove(0);
break;
case "/":
result = numFir / numSec;
arrSplit.remove(0);
break;
}
// stackCal에 저장하기 위해 계산 결과인 rst를 String을 type 변환
rst = Integer.toString(result);
// 결과 값을 stackCal에 add
stackCal.add(rst);
if(arrSplit.isEmpty()) {
stackCal.pop();
break;
}
}
// arrSplit 배열에 숫자가 남아 있을 경우 stackCal 에 값을 넘겨 계산 진행
else if(!distinction(arrSplit)) {
stackCal.add(arrSplit.get(0));
arrSplit.remove(0);
}
}
// 결과값 출력
System.out.println(rst);
}
// 연산자 및 숫자 저장 분배 함수
public static void classifi(List<String> arr,
ArrayList<String> arrSplit, int i,
Stack<String> stackOp) {
if(arr.get(i).equals("+") || arr.get(i).equals("-")) {
// 이전 string이 ')' 괄호 였을 경우, 연산자 우선 순위 비교에 따라 arr 또는 stack에 값을 넣음
if(arr.get(i-1).equals(")")) {
arrSplit.add(stackOp.get(stackOp.size() - 1));
stackOp.pop();
stackOp.add(arr.get(i));
}
// 이전 string이 괄호가 아닌 경우, 그냥 arr에 넣음
else {
stackOp.add((String) arr.get(i));
}
}
else if(arr.get(i).equals("*")) {
stackOp.add((String) arr.get(i));
}
else if(arr.get(i).equals("/")) {
stackOp.add((String) arr.get(i));
}
else if (arr.get(i).equals("(")) {
stackOp.add((String) arr.get(i));
}
// else 에 포함시키지 않으며 동시에 ')' 를 넣지 않기 위한 조건
else if (arr.get(i).equals(")")) {
}
else {
arrSplit.add((String) arr.get(i));
}
}
public static void stackToArr(List<String> arr,
ArrayList<String> arrSplit, int j,
Stack<String> stackOp) {
while (true) {
// stack 요소가 '(' 라면 배열로의 이동을 중단하고, 괄호를 제거
if(stackOp.get(j).equals("(")) {
stackOp.pop();
break;
}
else {
// stack 요소가 ')' 이 아니라면 마지막 값을 arrSplit 배열로 이동 후 pop
if(!stackOp.get(j).equals(")")) {
arrSplit.add(stackOp.get(stackOp.size() - 1));
stackOp.pop();
}
// stack 요소가 ')' 라면 괄호를 제거
else if(stackOp.get(j).equals(")")) {
stackOp.pop();
}
}
// while 증가용 변수 'j'
j++;
}
}
// 후위식 배열에서 순서대로 숫자를 꺼내, 연산자가 나올 때까지 stackCal에 저장
public static void moveCal(ArrayList<String> arrSplit, Stack<String> stackCal) {
while(true) {
if(arrSplit.get(0).equals("+")) {
break;
}
else if(arrSplit.get(0).equals("-")) {
break;
}
else if(arrSplit.get(0).equals("*")) {
break;
}
else if(arrSplit.get(0).equals("/")) {
break;
}
else {
stackCal.add(arrSplit.get(0));
arrSplit.remove(0);
}
}
}
// distinction : 배열값이 문자열인지 숫자인지 구분하는 메소드
public static boolean distinction(ArrayList<String> arrSplit) {
if(arrSplit.get(0).equals("+")) {
return true;
}
else if(arrSplit.get(0).equals("-")) {
return true;
}
else if(arrSplit.get(0).equals("*")) {
return true;
}
else if(arrSplit.get(0).equals("/")) {
return true;
}
else {
return false;
}
}
}
댓글