[C++] MFC 리스트(CList/CObList/CStringList) 및 POSITION 사용법

[C++] MFC 리스트(CList/CObList/CStringList) 및 POSITION 사용법

동일한 타입의 여러 데이터들을 저장할 수 있는 구조는

STL 컨테이너를 제외하고 대표적으로 배열과 리스트가 있다.

이번에는 리스트의 사용법과 대표적으로 사용되는 예시에대해서 알아보려고 합니다.

MFC에서 List형태의 자료구조는 다양하게 많은데

템플릿 리스트클래스는 CList가 있고

비 템플릿 리스트 클래스는 CObList, CStringList, CPtrList 정도가 있다.

CObList는 CObject 포인터를 데이터 타입으로 가지고,

CStringList는 CString을, CPtrList는 void 포인터를 데이터 타입으로 가진다.

CList를 사용하기 위해서는 "afxtempl.h" 헤더 파일을 #include 해줘야하고,

비템플릿 리스트 클래스들을 사용하기 위해서는 "afxcoll.h" 헤더를 #include 해줘야 한다.

개인적으로 가장 많이 사용하는 것은 CObList이다.

추가로 MFC의 CList 에 대한 자세한 정보는 MSDN을 참고하면 될 것 이다.

https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/bxde0zae(v=vs.110)?redirectedfrom=MSDN

MFC의 리스트 클래스들은 모두 양방향 연결 리스트로 Head와 Tail을 모두 가지고 있다.

양방향 연결리스트의 장점은 어떤 방향이로든 이동할 수 있어 원하는 위치에 편하게 접근 할 수 있다.

이제 간단한 사용법에 대해서 알아 볼건데, 가장 많이 사용되는 함수들 위주로 설명하려고 한다.

MFC 리스트의 각 항목에 대한 접근은 POSITION 타입을 사용하여 이뤄진다.

소스 예제

//템플릿 클래스를 사용하기 위해 헤더 추가 // .... // 나머지 헤더는 생략 #include using namespace std; CList exList; // 리스트의 뒤쪽에 데이터 삽입 for(int i = 0; i<10 ; i++) exList.AddTail(i); // 리스트의 앞쪽에 데이터 삽입 for(int i = 0 ; i<10 ; i++) exList.AddHead(i); // 전체 출력( 데이터 삽입, 삭제 전 ) // cout << "전 : " << endl; POSITION pos = exList.GetHeadPosition(); while(pos) { int output = exList.GetNext(pos); cout << output << " "; } cout << endl; // POSITION을 이용한 데이터 삽입 pos = exList.GetHeadPosition(); while(pos) { const int five = 5; int num = (int)exList.GetNext(pos); if( num == five ) { // 해당 position 기준으로 앞쪽에 100 삽입 exList.InsertBefore(pos, 100); // 해당 position 기준으로 뒤쪽에 200 삽입 exList.InsertAfter(pos, 200); // 해당 Position 위치 데이터 삭제 exList.RemoveAt(pos); } } // 전체 출력( 데이터 삽입, 삭제 후 ) // cout << "후 : " << endl; pos = exList.GetHeadPosition(); while(pos) { int output = exList.GetNext(pos); cout << output << " "; } cout << endl;

POSITION을 사용하여 리스트를 하나씩 GetNext(pos) 다음으로 넘겨가며 원하는 위치에 접근 할 수 있다.

양방향 연결리스트인 만큼 반대로 Next가 아닌 이전으로도 이동할 수 있는데, 이는 GetPrev(pos) 를 사용하면 된다.

또한 리스트의 처음 시작 위치가 중요한데, 처음부터 시작하고 싶다면 GetHeadPostion()을,

리스트의 마지막 부터 시작하고 싶다면 GetTailPosition()을 사용하고.

특정 위치에 접근하고싶다면 GetAt() 을 사용 하면된다.

위의 소스에서 나와있듯이 데이터의 삽입 함수는

리스트의 마지막에 데이터를 삽입하는 AddTail() 과 리스트의 앞부분에 삽입하는 AddHead() 가 있고,

특정위치에 넣고싶다면 InsertBefore() 나 InsertAfter() 를 사용하면 된다.

데이터의 삭제 함수는

특정위치 삭제는 RemoveAt(), 리스트 전체 데이터를 삭제하고 싶다면 RemoveAll() 을 사용 하면된다.

MFC 프로젝트를 진행하면서 리스트는 정말 많이 사용 되는 구조고,

그중에서도 CObject로 특정 템플릿 데이터를 만들어 저장 후

POSITION을 이용하여 원하는 위치를 얻어와 적절한 타입으로 형변환 하여 사용을 많이하게 된다.

자세히 설명하면 더 길어 지겠지만,

간략히 이정도만 알아도 어느정도 리스트를 사용하는데에는 문제가 크게 없을 것이다.

참고사항

GetNext()와 GetPrev() 를 사용할 때 헷갈릴 여지가 있는 부분이 존재하는데,

함수만 읽어보면 바로 다음 포인터로 넘겨주어

그 다음이나 이전부분의 노드정보를 가져올 것으로 보이지만,

위 함수들은 먼저 지금 노드의 정보를 남기고 그 후에 다음 위치로 넘어간다.

따라서 GetAt()을 사용하거나 특정 위치를 알아야 할 때

GetNext() 진행 전에 미리 저장을 해두는 방법을 사용 해야한다.

GetNext(pos) 호출 전에 GetAt(pos)해보고, GetNext(pos) 호출 후에 GetAt(pos)를 사용하여

직접 디버깅 해보면 바로 이해가 갈 것이다.

from http://skuin.tistory.com/33 by ccl(A) rewrite - 2021-09-09 16:01:00