와드의 블로그

3613번: Java vs C++ 본문

PS/B.O.J

3613번: Java vs C++

Ward 2026. 4. 10. 01:37

문제

C++에서는 변수명을 작성할 때 단어와 단어 사이를 밑줄('_')로 구분하는 형식을 사용합니다. (예: c_identifier) 반면 Java에서는 첫 단어를 제외한 나머지 단어의 첫 글자를 대문자로 쓰는 형식을 사용합니다. (예: javaIdentifier) 어떤 변수명이 주어졌을 때, 이것이 C++ 형식이라면 Java 형식으로, Java 형식이라면 C++ 형식으로 변환하는 프로그램을 작성하는 문제입니다. 두 형식에 모두 맞지 않는 에러 상황이라면 "Error!"를 출력해야 합니다.

  • 입력: 첫째 줄에 변수명이 주어집니다. 영문 알파벳과 밑줄('_')로만 이루어져 있으며, 길이는 100을 넘지 않습니다.
  • 출력: 변환된 변수명을 출력합니다. 에러 형식인 경우 "Error!"를 출력합니다.

링크: https://www.acmicpc.net/problem/3613

풀이 1: 플래그(Flag) 변수와 replaceAll을 활용한 일괄 치환

입력된 문자열을 한 글자씩 검사하여 어떤 언어의 형식인지 플래그 변수로 판별한 뒤, 26번의 반복문과 replaceAll 메서드를 활용하여 알파벳 치환을 일괄적으로 수행하는 풀이입니다.

  • 형식 판별 (Flag 확인): 문자열을 순회하며 밑줄(_)이 등장하면 isC를 true로, 대문자(A~Z)가 등장하면 isJava를 true로 설정합니다.
  • 에러 검출:
    • isC와 isJava가 모두 true인 경우: 밑줄과 대문자가 혼용된 형태
    • s.charAt(0) >= 'A' && s.charAt(0) <= 'Z': Java 형식은 소문자로 시작해야 함
    • s.startsWith("_") || s.endsWith("_"): 밑줄로 시작하거나 끝나는 경우
    • s.contains("__"): 밑줄이 연속으로 등장하는 경우
  • 변환 진행: 에러가 아니라면, replaceAll을 26번 순회하며 _a를 A로 바꾸거나(C++ -> Java), A를 _a로 바꾸는(Java -> C++) 치환 작업을 일괄 수행합니다.

코드 1

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
       BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
       BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

       String s = br.readLine();

       boolean isJava = false;
       boolean isC = false;
       for (char c : s.toCharArray()) {
          if (c == '_') {
             isC = true;
          } else if (c >= 'A' && c <= 'Z') {
             isJava = true;
          }
       }

       // 모든 예외 케이스 완벽 처리
       if ((isC && isJava) || (s.charAt(0) >= 'A' && s.charAt(0) <= 'Z') || s.startsWith("_") || s.endsWith("_")
          || s.contains("__")) {
          bw.write("Error!");
          bw.flush();
          return;
       }

       // C++ -> Java 변환
       if (isC) {
          for (int i = 0; i < 26; i++) {
             s = s.replaceAll("_" + (char)(i + 'a'), Character.toString((char)(i + 'A')));
          }
       } 
       // Java -> C++ 변환
       else {
          for (int i = 0; i < 26; i++) {
             s = s.replaceAll(Character.toString((char)(i + 'A')), "_" + (char)(i + 'a'));
          }
       }

       bw.write(s);

       bw.flush();
    }
}

풀이 2: StringBuilder를 활용한 파싱

replaceAll은 호출될 때마다 내부적으로 새로운 String 객체를 생성하므로 메모리와 시간 측면에서 다소 비효율적일 수 있습니다. 이를 보완하기 위해 문자열을 한 번만 순회하며 O(N) 시간에 StringBuilder로 변환된 문자를 덧붙이는 정석적인 구현 방식입니다.

  • 에러 검출: 풀이 1과 동일하게 까다로운 예외 상황들을 먼저 걸러냅니다.
  • C++ 형식을 Java 형식으로 변환: 문자열을 순회하며 밑줄(_)을 만나면 바로 추가하지 않고, nextUpper 플래그를 true로 둡니다. 그 다음 문자가 들어올 때 대문자로 변환(Character.toUpperCase)하여 StringBuilder에 추가합니다.
  • Java 형식을 C++ 형식으로 변환: 순회 중 대문자를 만나면 먼저 밑줄(_)을 추가하고, 해당 문자를 소문자로 변환(Character.toLowerCase)하여 추가합니다. 일반 소문자는 그대로 덧붙입니다.

코드 2

import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
       BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
       BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

       String s = br.readLine();

       boolean isJava = false;
       boolean isC = false;
       for (char c : s.toCharArray()) {
          if (c == '_') {
             isC = true;
          } else if (c >= 'A' && c <= 'Z') {
             isJava = true;
          }
       }

       if ((isC && isJava) || (s.charAt(0) >= 'A' && s.charAt(0) <= 'Z') || s.startsWith("_") || s.endsWith("_")
          || s.contains("__")) {
          bw.write("Error!");
          bw.flush();
          return;
       }

       StringBuilder sb = new StringBuilder();

       // C++ -> Java 변환
       if (isC) {
          boolean nextUpper = false;
          for (int i = 0; i < s.length(); i++) {
             char c = s.charAt(i);
             if (c == '_') {
                nextUpper = true;
             } else {
                if (nextUpper) {
                   sb.append(Character.toUpperCase(c));
                   nextUpper = false;
                } else {
                   sb.append(c);
                }
             }
          }
       } 
       // Java -> C++ 변환
       else {
          for (int i = 0; i < s.length(); i++) {
             char c = s.charAt(i);
             if (c >= 'A' && c <= 'Z') {
                sb.append('_');
                sb.append(Character.toLowerCase(c));
             } else {
                sb.append(c);
             }
          }
       }

       bw.write(sb.toString());
       bw.flush();
    }
}

알고리즘 분류

구현 (Implementation), 문자열 (String)

'PS > B.O.J' 카테고리의 다른 글

2999번: 비밀 이메일  (0) 2026.04.10
1969번: DNA  (0) 2026.04.10
2941번: 크로아티아 알파벳  (0) 2026.04.10
1929번: 소수 구하기  (0) 2026.04.08
단어 나누기  (0) 2026.04.07