공백(space), 줄바꿈 문자(new line), 탭 문자(tab)가 섞여 있을 수 있는 문장 형태의 문자열이 주어졌을 때, 해당 문자열 안에 포함된 총 단어 수를 계산하여 출력하는 것이 이번 글의 목표입니다.
문제 정의
입력 − string str = "welcome to\n tutorials point\t"
출력 − 문자열의 단어 수: 4
설명 − 문자열에는 welcome, to, tutorials, point의 네 단어가 있으며, 나머지는 단어 사이에 위치한 공백(" "), 줄바꿈 문자(\n), 탭 문자(\t)입니다.
입력 − string str = "\nhonesty\t is the best policy"
출력 − 문자열의 단어 수: 5
설명 − 문자열에는 honesty, is, the, best, policy의 다섯 단어가 있으며, 앞뒤와 단어 사이에는 줄바꿈 문자(\n), 탭 문자(\t), 공백(" ")이 포함되어 있습니다.
해결 접근 방법
이 문제는 여러 가지 방법으로 풀 수 있습니다. 먼저 아래 코드에서 사용한 비교적 간단한 접근 방식부터 살펴보겠습니다.
- 문자열을 저장하기 위한 char 타입 배열(예: str[])을 생성합니다.
- 두 개의 임시 변수를 선언합니다. 하나는 단어 수를 세는
count, 다른 하나는 플래그 역할을 하는temp입니다. - str이 널(null)이 아닌 동안 while 루프를 실행합니다.
- 루프 내부에서 *str이 공백(' '), 줄바꿈('\n'), 또는 탭('\t')이라면 temp를 0으로 설정합니다.
- 그 외의 경우 temp가 0이라면 temp를 1로 바꾸고 count 값을 1 증가시킵니다. 이는 새로운 단어의 시작을 의미합니다.
- str 포인터를 1씩 증가시켜 다음 문자로 이동합니다.
- 루프가 끝나면 count 값을 반환합니다.
- 결과를 출력합니다.
핵심 아이디어는 구분 문자(whitespace)에서 일반 문자로 전환되는 시점을 감지하는 것입니다. temp 플래그는 연속된 공백이 여러 개 있어도 한 단어로만 계산되도록 도와줍니다.
예제 코드
#include <iostream>
using namespace std;
// 주어진 문자열에서 단어 수를 세는 함수
int total_words(char *str){
int count = 0;
int temp = 0;
while (*str){
if (*str == ' ' || *str == '\n' || *str == '\t'){
temp = 0;
}
else if(temp == 0){
temp = 1;
count++;
}
++str;
}
return count;
}
int main(){
char str[] = "welcome to\n tutorials point\t";
cout << "Count of words in a string are: " << total_words(str);
return 0;
}실행 결과
위 코드를 실행하면 다음과 같은 출력이 생성됩니다.
Count of words in a string are: 4
대안 방법: stringstream 활용
C++ 스타일의 더 간결한 해법도 있습니다. <sstream> 헤더의 istringstream을 사용하면 스트림 추출 연산자(>>)가 자동으로 모든 종류의 공백 문자를 구분자로 처리해 주므로, 별도의 플래그 로직 없이 단어 수를 셀 수 있습니다.
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
int total_words(const string &str){
istringstream iss(str);
string word;
int count = 0;
while (iss >> word){
count++;
}
return count;
}
int main(){
string str = "welcome to\n tutorials point\t";
cout << "Count of words in a string are: " << total_words(str);
return 0;
}두 방법 모두 시간 복잡도는 O(n)(n은 문자열 길이)으로 동일하지만, stringstream 방식은 코드가 짧고 가독성이 좋아 실무에서 더 자주 사용됩니다. 반면 포인터 기반 방식은 문자 순회의 원리를 명확히 보여주므로 학습 목적이나 C 스타일 코드를 다룰 때 유용합니다.