'2007/11/21'에 해당되는 글 2건

  1. 2007.11.21 [MFC 탐색] CList 에서 GetNext 의 함정 by system
  2. 2007.11.21 [MFC 탐색] CList by system
CList 를 사용하여 데이터를 List 구조 안에 차근차근 넣다가보면
특정 위치에서 데이터를 찾을때 GetNext 라는 CList 의 멤버 함수를 사용하게 마련이다.
이때, 헷갈리기 쉬운 것이, GetNext 라고 하면 현재 위치의 다음 위치에 있는
데이터를 내 놓으라고 하는 것 같지만
사실은 현재 위치의 데이터를 뱉어낸 다.음.에 그 다음 위치로 넘어간다는 것이다.
따라서, GetNext 로 나온 데이터만 보고 , 아... 여기에다 업데이트 해야지 잇힝~ 하고는
SetAt 을 사용해버리면, 원하는 위치가 아닌, 그 다음 위치에 데이터 업데이트가 되기 때문에
무척이나 조심해야 한다.
이것이 바로 GetNext 의 함정인 것이다!!! (뭔... 명탐정 코난이냐...)

예제를 통해 확인해보자.

일단 CList 를 사용한 list 구조를 만든다. 헤더에...
int 형의 m_iTest 와 CString 형의 m_strTest 라는 두개의 변수를 가지고 있는 List 구조체? 이다.

class CTest
{
public:
 CTest() {}
 CTest(int m_iTest, CString &m_strTest) { CTest::m_iTest = m_iTest; CTest::m_strTest = m_strTest; }
 void operator=(CTest& test) { m_iTest = test.m_iTest; m_strTest = test.m_strTest; }
 int m_iTest;
 CString m_strTest;
};

정의한 CTest 를 사용해야지
cpp 파일에는 다음과 같은 내용이 들어간다.

CList<CTest, CTest&> m_Test;

// 데이터를 추가해보자
// int 형의 숫자들과, CString 형의 문자열이 차근차근 들어간다.
m_Test.AddHead(CTest(1, CString("a")));
m_Test.AddHead(CTest(2, CString("b")));
m_Test.AddHead(CTest(3, CString("c")));

// 맨 처음의 위치를 받아온다.
POSITION pos = m_Test.GetHeadPosition();
int i = 0;

// 데이터 중 2 가 있으면 4로 바꾸고, CString 형의 문자열도 b 를 d 로 바꾼다는 내용.
while(i<m_Test.GetCount())
{
     CTest test = m_Test.GetNext(pos);
     if(test.m_iTest == 2)
     {
          test.m_iTest = 4;
          test.m_strTest = "d";
          m_Test.SetAt(pos, test);
          break;
     }
     i++;
}

자, 여기서 GetNext 함수를 사용했다.
2가 발견되면 4로 바꾸고 문자열도 d 로 바꾼다.
하지만 CTest 의 내부를 보면 다음 처럼 바뀌어 있다.
// AddHead 를 했으므로 마지막에 한 3, c 가 맨 앞에 있게 된다.
3, c
2, b
4, d

처음의 의도는 2, b 가 들어있는 데이터를 4, d 로 바꾸는 것이었는데
2, b 는 멀쩡하고, 1, a 가 4, d 로 바뀌어 버렸다.
앞서 말한대로, GetNext 를 쓰면
현재의 위치에 있는 데이터를 반환한 뒤 다음 위치로 넘어가기 때문.이다.
따라서, m_Test.SetAt(pos, test) 를 한 시점에서 pos 는
2, b 가 아니라 1, a 의 position 인 것이다 !!!

올바르게 2, b 를 바꾸려고 한다면
다음처럼 해야 한다.

while(i<m_Test.GetCount())
{
     CTest test = m_Test.GetAt(pos);
     if(test.m_iTest == 2)
     {
          test.m_iTest = 4;
          test.m_strTest = "d";
          m_Test.SetAt(pos, test);
          break;
     }
     i++;
     test.GetNext(pos);
}

먼저 GetAt 를 이용하여 정확하게 현재 위치의 데이터를 받아 온 후
조건에 맞으면 SetAt 으로 업데이트를 시켜주고 나서
GetNext 로 다음 위치로 넘어가야 한다.

실험 성공.

출처 : http://lafirr.tistory.com/8
Posted by system
l

인클루드 <afxtempl.h>


CList<타입,타입&> list;


여기서 POSITION (pos)를 따로 선언하여 필요할 때 사용.

<-  Tail  ---------------  Head  ->

<-  Next  ---------------  Prev  ->

<-  After  ---------------  Before  ->


List 안에 있는 값을 얻을 때 개수 범위가 넘었는지를 확인 해주어야 한다. 안그러면 ASSERT 발동


Head/Tail 접근

GetHead list의 head element를 리턴한다. (empty면 할 수 없다).
GetTail list의 tail element를 리턴한다.(empty면 할 수 없다).

Operations(조정)

AddHead

하나의 element(또는 다른 list의 모든element들)을 list의 head에 추가한다(새로운 head를 만든다).

AddTail

하나의 element(또는 다른 list의 모든element들)을 list의 tail에 추가한다(새로운 tail를 만든다).

RemoveAll list의 모든 element를 제거한다.
RemoveHead list의 head로부터 element를 제거한다.
RemoveTail list의 tail로부터 element를 제거한다.

Iteration(반복)

GetHeadPosition head의 position을 리턴한다.
GetNext

(position이) 반복되어 다음 element로 도달한다.(원래 인수로 넣었던 position의 값으로 리턴하고 position을 다음 위치로 바꿔진다)

GetPrev

(position이) 반복되어 이전 element로 도달한다.(원래 인수로 넣었던 position의 값으로 리턴하고 position을 이전 위치로 바꿔진다)

GetTailPosition tail  position을 리턴한다.

Retrieval(정정)/Modification(수정)

GetAt 주어진 position에서 element(값)을 얻는다.
RemoveAt position에 의해 정해진 element 를 list로부터 제거한다.
SetAt 주어진 position에서 element(값)을 넣는다.

Insertion(삽입)

InsertAfter 주어진 position 뒤에 새로운 element를 삽입한다.
InsertBefore 주어진 position 앞에 새로운 element를 삽입한다.

Searching(찾기)

Find pointer 값에 의해 정해진 position을 얻는다.
FindIndex zero-based index 값에 의해 정해진 position을 얻는다.

Status(상태)

GetCount list의 element 개수를 리턴한다
GetSize list의 element 개수를 리턴한다
IsEmpty 비어있는 상태인지 검사한다.(no elements).

출처 : http://blog.naver.com/yjh1990?Redirect=Log&logNo=130020477353

Posted by system
l