C++ 코드를 JAVA로 바꿔보자
오늘은 https://www.acmicpc.net/problem/2557 문제를 통과하는 코드인 cpp 코드를 java코드로 바꿔주는 소스를 작성해 봤습니다.
코드 컨벤션을 준수한 코드를 기준으로 작성했습니다.
테스트 cpp 코드
#include<iostream>
using namespace std;
int main(){
cout << "Hello World!";
}
자바로 바꾼 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args)throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
sb.append("Hello World!");
System.out.print(sb);
}
}
JAVA는 Scanner 또는 BufferedReader로 보통 입력을 받습니다.
그 중 제가 자주 쓰는 BufferedReader로 해결을 하였습니다.
출력같은 경우도 System.out.println(); 을 사용하게 되면 효율적이지 못하여 StringBuilder를 사용하는 방식으로 진행했습니다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Stack;
public class Main {
static boolean iostream = false;
static boolean printFirst = false;
static boolean end = false;
static Stack<Character> stack = new Stack<>();
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
while(true) {
String s = br.readLine();
// 공백일 경우 pass
if(s.equals("")) {
continue;
}
sb.append(change(s));
if(end) {
break;
}
}
System.out.print(sb);
}
public static StringBuilder change(String str) {
StringBuilder sb = new StringBuilder();
String[] s = str.trim().split(" ");
if(str.equals("#include<iostream>")) {
sb.append("import java.io.BufferedReader;").append("\n");
sb.append("import java.io.IOException;").append("\n");
sb.append("import java.io.InputStreamReader;").append("\n\n");
iostream = true;
} // 입출력을 사용할 것이다.
else if(str.length() > 1 && s[1].contains("main")) {
sb.append("public class Main {").append("\n");
sb.append(" public static void main(String[] args)").append(iostream ? "throws IOException" : "").append(" {").append("\n");
if(iostream) {
sb.append(" BufferedReader br = new BufferedReader(new InputStreamReader(System.in));").append("\n\n");
}
stack.add('{');
} // main문을 작성하였을 떄
else if(s[0].endsWith("cout")) {
if(!printFirst) {
printFirst = true;
sb.append(" StringBuilder sb = new StringBuilder();").append("\n");
}
String[] coutS = str.split("<<");
for(int i = 1; i < coutS.length; i++) {
sb.append(" sb.append(");
char[] c = coutS[i].trim().toCharArray();
int len = c[c.length - 1] == ';' ? c.length - 1 : c.length;
for(int j = 0; j < len; j++) {
if(j < c.length - 6 && c[j] == '\\' && c[j + 1] == 'u'){
j += 5;
continue;
} // 유니코드를 사용한 경우 pass
sb.append(c[j]);
}
sb.append(");").append("\n");
}
} // 출력문인 경우
else if(str.equals("}")) {
if(stack.size() == 1 && stack.peek() == '{') {
sb.append(" System.out.print(sb);").append("\n");
sb.append(" }").append("\n");
}
sb.append("}").append("\n");
stack.pop();
end = true;
} // 마무리인 경우
return sb;
}
}
작성한 코드는 이렇습니다.
Stack의 경우 추루 for(;;){} 등 괄호를 사용하는 구문이 추가될 경우를 고려하여 stack을 작성하였습니다.
만드는데 1시간 정도 걸린거 같네여
다 만들고 나니 저격케이스를 제공해주셔서 그거 수정하느라 몇분...
추후에는 JAVA코드를 CPP로 바꾸는 방식을 작성해보고자 합니다.
해당 방식을 할떄 고려할 사항은
Scanner를 기준으로 할 것인가, BufferedReader를 기준으로 할 것인가
System.out.println();을 기준으로 할 것인가, StringBuilder를 기준으로 할 것인가, StringBuffer를 기준으로 할 것인가, BufferedWriter를 기준으로 할 것인가...
등 고려해야할 사항이 많다보니 조금 더 고민해 봐야할거 같습니다.
퇴근하면서 '한번 해볼까?' 라는 생각으로 시작했는데, 추후 확장성을 생각한다면 그렇게 쉬운거 같진 않네요..