이 문제의 요구사항은 아래와 같다.
대.소문자가 함께 사용된 문자열에서 , 대문자는 소문자로 , 소문자는 대문자로 변환하기.
이에 따른 나의 해결 로직은 다음과 같다.
입력받은 문자를 문자단위로 탐색하면서 , 대문자라면 소문자로 , 소문자라면 대문자로 변환시키기.
이렇게 요구사항도 , 그에 따른 로직도 단순하지만, 코드로 어떻게 구현할지가 막막했다.
Q1. 결국은 입력받은 문자열을 문자단위로 탐색하려면, String 객체를 char 배열로 변환시킨 후 그 배열의 각 element단위로 검사를 해야하는데,
"객체도 아닌 primitive 타입인 char값이 소문자 인지 대문자 인지 어떻게 확인하지?"
Q2. 또한 대문자라면 소문자로 , 소문자라면 대문자로 어떻게 변환시키지?
Q3. 변환시켰다 쳐도, 변환된 결과 또한 char 배열 이므로 , "이를 다시 String 객체로 변환해야 하는데 어떻게 하더라?"
문제를 해결하면서 발견한 해결책은 아래와 같았다.
A1. java.lang에서 제공하는 Charater클래스의 static메서드인
Charater.isUpperCase() 와 Charater.isLowerCase()를 사용하면
char값인 문자단위로 그 문자가 대문자 인지 or 소문자 인지 판별할 수 있었다.
A2. 이 또한 java.lang에서 제공하는 Charater 클래스의 static 메서드인 Character.toUpperCase() 와 Character.toLowerCase()를 사용하면 , 문자인 char값을 대문자로 or 소문자로 변환시켜 , char값 그대로 반환받을 수 있었다.
A3. String 객체의 생성자 중에 , char 배열을 인자로 받아 그 char들을 가지고 String 객체를 생성해 리턴해 주는 생성자가 존재했다.
위의 로직과 해결책을 기반으로 작성한 나의 코드는 다음과 같다.
import java.util.Scanner;
public class Main {
public String solution(String input){
char[] chars = input.toCharArray();
char[] outputChars = new char[chars.length];
//입력받은 문자열의 각 문자단위로 , 대문자면 -> 소문자로 , 소문자면 -> 대문자로 변환
for(int i=0; i<chars.length; i++){
if(Character.isUpperCase(chars[i])){
outputChars[i] = Character.toLowerCase(chars[i]);
}
else if(Character.isLowerCase(chars[i])){
outputChars[i] = Character.toUpperCase(chars[i]);
}
}
String outputStr = new String(outputChars);
return outputStr;
}
public static void main(String[] args){
//0. Scanner 준비
Scanner sc = new Scanner(System.in);
//1. 문자열 입력
String str = sc.next();
//2. solution 메서드를 통한 , 요구사항에 따른 문자열 변환
Main T = new Main();
String outputStr = T.solution(str);
//3. 변환된 문자열을 받아 출력
System.out.println(outputStr);
System.out.println(new char[2]);
}
}
이 문제에 대한 선생님의 코드는 아래와 같다.
import java.util.*;
class Main {
public String solution(String str){
String answer="";
for(char x : str.toCharArray()){
if(Character.isLowerCase(x)) answer+=Character.toUpperCase(x);
else answer+=Character.toLowerCase(x);
}
return answer;
}
public static void main(String[] args){
Main T = new Main();
Scanner kb = new Scanner(System.in);
String str=kb.next();
System.out.print(T.solution(str));
}
}
import java.util.*;
class Main {
public String solution(String str){
String answer="";
for(char x : str.toCharArray()){
if(x>=97 && x<=122) answer+=(char)(x-32);
else answer+=(char)(x+32);
}
return answer;
}
public static void main(String[] args){
Main T = new Main();
Scanner kb = new Scanner(System.in);
String str=kb.next();
System.out.print(T.solution(str));
}
}
차이점이라 하면
1. 선생님의 첫 번째 방식은 , 변환시킨 문자들을 char배열에 담지 않고 바로 String 객체에 이어 붙이고 있다.
-> 이렇게 문자열을 이어붙이는 방법은 생각하지 못했다.
-> 그리고 문자열+문자열이아닌data 를 하면 , 문자열이 아닌 data가 Stirng으로 type casting된 후 문자열로 연결된다는 사실이 char 값에도 적용된다는 점을 잊고 있었다.
-> 결론적으로는 이렇게 바로 String으로 이어붙이는 방식이 더 좋은것 같아, 코드를 수정하였다.
-> 아스키코드값을 가지고 대소문자 변환이 가능하지만, 이는 코드만 보고 의미를 파악하는것이 쉽지 않으므로, 이보다는 첫 번째 방식이 더 좋다고 생각한다.
그외 추가적으로 주의가 필요한 부분은 아래와 같았다.
나의 경우 별도의 빈 char배열을 생성해서, 그 안에 변환된 문자들을 담았다.
그런데 처음에는
char[] outputChars = new char[]{};
와 같이 배열을 생성하였더니 에러가 터졌다.
자세히 보니 new char[]{} 와 같이 배열을 생성하면
배열을 생성과 동시에 초기화 하는 방식으로써
{}안의 element를 포함하는 배열이 생성되는데,
나의 경우는 {}안에 어떤 element도 없었기 때문에
텍스트길이가 0인 배열이 생성되어 에러가 터졌던 것이다
따라서 기존 문자열을 담는 배열의 크기만큼 배열 길이를 할당하는 방식으로
char[] outputChars = new char[chars.length];
이와 같이 배열을 생성하여야 , 변환된 문자들을 온전히 담을만큼의 크기를 갖는 배열이 생성된다는 사실을 다시 한번 상기하였다.