Programming 기초/Coding Test

[BOJ#1152번] 문자열에서 단어 개수 세기. count()함수, len()함수, split(' ')와 split()의 차이

코딩상륙작전 2023. 7. 9. 10:50

* 단어의 개수 (1152번)

문제

영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열에는 몇 개의 단어가 있을까? 이를 구하는 프로그램을 작성하시오. 단, 한 단어가 여러 번 등장하면 등장한 횟수만큼 모두 세어야 한다.

 

입력

첫 줄에 영어 대소문자와 공백으로 이루어진 문자열이 주어진다. 이 문자열의 길이는 1,000,000을 넘지 않는다. 단어는 공백 한 개로 구분되며, 공백이 연속해서 나오는 경우는 없다. 또한 문자열은 공백으로 시작하거나 끝날 수 있다.

 

출력

첫째 줄에 단어의 개수를 출력한다.

 

* len()함수를 이용한 풀이

print(len(input().strip().split()))

 

* count()함수를 이용한 풀이

# 정답 소스코드
s = input().strip()
print(s.count(" ") + 1 if s != "" else 0)

 

* 논리적 오류를 조심하자

위와 같은 정답 소스코드를 작성하기까지 여러 오류를 겪었다. 그 중 도움이 될 만한 피드백 경험을 기록한다.

# 틀린 소스코드
s = input().strip().count(" ")
print(s + 1 if s else 0)

해당 소스코드는 틀렸다는 판정을 받았고, 문법적 오류가 아니라서 그 이유를 쉽게 찾지 못했다.

결국, 파이썬 오픈톡방에 질문을 올려서 해답을 찾았다.

# 논리적 오류를 범한 소스코드
s = input().strip().count(" ")
print(s + 1 if s else 0)
------------------------------------
a
0

빈칸 없이 단어 하나 뿐인 경우 s=0이 되어서 else 0값이 출력되는 논리적 오류가 발생했다.

# 정답 소스코드
s = input().strip()
print(s.count(" ") + 1 if s else 0)

위와 같이 count()함수를 아래에 붙여주면 정답처리된다. bool값에서 0값 이외에는 문자열을 포함해서 모두 True 값이 됨을 기억하자.

 

* split(' ')와 split()의 차이

len()함수를 이용한 풀이에서 split()함수를 조심해야한다.

1. split('')와 같이 따옴표 사이에 빈 칸을 삽입하지 않으면 ValueError: empty separator와 같은 에러가 발생한다.

2. split(' ')와 split()의 차이는 출력값에 영향을 줄 수 있다

s = input().strip().split()
print(len(s))
-------------------------------
	# 공백 하나만 입력했을 경우
0	# 출력 값

split(sep=None, maxsplit=-1)에서 sep 이 지정되지 않거나 None 이면, 다른 분할 알고리즘이 적용된다. 연속된 공백 문자는 단일한 구분자로 간주하고, 문자열이 선행이나 후행 공백을 포함해도 결과는 시작과 끝에 빈 문자열을 포함하지 않는다. 결과적으로, 빈 문자열이나 공백만으로 구성된 문자열을 None 구분자로 나누면 [] 를 돌려준다.(

 

(+) maxsplit 인자에 대한 설명

더보기

maxsplit 이 주어지면 최대 maxsplit 번의 분할이 수행됩니다 (따라서, 리스트는 최대 maxsplit+1 개의 요소를 가지게 됩니다). maxsplit 이 지정되지 않았거나 -1 이라면 분할 수에 제한이 없습니다 (가능한 모든 분할이 만들어집니다).

>>> '1,2,3'.split(',', maxsplit=1)
['1', '2,3']

 

s = input().strip().split(" ")
print(len(s))
-------------------------------
	# 공백 하나만 입력했을 경우
1	# 출력 값

sep을 지정하는 경우에는 sep 를 구분자 문자열로 사용하여 문자열에 있는 단어들의 리스트를 돌려준다. sep 이 주어지면, 연속된 구분자는 묶이지 않고 빈 문자열을 구분하는 것으로 간주한다(예를 들어, '1,,2'.split(',')  ['1', '', '2'] 를 돌려준다).  지정된 구분자로 빈 문자열을 나누면 [''] 를 돌려준다.
→ 즉, split()을 사용할 경우 s에는 []가 저장되고, split(' ')을 사용할 경우 s에는 ['']가 저장된다.

print("@".strip().split("@"))
print("   ".strip().split("@"))
print(" ".strip().split(" "))
print("999      99              ".strip().split(" "))
-------------------------------
['', '']
['']
['']
['999', '', '', '', '', '', '99']

 

 

* 참고

https://docs.python.org/ko/3/library/stdtypes.html?highlight=split#str.split