Software Hyena::

[백준 2941번] - 크로아티아 알파벳 / C++ (예외 발견) 본문

알고리즘/백준

[백준 2941번] - 크로아티아 알파벳 / C++ (예외 발견)

bluehyena 2021. 2. 23. 02:30
반응형

문제

예전에는 운영체제에서 크로아티아 알파벳을 입력할 수가 없었다. 따라서, 다음과 같이 크로아티아 알파벳을 변경해서 입력했다.

크로아티아 알파벳변경

č c=
ć c-
dz=
đ d-
lj lj
nj nj
š s=
ž z=

예를 들어, ljes=njak은 크로아티아 알파벳 6개(lj, e, š, nj, a, k)로 이루어져 있다. 단어가 주어졌을 때, 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.

dž는 무조건 하나의 알파벳으로 쓰이고, d와 ž가 분리된 것으로 보지 않는다. lj와 nj도 마찬가지이다. 위 목록에 없는 알파벳은 한 글자씩 센다.

입력

첫째 줄에 최대 100글자의 단어가 주어진다. 알파벳 소문자와 '-', '='로만 이루어져 있다.

단어는 크로아티아 알파벳으로 이루어져 있다. 문제 설명의 표에 나와있는 알파벳은 변경된 형태로 입력된다.

출력

입력으로 주어진 단어가 몇 개의 크로아티아 알파벳으로 이루어져 있는지 출력한다.

---------------------------------------------------------------------------------------------------------

풀이

<C++>

1. 오류가 있으나 정답처리된 코드

#include <iostream>

using namespace std;

int main() {
	string words;
	cin >> words;

	int word_num = 0;

	for (int i = 1; i < words.length(); ++i) {
		if (words[i] == '=') {
			if (words[i - 1] == 'c' || words[i - 1] == 's') {
				++word_num;
			}
			else if (words[i - 1] == 'z') {
				if (words[i - 2] == 'd') { // 에러 발생 가능
					word_num += 2;
				}
				else {
					++word_num;
				}
			}
		}
		else if (words[i] == '-') {
			if (words[i - 1] == 'c' || words[i - 1] == 'd') {
				++word_num;
			}
		}
		else if (words[i] == 'j') {
			if (words[i - 1] == 'l' || words[i - 1] == 'n') {
				++word_num;
			}
		}
	}

	cout << words.length() - word_num;

	return 0;
}

이 코드의 문제점은 주석을 달아 둔 위치에 있다. 반복문은 i가 1일때부터 진행하는데, 만일 입력으로 "z=da" 가 주어졌을 경우, '=' 를 찾은 순간 word배열의 0번인덱스를 확인하고, 0번인덱스가 'z' 임을 확인하고, word[-1] 인덱스에 접근하게 된다. 이 때문에 오류가 나야 정상이지만, 테스트 케이스가 부족한 듯 보였다.

 

이 오류를 발견하고 나서 아래처럼 예외를 추가 해 주었다.

#include <iostream>

using namespace std;

int main() {
	string words;
	cin >> words;

	int word_num = 0;

	for (int i = 1; i < words.length(); ++i) {
		if (words[i] == '=') {
			if (words[i - 1] == 'c' || words[i - 1] == 's') {
				++word_num;
			}
			else if (words[i - 1] == 'z') {
				if (i == 1) { // 1일때 예외처리
					++word_num;
				}
				else if (words[i - 2] == 'd') {
					word_num += 2;
				}
				else {
					++word_num;
				}
			}
		}
		else if (words[i] == '-') {
			if (words[i - 1] == 'c' || words[i - 1] == 'd') {
				++word_num;
			}
		}
		else if (words[i] == 'j') {
			if (words[i - 1] == 'l' || words[i - 1] == 'n') {
				++word_num;
			}
		}
	}

	cout << words.length() - word_num;

	return 0;
}

주석을 단 부분처럼 i가 1일때 단순히 조건문으로 예외처리를 해 주었다.

 

www.acmicpc.net/board/view/64574

 

글 읽기 - 테스트케이스 추가 요청드립니다.

댓글을 작성하려면 로그인해야 합니다.

www.acmicpc.net

현재 백준사이트에 테스트케이스를 추가해 달라는 요청을 올려 둔 상태이다.

----------------------------------------------------------------------------------------------------

2021.02.24 추가

테스트 케이스에 대한 댓글이 달렸다.

 

"배열의 범위를 벗어난 인덱스에 접근하는 것은 undefined behavior이기 때문에 정답을 받더라도 이상하지 않습니다." 라는 답변이었는데, 내용을 살펴보면 범위를 벗어난 배열접근에대해서는 UB처리 되어 정답처리가 된다고 한다. PS를 할때는 정답을 받을 수 있겠지만, 실제 프로그래밍을 할 때에는 주의해야 하는 부분이다.

반응형
Comments