본문 바로가기
C++/기초

C++ 기초 : tree (5)

글: 시플마 2024. 4. 27.

이제 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