개요
임의의 길이를 가진 문자열 str이 주어졌을 때, 반복(iteration) 방식과 재귀(recursion) 방식, 두 가지 방법으로 해당 문자열에 포함된 자음의 개수를 계산하는 것이 이 글의 목표입니다.
여기서 자음(consonant)이란 모음(vowel)이 아닌 알파벳을 의미합니다. 즉, a, e, i, o, u를 제외한 나머지 알파벳은 모두 자음으로 간주됩니다. 따라서 아래 프로그램에서는 문자열 안에서 이 다섯 개의 모음을 제외한 알파벳의 개수를 세어야 합니다.
재귀와 반복은 공통적으로 일련의 명령어를 반복해서 실행한다는 특징이 있습니다. 재귀는 함수 내부의 문장이 자기 자신을 계속 호출하는 방식이고, 반복은 제어 조건이 거짓(false)이 될 때까지 루프가 실행되는 방식입니다. 두 방식의 핵심 차이는 재귀가 항상 함수에 적용되는 프로세스라는 점이며, 반복은 반복 실행하고자 하는 명령어 집합에 적용된다는 점입니다.
예시
입력 − string str = “tutorials point”
출력 − count is 8
설명 − 주어진 문자열 str에는 총 8개의 자음이 포함되어 있으며, 각각 t, t, r, l, s, p, n, t입니다.
입력 − string str = “a e io u”
출력 − count is 0
설명 − 주어진 문자열 str에는 자음이 하나도 없고 모음만 존재하므로 개수는 0이 됩니다.
방법 1: 반복문(Iteration)
프로그램에 사용된 접근 방식
문자열을 변수(예: str)에 입력받습니다.
length() 함수를 사용해 문자열의 길이를 구합니다. 이 함수는 문자열에 포함된 문자 수에 해당하는 정수를 반환합니다.
자음의 개수를 저장할 임시 변수를 준비합니다.
i를 0부터 문자열 길이보다 작을 때까지 1씩 증가시키며 루프를 실행합니다.
루프 내부에서 str[i]가 자음인지 검사하고, 자음이라면 카운트 값을 1 증가시킵니다.
최종 카운트를 반환합니다.
결과를 출력합니다.
반복문 예제 코드
// Iterative CPP program
#include <iostream>
using namespace std;
// Function to check for consonant
bool consonant(char ch){
// To handle lower case
ch = toupper(ch);
return !(ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') && ch >= 65 && ch <= 90;
}
//function to count consonant
int countconsonants(string s){
int result = 0;
for (int i = 0; i < s.length(); i++){
// To check is character is Consonant
if (consonant(s[i])){
++result;
}
}
return result;
}
// main function
int main(){
string s = "wx abc def";
cout <<"count is: "<<countconsonants(s);
return 0;
}
실행 결과
위 코드를 실행하면 다음과 같은 출력 결과를 얻을 수 있습니다.
count is: 6
방법 2: 재귀 함수(Recursion)
프로그램에 사용된 접근 방식
문자열을 변수(예: str)에 입력받습니다.
length() 함수를 사용해 문자열의 길이를 구합니다. 이 함수는 문자열에 포함된 문자 수에 해당하는 정수를 반환합니다.
자음의 개수를 저장할 임시 변수를 준비합니다.
문자열 속 자음을 계산하기 위해 스스로를 호출하는 재귀 함수를 생성합니다.
문자열 크기(n)가 1이라면 str[0]에 대한 자음 여부 검사 결과를 반환합니다.
그렇지 않다면, 재귀 호출 결과인 consonantcount(str, n - 1)에 마지막 문자(str[n-1])의 자음 여부 검사 결과를 더하여 반환합니다.
재귀 함수 예제 코드
// Recursive CPP program
#include <iostream>
using namespace std;
// Function to check for consonant
bool consonant(char ch){
// To convert the lower case
ch = toupper(ch);
return !(ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') && ch >= 65 && ch <= 90;
}
// to count total number of consonants
int consonantcount(string str, int n){
if (n == 1){
return consonant(str[0]);
}
return consonantcount(str, n - 1) +
consonant(str[n-1]);
}
int main(){
string str = "wx abc def";
cout <<"count is: "<<consonantcount(str, str.length());
return 0;
}
실행 결과
위 코드를 실행하면 다음과 같은 출력 결과를 얻을 수 있습니다.
count is: 6
마무리
두 방식 모두 동일한 결과를 반환하지만, 반복문은 루프를 통해 순차적으로 문자를 검사하는 반면, 재귀는 함수가 자기 자신을 호출하며 문자열을 끝에서부터 앞쪽으로 처리한다는 차이가 있습니다. 문자열이 매우 긴 경우에는 재귀 호출로 인한 스택 오버플로 위험을 고려하여 상황에 맞는 방식을 선택하는 것이 좋습니다.