C++Builder Programming Forum
C++Builder  |  Delphi  |  FireMonkey  |  C/C++  |  Free Pascal  |  Firebird
볼랜드포럼 BorlandForum
 경고! 게시물 작성자의 사전 허락없는 메일주소 추출행위 절대 금지
C++빌더 포럼
Q & A
FAQ
팁&트릭
강좌/문서
자료실
컴포넌트/라이브러리
메신저 프로젝트
볼랜드포럼 홈
헤드라인 뉴스
IT 뉴스
공지사항
자유게시판
해피 브레이크
공동 프로젝트
구인/구직
회원 장터
건의사항
운영진 게시판
회원 메뉴
북마크
볼랜드포럼 광고 모집

컴포넌트/라이브러리
Delphi/C++Builder Programming Components&Libraries
[441] 구조체를 동적 배열로 관리할 수 있는 클래스
김태선 [] 12250 읽음    2006-02-24 11:32
빌더에는 기본으로 DynamicArray가 내장되어 있습니다.
델파이의 다이나믹 어레이를 옮길때 사용하기 위해 제공하고 있는데,
사용법이 간단하고 쓰기 좋으나, TList 처럼  항목을 Add Delete 할수 없는
단점이 있습니다.

VC++의 ATL/WTL에 CSimpleArray라는 클래스가 있는데,
역시 다이나믹 어레이를 지원하는 템플릿 클래스로 Add Remove 와
DynamicArray 같이 바로 [ ] 로 배열로 참조할 수 있는,
데이타를 동적으로 관리할 수 있게 지원하는 클래스입니다.

구조체나 클래스를 동적배열로 관리하는 일은 플젝에서 매우
빈번하게 요구되는 일로, 쓸만한 클래스를 익혀 두는 것은 중요한 일입니다.

DynamicArray 가 다소 불편해서, WTL에서 CSimpleArray 클래스를 추출해
빌더에서 사용할 수 있게 수정했습니다.
일부 함수의 기능도 약간 수정했습니다.
물론, 빌더 뿐만 아니라 VC++에서도 이용가능합니다.

아래는 소스고 사용은 첨부파일을 이용하세요.
사용법은 소스 잠깐만 훑어 보시면 아실겁니다.
WTL를 가져다 쓸때 명칭이 중복될 수 있으므로, CSArray로 바꾸었습니다.

#ifndef CSimpleArrayH
#define CSimpleArrayH

#include <assert.h>
//---------------------------------------------------------------------------

inline void __declspec(noreturn) _AtlRaiseException( DWORD dwExceptionCode, DWORD dwExceptionFlags = EXCEPTION_NONCONTINUABLE )
{
    RaiseException( dwExceptionCode, dwExceptionFlags, 0, NULL );
}

// Simple Struct Array class (WTL의 CSimpleArray를 수정 개선함)

template <class T> class CSArray
{
    #define ATLASSERT        assert
public:
    CSArray() : m_aT(NULL), m_nSize(0), m_nAllocSize(0)
    {
    }
    ~CSArray()
    {
        RemoveAll();
    }

    CSArray(const CSArray<T>& src) : m_aT(NULL), m_nSize(0), m_nAllocSize(0)
    {
        m_aT = (T*)malloc(src.GetSize() * sizeof(T));
        if (m_aT != NULL)
        {
            m_nAllocSize = src.GetSize();
            for (int i=0; i<src.GetSize(); i++)
                Add(src[i]);
        }
    }
    CSArray<T>& operator=(const CSArray<T>& src)
    {
        if (GetSize() != src.GetSize())
        {
            RemoveAll();
            m_aT = (T*)malloc(src.GetSize() * sizeof(T));
            if (m_aT != NULL)
                m_nAllocSize = src.GetSize();
        }
        else
        {
            for (int i = GetSize(); i > 0; i--)
                RemoveAt(i - 1);
        }
        for (int i=0; i<src.GetSize(); i++)
            Add(src[i]);
        return *this;
    }

    // Operations
    int GetSize() const
    {
        return m_nSize;
    }
    int  Add(const T& t)
    {
        if(m_nSize == m_nAllocSize)
        {
            T* aT;
            int nNewAllocSize = (m_nAllocSize == 0) ? 1 : (m_nSize * 2);
            aT = (T*)realloc(m_aT, nNewAllocSize * sizeof(T));
            if(aT == NULL)
                return -1;
            m_nAllocSize = nNewAllocSize;
            m_aT = aT;
        }
        InternalSetAtIndex(m_nSize, t);
        return m_nSize++;
    }
    bool Remove(const T& t)
    {
        int nIndex = Find(t);
        if(nIndex == -1)
            return false;
        return RemoveAt(nIndex);
    }
    bool RemoveAt(int nIndex)
    {
        ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
        if (nIndex < 0 || nIndex >= m_nSize)
            return false;
        m_aT[nIndex].~T();
        if(nIndex != (m_nSize - 1))
            memmove((void*)(m_aT + nIndex), (void*)(m_aT + nIndex + 1), (m_nSize - (nIndex + 1)) * sizeof(T));
        m_nSize--;
        return true;
    }
    void RemoveAll()
    {
        if(m_aT != NULL)
        {
            for(int i = 0; i < m_nSize; i++)
                m_aT[i].~T();
            free(m_aT);
            m_aT = NULL;
        }
        m_nSize = 0;
        m_nAllocSize = 0;
    }
    const T& operator[] (int nIndex) const
    {
        ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
        if(nIndex < 0 || nIndex >= m_nSize)
        {
            _AtlRaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
        }
        return m_aT[nIndex];
    }
    T& operator[] (int nIndex)
    {
        ATLASSERT(nIndex >= 0 && nIndex < m_nSize);
        if(nIndex < 0 || nIndex >= m_nSize)
        {
            _AtlRaiseException(EXCEPTION_ARRAY_BOUNDS_EXCEEDED);
        }
        return m_aT[nIndex];
    }
    T* GetData() const
    {
        return m_aT;
    }

    int Find(const T& t) const
    {
        for(int i = 0; i < m_nSize; i++)
        {
            if(TEqual::IsEqual(m_aT[i], t))
                return i;
        }
        return -1;  // not found
    }

    BOOL SetAtIndex(int nIndex, const T& t)
    {
        if (nIndex < 0 || nIndex >= m_nSize)
            return FALSE;
        InternalSetAtIndex(nIndex, t);
        return TRUE;
    }

    // Implementation
    class Wrapper
    {
    public:
        Wrapper(const T& _t) : t(_t)
        {
        }
        template <class _Ty>
        void * __cdecl operator new(size_t, _Ty* p)
        {
            return p;
        }
        template <class _Ty>
        void __cdecl operator delete(void* /* pv */, _Ty* /* p */)
        {
        }
        T t;
    };

    // Implementation
    void InternalSetAtIndex(int nIndex, const T& t)
    {
        new(m_aT + nIndex) Wrapper(t);
    }

    //typedef T _ArrayElementType;
    T* m_aT;
    int m_nSize;
    int m_nAllocSize;

};

//---------------------------------------------------------------------------
#endif

+ -

관련 글 리스트
441 구조체를 동적 배열로 관리할 수 있는 클래스 김태선 12250 2006/02/24
Google
Copyright © 1999-2015, borlandforum.com. All right reserved.