2022년 3월 31일 목요일

정규식을 활용한 간단한 계산기 ( 사칙연산만 가능 ) 기록

 간단한 내용은 구현 후 관리하지 않아서 여기저기 소스가 흩어져 있어 정리 용도로 

구성합니다. 

에러 확인 없이 정말 간단한 사칙연산을 위한 코드를 구성해 보았습니다. 

곱하기 나누기는 우선순위가 높기 때문에 먼저 문자열 분해 과정에서 계산을 하고, 

더하기 빼기의 연산은 Stack 구조이긴 하지만, 앞에서 뒤로 계산하도록 간단히 구성해 

보았습니다. 


public static double parseStringBasicCalulation(String str) {

if ( str == null ) {

return Double.NaN;

}

double result = Double.NaN;

String trStr = str.replaceAll("[\\h]+", "");

String regStr = "(([+\\-])?([\\d]+)?([.][\\d]+)?([eE][+\\-]?[\\d]+)?)([*/+-]{1}?)?";

Pattern pObj = Pattern.compile(regStr, Pattern.MULTILINE);

Matcher mObj = pObj.matcher(trStr);

Stack<String> dataStack = new Stack<String>();

while ( mObj.find()) {

String numStr = mObj.group(1);

String markStr = mObj.group(6);

if ( !dataStack.isEmpty() ) {

if ( dataStack.peek().equals("*")) {

dataStack.pop();

String preNum = dataStack.pop();

numStr = (Double.parseDouble(preNum)*Double.parseDouble(numStr))+"";

} else if ( dataStack.peek().equals("/")) {

dataStack.pop();

String preNum = dataStack.pop();

numStr = (Double.parseDouble(preNum)/Double.parseDouble(numStr))+"";

}

}

dataStack.add(numStr);

if ( markStr != null ) {

dataStack.add(markStr);

} else {

break;

}

}

if ( dataStack.size() >= 3 ) {

result = Double.parseDouble(dataStack.remove(0));

while ( !dataStack.isEmpty() ) {

String s = dataStack.remove(0);

if ( s.equals("+")) {

result += Double.parseDouble(dataStack.remove(0));

} else if ( s.equals("-")) {

result -= Double.parseDouble(dataStack.remove(0));

}

}

} else {

result = Double.parseDouble(dataStack.pop());

}

return result;

}


main block 에서 

String str02 = "8*15/15+5/5+7-6";

System.out.println (parseStringBasicCalulation(str02)); 

호출하면 결과가 10.0 이 나오면 정상입니다. 


정규식을 활용한 Brace Block 추출

 졍규식을 활용하여 "()" Block 을 추출하는 모듈을 구성해 보았습니다.


매번 구성하고 소스가 어디에 있는지 몰라 다시 구성하는 것을 반복하다 보니, 

간단히 메모처럼 적어 놓게 되었습니다. 


public static Map<String,String> parseStringBraceBlocks(String str) {

if ( str == null )

return null;

Map<String,String> result = new LinkedHashMap<String,String>();

String regStr = "([(]([^()]+?)[)])";

Pattern pObj = Pattern.compile(regStr, Pattern.MULTILINE);

Matcher mObj = pObj.matcher(str);

String tr = str;

int count = 0;

while ( mObj.find()) {

String keyStr = "@"+(++count)+"@";

String valueStr = mObj.group(2);

result.put(keyStr, valueStr);

tr = tr.substring(0,mObj.start(1))

+ keyStr + tr.substring(mObj.end(1));

mObj = pObj.matcher(tr);

}

result.put("FINAL", tr);

return result;

}


정규식으로 내용을 찾고, 찾은 결과를 치환하여 다시 대상이 되지 않도록 구성 후 
재귀 호출처럼 반복하여 결과를 분해한 후 최종적으로 각 단계에 포함된 내용을 
Map 에 담아 반환 하는 함수 입니다.