대소문자를 포함한 문장을 입력받고, 문장에 포함된 단어의 개수를 출력하는 문제이다.
같은 단어가 여러개 나온다고 하나로 칠 필요는 없고 각각 세면 된다.
주의할점은 입력받는 문자열의 맨 앞이나 맨 뒤에 공백이 들어갈 경우인데,
만약 단순히 입력받은 문자열에서 공백이 몇개인지를 세게 된다면 잘못된 결과가 나올수도 있다.
나는 readLine()으로 String을 입력받은뒤 구분자를 " "으로 두어 split()으로 나누어진 String들을 배열에 담았다.
만일 입력받은 String인 s의 맨 앞에 공백이 하나 있다면 words 배열 맨 앞자리에 빈 값이 들어갈 것이고
맨 뒤에 공백이 있다면 배열 맨 뒷자리에 빈 값이 들어가게 될 것이다.
-> 엇 아니다..맨 뒤에 공백이 있는 경우에는 배열에 아무것도 넣어지는 값이 없다(공백 문자열조차 들어가지 않는다)
맨 앞에 공백 문자열이 생기는 경우와 왜 다를까???
구글링을 해봤지만 아직 명확한 원인을 찾지 못했다..
추측하건데 스페이스바와 엔터를 하나의 공백으로 인식해서 그런게 아닐까 싶다.
찜찜하다...정확한 원인을 알게 되면 다시 추가해서 작성하도록 해야겠다
따라서 foreach문으로 words에 있는 원소들을 하나씩 꺼내어 빈 값이면 건너뛰고, 아니라면 카운트하는 식으로 풀었다.
다음과 같이 코드를 짰다.
import java.io.*;
public class WordCount {
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(); //String으로 일단 입력받음
String[] words = s.split(" ");
int count = 0;
for (String ss : words) {
if (ss.equals("")) { //맨 앞에 공백이 붙어있을경우 NULL이 아니라 빈 문자열 값이 들어있다
continue;
} else {
count++;
}
}
bw.write(Integer.toString(count));
bw.flush();
bw.close();
}
}
겪었던 문제는 이러했다.
처음에는 문자열 ss == null인지를 확인했으나
단어들 사이의 공백이 아닌 맨 앞의 공백을 split에서 처리하여
문자열 배열에 들어가있던 값은 null이 아니라 빈 문자열 ""였다.
따라서 조건을 바꿔야했는데, 두번쨰로는 ss == ""로 했다.
근데 이렇게 하니까 무슨 이유에선지 false로 판정되더라. 왜일까..
그래서 알아본 결과!!
==연산자와 equals()의 차이를 우선 알아야 했다.
==연산자는 int형, boolean, char과 같은 기본 타입들(Primitive type)의 경우 값을 비교하지만,
(사실 primitive type의 경우도 Constant Pool에 있는 특정 상수를 참조하는 것이기 때문에 결국 주소값을 비교하는것이긴 하지만,
같은 상수를 참조하면 주소값이 같으므로 결국 같은 값이면 동일 주소, 즉 동일하다고 판단하는것!
이 Constant Pool이라는것에 대해 잘 알지 못해서 완전히 이해는 안가지만 추후 공부해봐야겠다.)
String과 같은 참조형 타입(reference type)클래스 객체의 경우에서는 주소값을 비교한다!
따라서 String타입간을 ==를 통해 비교하게 되면 둘의 주소값을 비교하게 되고,
ss == ""의 주소값은 다르기때문에 결과는 false로 나오게 되었던 것이다.
그래서 String객체 사이의 값을 비교하고자 한다면 ==가 아닌 equals()를 사용해야한다!
따라서, 결국 나는 isBlank()라는 함수를 통해 빈 문자열인지 확인을 했고 원하던 결과가 나왔지만
ss.equals("")로 조건을 설정해주어도 되는 것이다.
이렇게 하면 배열 맨 앞에있는 빈 문자열이 카운트되는것을 방지할 수 있다.
.
.
다른 사람의 코드를 둘러보다가 혼란을 겪었다.
그 코드는 다음과 같다..
Scanner Sc = new Scanner(System.in);
String String = Sc.nextLine();
String[] Word = String.split(" ");
ArrayList<String> List = new ArrayList<>();
for(int i=0; i < Word.length ; i++)
{
if(Word[i] == "")
{
continue;
}
else
{
List.add(Word[i]);
}
}
System.out.println(List.size());
Sc.close();
일단 이 코드는 맞았습니다 판정을 받은 코드이다.
그런데, 이거대로 실행했을때 백준에 있는 두번째 테스트 케이스의 경우 결괏값이 7로 나오게 된다.
결괏값은 6이 되어야 맞다.
if 조건문에서 == ""로 해놨기 때문에 앞서 말했던 이유로 빈 문자열이어도 연산결과는 false가 되게 되어
List에 추가가 되고, 따라서 List의 사이즈를 구하면 7이 되는것이다.
그럼 틀린건데.. 왜 백준에서 이를 맞는 결과라고 하는지 이해가 가질 않는다.
누가 설명좀 해주세요 제발........
찜찜한 점 두개를 남기게 된 문제였다..
+
trim()메소드를 사용하여 문자열의 앞뒤 공백을 아예 제거해서 푸는 방법도 있다고 하네요~
이때 입력값이 " "로 공백뿐이라면 해당 공백은 남게 되고, 이 경우를 생각해 주어야 함.
아니 이해가 안가는게..
1. 공백 하나뿐인 문자열을 trim()하고나서 그대로 공백 하나만 나오게 되는 이유가 뭐지?
2. trim()으로 앞뒤공백을 제거하고 split으로 공백기준으로 잘라 String배열로 만들어 넣게되면
어떻게 맨 뒤에있는 문자열까지 들어가게 되는거지?trim으로 뒤의 공백까지 제거했는데
뭘보고 판단해서 맨 뒤의 문자열까지 잘 배열에 들어가게 되는거지??
'알고리즘 > 문자열' 카테고리의 다른 글
[백준알고리즘] 문자열 - 5622번 다이얼 문제 (0) | 2022.07.26 |
---|---|
[백준알고리즘] 문자열 - 2908 상수 문제 (0) | 2022.07.26 |
[백준알고리즘] 문자열 - 1157번 단어공부 문제 (0) | 2022.07.20 |
[백준알고리즘] 문자열 - 2675번 문자열 반복 문제 (0) | 2022.07.15 |
[백준알고리즘] 문자열 - 10809번 알파벳 찾기 문제 (0) | 2022.07.12 |