3.1.2 vector에 순차적으로 보관

작성할 프로그램은 장르 관리 프로그램입니다. 장르에는 장르 번호와 장르명이 있습니다. 장르 번호는 순차적으로 부여하며 장르명은 사용자에게 입력받습니다. 장르 번호와 장르명으로 삭제할 수 있고 검색할 수 있습니다. 그리고 모든 장르 목록을 확인할 수 있습니다.

제공할 기능을 살펴보면 장르 추가, 장르 번호로 장르 삭제, 장르명으로 장르 삭제, 장르 번호로 검색, 장르명으로 검색, 모든 장르 목록 확인이 있어요.

vector에 순차적으로 보관할 때는 push_back 메서드를 사용하세요. 원하는 자료를 찾을 때는 반복자를 이용하여 찾거나 find, find_if 알고리즘을 이용하여 찾습니다. 삭제할 때는 자료가 있는 위치를 찾아 erase 메서드를 사용하세요. 모든 자료를 탐색할 때는 반복자를 이용하세요.

이 책에서는 프로그래밍을 통해 vector를 사용하는 방법을 소개할 것입니다. 따라서 vector에서 제공하는 다양한 멤버들 중에 작성할 프로그램에 필요한 멤버들만 소개하는 한계를 갖습니다. 대신 실제 프로그래밍에 자주 사용하는 것에 초점을 맞추기 때문에 실질적인 노하우를 터득할 수 있는 장점을 갖습니다.

 

먼저 장르를 구현한 후에 vector를 이용하여 구현하기로 할게요.

 

생성자에서는 입력 인자로 멤버 필드를 설정하세요.

 

접근자 메서드에서는 장르 번호와 장르명을 반환하세요.

 

콘솔 화면에 장르 정보를 출력하는 메서드도 정의하세요.

 

이제 장르를 관리할 형식을 정의합시다. 장르를 관리할 클래스를 App라 정할게요. vector를 사용하기 위해 vector 파일을 포함하세요.

find와 find_if 알고리즘을 사용하기 위해 algorithm 파일을 포함하세요.

사용할 이름을 using 문으로 작성하세요. using namespace std;로 간략하게 할 수 있지만 앞으로 우리는 STL에서 제공하는 이름과 같은 이름으로 만드는 실습도 할 거예요. 그 때 이름 충돌이 나지 않게 하기 위해 명확하게 사용할 이름을 using 문으로 작성하세요.

동적으로 생성한 장르를 보관할 vector를 Genres 이름으로 타입 재지정합시다. 타입 재지정하면 사용할 때 간략하게 표현할 수 있어 사용하기 편합니다.

반복자는 STL의 자료구조마다 내부에 iterator 이름으로 정의하고 있습니다. 이를 GIter 이름으로 타입 재지정하세요.

상수화 메서드에서 반복자를 사용할 수 있게 const_iterator도 제공하고 있어요. 마찬가지로 GCIter 이름으로 타입 재지정하세요.

 

이제 App 클래스의 메서드들을 구현합시다.

 

메뉴를 출력하고 입력한 키를 반환하는 메서드를 구현하세요.

 

장르를 추가하는 메서드를 구현합시다.

 

테스트를 쉽게 하기 위해 장르 목록 보기 기능을 먼저 구현하기로 해요.

 

이번에는 번호로 장르 삭제 기능을 구현합시다. 장르 목록 보기 기능처럼 반복자를 이용하여 원하는 번호의 장르의 위치를 구할 수도 있습니다. 여기에서는 다른 방법을 사용할게요.

STL에서는 find와 find_if 알고리즘을 제공하여 원하는 위치를 찾을 수 있습니다. find 알고리즘은 검색할 구간(구간의 시작과 끝)과 검색할 자료를 입력 인자로 전달하면 처음 발견한 위치를 반환합니다. 그리고 find_if 알고리즘은 검색할 구간과 함수 호출이 가능한 표현(함수명 혹은 함수 호출 연산자를 정의한 개체)을 입력 인자로 전달하면 처음으로 함수 호출 연산의 결과가 참인 위치를 반환합니다.

find_if에 전달할 함수의 원형은 입력 인자로 보관한 형식이 오고 반환 형식이 참과 거짓인지 판별할 수 있어야 합니다. 함수 개체를 전달한다면 해당 개체도 입력 인자로 보관한 형식이 오고 반환 형식이 참과 거짓인지 판별할 수 있는 함수 호출 연산을 정의하고 있어야 합니다.

STL의 find_if를 따라가 보면 다음과 같은 _Find_if를 호출하는 부분까지 도달합니다.

 

템플릿 인자를 두 개 정의하고 있죠. 입력 인자로 받은 두 개의 형식은 같고 세 번째 인자는 다른 것을 알 수 있습니다. 그리고 for문에서 두 개의 인자를 비교하여 다를 때까지 반복하고 있으며 첫 번째 입력 인자를 받은 변수를 증가하는 것을 알 수 있어요.

그리고 세 번째 입력 인자로 받은 형식에 입력 인자로 첫 번째 입력 매개 변수에 간접 연산을 하고 있으며 결과가 참일 때 반복문을 탈출하여 첫 번째 입력 매개 변수를 반환하고 있어요.

find_if 알고리즘에서는 검색 구간(첫 번째 인자는 검색 구간의 시작, 두 번째 인자는 검색 구간의 마지막)과 함수(혹은 함수 개체)를 인자로 받아 구간 내에 보관한 자료를 함수에 적용했을 때 참인 부분을 만나면 반복문을 탈출하여 해당 위치를 반환하고 있음을 알 수 있어요.

이와 같은 정보만 가지고 STL을 사용하는 것은 어느 정도 노하우를 갖고 있지 않다면 어려운 일입니다. 다행히 find나 find_if 알고리즘을 사용하지 않아도 반복자를 이용하여 원하는 구현을 할 수 있죠. 하지만 이와 같은 표현을 사용할 수 있다면 앞으로 프로그래밍할 때 이러한 매커니즘으로 만들어진 라이브러리를 사용할 수 있기 때문에 도전해 볼만한 가치가 있어요.

실제 이와 같은 매커니즘은 이벤트 처리하는 곳에서는 매우 흔한 작업입니다. 여러분께서 이와 같은 부분을 캐치하지 못하더라도 라이브러리 사용을 자주하면서 익힐 수도 있을 거예요.

다음은 번호로 보관한 장르를 찾고자 할 때 정의한 클래스입니다.

 

번호로 장르 삭제 기능을 구현합시다.

 

같은 방법으로 장르명으로 도서 삭제 기능을 구현합시다. 먼저 검색할 이름으로 보관한 장르를 찾을 때 사용할 클래스를 정의해야겠죠.

 

이름으로 장르 삭제하는 기능을 구현합시다.

 

이제 번호로 장르 검색 기능을 구현합시다.

 

이름으로 장르 검색 기능도 구현하세요.

 

소멸자에서는 자신이 생성한 장르 개체를 모두 소멸해야겠죠.

 

STL을 사용하는 것이 처음인 분들은 낯설 수 있을 거예요. 하지만 STL에서 제공하는 대부분의 자료구조는 사용 방법이 비슷하며 점차 노하우가 생길 거예요. 프로그래밍 언어 문법을 학습하거나 자료구조, 알고리즘을 학습하는 것과 다르게 제공하는 라이브러리는 자주 사용하여 사용 방법에 익숙해 지는 것이라 할 수 있습니다. 물론 이 책에서는 알고리즘과 자료구조를 설명하는 책이며 STL 사용법을 소개하는 이유는 우리가 작성할 자료구조의 모델이기 때문입니다. 물론 STL 사용법을 익히는 것 자체도 의미있는 일임에 틀림없구요.