출제 의도
- 구현
문제가 요구하는 대로 구현할 수 있는지 확인하는 문제입니다.
문제 해설
처음에 테스트케이스의 수를 입력받고, 그 다음 줄부터 공백이 포함된 문자열이 입력으로 주어집니다. 한 줄을 통째로 입력받을 때 C언어의 경우는 fgets
함수를 사용할 수 있고, C++의 경우는 std::getline
함수를 사용할 수 있습니다. 문자열을 입력받은 후, 이 문자열을 처음부터 순회하면서 알파벳 모음인지 아닌지를 판별하는 것이 중요합니다. 현재 문자가 모음인지 확인하려면 어떻게 하면 좋을까요? 모음은 소문자 a, e, i, o, u와 대문자 A, E, I, O, U로 총 10가지의 경우가 있습니다. 물론 다음과 같이 if
문이나 switch
문으로 10가지의 경우를 모두 처리해줄 수도 있습니다.
// if문 사용if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' ||ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') putchar(ch);
// switch문 사용switch (ch) {case 'a': case 'e': case 'i': case 'o': case 'u':case 'A': case 'E': case 'I': case 'O': case 'U':
putchar(ch); break; defalut:break; }
하지만... 너무 번거롭죠? 비교해야 할 경우를 10가지에서 5가지로 줄이는 방법이 있습니다. 현재 문자를 대문자든 소문자든 항상 소문자로 취급한다고 하면 가능한데요, 대문자를 소문자로 취급하는 방법은 대문자와 소문자의 아스키 코드 값이 32가 차이 남을 이용할 수 있습니다. ch | 32
처럼 bitwise-or 연산자를 이용해 32와 입력받은 문자를 or 연산하면 소문자를 얻을 수 있습니다. 물론 ch가 알파벳이 아닌 다른 특수 문자였다면 32와 or 연산한 결과 역시 알파벳이 아니므로 이 부분은 신경쓰지 않아도 됩니다.
이러한 방법뿐만 아니라 대부분의 언어 라이브러리엔 주어진 문자열에서 특정 문자를 찾는 함수가 이미 존재합니다. C/C++는 물론이고 자바, 파이썬도 마찬가지입니다. C에는 strchr
함수, C++의 string 클래스에는 find
메소드, 자바의 String 클래스에는 indexOf
메소드, 파이썬은 아예 in
연산자로 확인이 가능합니다. 따라서 현재 문자를 32와 or 연산한 뒤 "aeiou" 문자열에서 현재 문자를 찾아, 있으면 출력하고 없으면 그대로 넘어가면 됩니다.
그럼 이걸로 끝난 걸까요? 그렇게 생각하신다면, 문제를 다시 한 번 잘 읽어보셔야 합니다. 문제 조건에 소문자가 없으면 ???
을 출력하라는 말이 있었지요. 따라서 상태 변수 하나를 만들어 처음에 0으로 초기화하고 한번이라도 모음이 있었으면 1로 만들고 마지막에 0이면 ???
을 출력하면 됩니다. 물론 이는 풀이에 따라 다른데, 제때 출력하지 않고 배열 등에 저장하여 프로그램이 끝나기 직전 한꺼번에 출력한다면 모아둔 개수를 확인하면 되니 따로 상태 변수가 필요 없습니다.
※ 다른 언어로 작성한 알고리즘 코드에 대한 질문은 QnA 게시판을 이용해주시기 바랍니다.
C++ 답안 코드
컴파일러 설정 gcc 5.4, 언어 설정 -std=c++17 -02 -Wall -lm 기준입니다.