이제 find 함수를 통해
찾은 노드에 실질적으로 저장된
데이터를 출력하기 위한 코드를 작성합시다.
61번째 줄에 있는 if 문에 걸리지않아
else 구문으로 넘어갔다면 find 함수를 통해
찾은 노드가 존재한다는 의미겠죠?
67 ~ 68번째 줄에서
find 함수가 찾은 노드를 iterator로 반환합니다.
이를 기존에 있던 iterator에 대입하였으니
이제 iterator는 찾은 노드를 가리키게 되죠.
해당 노드에는 pair가 들어 있으며
pair의 두 번째 멤버에는 학생 정보가 들어 있습니다.
이 학생 정보에는 이름이 들어 있죠.
그래서 iterator가 가리키는 pair에 접근하고
여기서 학생 정보가 들어 있는 두 번째 멤버에 접근합니다.
그 학생 정보에 들어 있는 이름을 출력하는 것이죠.
마찬가지로 나이 또한 학생 정보에 들어 있는
나이를 출력하는 것입니다.
성별은 define 지시문을 통해
1이면 남자, 2면 여자로 설정해줬죠?
그래서 바로 출력하면 1 또는 2가 출력될 것입니다.
우리는 성별은 문자로 출력하고 싶습니다.
iterator가 가리키는 pair에 접근하여
학생 정보가 들어 있는 두 번째 멤버에 접근한 후
gender라는 멤버 변수의 값과 MAN과 같은지,
즉 1과 같은지 비교합니다. 맞다면 "남자"라는 문자열을 출력하죠.
만약 위에 해당하지 않는다면
iterator가 가리키는 pair에 접근하여
학생 정보가 들어 있는 두 번째 멤버에 접근한 후
gender라는 멤버 변수의 값과 WOMAN과 같은지,
즉 2와 같은지 비교합니다. 맞다면 "여자"라는 문자열을 출력하죠.
위 두 경우에 해당하지 않는다면
성별이 잘못 입력된 것으로 간주하고
성별을 알 수 없다는 문자열을 출력합니다.
참고로 한글을 표현하기 위해 이름을
문자 하나를 2Byte로 보는 와이드 문자열로
받기도 하였고 출력되는 안내 문자열이
모두 한글이기 때문에 wcout를 통해 유니코드
문자열을 출력할 수 있게 하는 겁니다.
또한 59번째 코드를 추가하여
지역 설정을 "korean"으로 해 줘야
wcout을 사용하여 와이드 문자열 출력 시
한글이 제대로 출력됩니다.
const wchar_t 포인터는 문자열의 주솟값을
저장하는 자료형이죠?
map의 첫 번째 typename을
const wchar_t 포인터로 하였습니다.
이는 문제가 있습니다.
첫 번째 typename에 지정된
자료형을 키-값으로 하여
트리를 구성하게 될텐데, 이 키-값의
자료형을 const wchar_t 포인터로 하면
주솟값을 비교하여 더 큰 주솟값을 가진
데이터를 오른쪽에 더 작은 주솟값을 가진
데이터를 왼쪽에 배치하게 될 겁니다.
이는 이름(문자열)을 비교하여
트리를 구성하려고 했던 의도와는 다르죠.
문자열을 비교하여 트리를 구성하려면
map의 키-값의 자료형을 결정하는
첫 번째 typename을 wstring으로 해줘야 합니다.
std라는 namespace에 구현되어 있어
범위 지정 연산자 없이 바로 사용하기 위해
using std::wstring; 코드를 추가해 줍니다.
그럼 우선 wstring에 대해서 알아 보죠.
wstring은 클래스로 객체를 하나 만들 수 있습니다.
그리고 와이드 문자열을 대입할 수 있죠.
여기서 중요한 점은 wchar_t형 포인터처럼
ROM(Read-Only Memory)에 있는 문자열을
가리키는 게 아니라 문자열을 직접 복사하여 저장한다는 것이죠.
(이때 wstring형 객체 안에 큰 공간이
미리 할당되어 있는 게 아니라 데이터가 들어갈 공간이
필요할 때마다 동적 할당하는 것이겠죠?)
그래서 const를 붙일 필요가
없습니다. 필요에 따라 수정할 수도 있거든요.
덕분에 문자열을 수정할 수도 있고
문자열을 이어 붙일 수 있도록
+ 연산도 가능한 겁니다.
마치 배열처럼 인덱스 번호로
접근하여 값을 대입하는 것도 가능하고요.
또한 wstring형 객체끼리 서로
비교할 수 있는 비교 연산자도 제공되어
같은지 다른지, 어느 쪽이 더 크고 작은지
비교할 수도 있습니다.
객체가 저장하고 있는 문자를 하나씩,
사전순을 기준으로 비교할 겁니다.
이러한 wstring을 map에 첫 번째 typename으로
하면 어떤 동작이 발생할까요?
처음에 "이민수"라는 문자열과 학생 정보가
하나의 pair로 묶이고 이것이
트리의 루트 노드가 될 것입니다.
다음에는 "최유리"라는 문자열과 학생 정보가
하나의 pair로 묶이고 이것을 삽입하려는 순간,
기존에 있던 루트 노드의 키-값 "이민수"와
현재 삽입하려면 노드의 키-값 "최유리"와
비교 연산을 진행하겠죠. 비교하여
"최유리"가 더 크면 오른쪽의 자식 노드로
더 작으면 왼쪽의 자식 노드로 배치되겠죠.
이 경우 '이'보단 '최'가 사전순으로 뒤에 있기
때문에 문자열 "최유리"가 더 크다고 판단하여
오른쪽 자식 노드로 배치되겠군요.
그러면 직접 만든 클래스도 map으로
트리를 구성할 때의 키-값 자료형으로 사용할 수 있지 않을까
라는 생각이 들어 클래스를 하나 만들고 진행해 보겠습니다.
위와 같은 간단한 클래스를 하나 만들고
typename을 방금 만든 클래스와 학생 정보를
담는 클래스로 지정하고 노드를 삽입하려고 하자
오류가 발생합니다.
< 연산자가 없다는 내용입니다.
MyClass라는 클래스로 만든 객체를
비교하여 트리를 구성해야 하죠?
MyClass는 기본 자료형이 아니기 때문에
비교 연산자를 오버로딩해 줘야 비교 시에
어떤 기준으로 비교할지 인지가 가능합니다.
그래서 아래 코드처럼
< 연산자를 오버로딩해 줘야
MyClass형 객체를 비교할 수가 있겠죠.
비교만 하면 되기 때문에 const MyClass형 레퍼런스로
객체를 받아 < 연산자를 호출한(왼쪽 객체) 객체보다
인자로 받은(오른쪽 객체)가 더 크면 true를 반환하고
아니면 false를 반환하는 함수입니다. 완벽하지는 않지만
저런 동작을 하는 연산자를 오버로딩해 줘야
노드의 배치가 이루어질 수 있겠죠.
해당 함수를 추가하면
오류가 발생하지 않는 것을 확인할 수 있습니다.
강의 출처 : https://www.youtube.com/watch?v=PFc4g8mxOiI&list=PL4SIC1d_ab-aOxWPucn31NHkQvNPHK1D1&pp=iAQB
'C++ > 기초' 카테고리의 다른 글
C++ 기초 : enum (0) | 2024.04.29 |
---|---|
C++ 기초 : tree (6) (0) | 2024.04.27 |
C++ 기초 : tree (4) (0) | 2024.04.26 |
C++ 기초 : tree (3) (0) | 2024.04.26 |
C++ 기초 : tree (2) (0) | 2024.04.26 |