나는 큰 메모리 상주 데이터베이스 내에 저장된 여러 다른 텍스트 배열을 반복 할 수있는 문제를 해결하려고했다 struct
.
다음은 MFC 테스트 응용 프로그램에서 Visual Studio 2017 Community Edition을 사용하여 해결되었습니다. 나는이 게시물이 내가 도움을 제공했지만 여전히 내 요구에 충분하지 않은 것을 가로 질러 여러 가지 중 하나 였기 때문에 이것을 예로 들어 설명하고 있습니다.
struct
포함하는 메모리 상주 데이터는 다음과 같은 것을 보았다. 간결성을 위해 대부분의 요소를 제거했으며 사용 된 전 처리기 정의도 포함하지 않았습니다 (사용중인 SDK는 C뿐만 아니라 C ++이며 오래되었습니다).
내가하고 싶은 것은 WCHAR
니모닉을위한 텍스트 문자열을 포함 하는 다양한 2 차원 배열에 대한 반복자를 갖는 것입니다 .
typedef struct tagUNINTRAM {
// stuff deleted ...
WCHAR ParaTransMnemo[MAX_TRANSM_NO][PARA_TRANSMNEMO_LEN]; /* prog #20 */
WCHAR ParaLeadThru[MAX_LEAD_NO][PARA_LEADTHRU_LEN]; /* prog #21 */
WCHAR ParaReportName[MAX_REPO_NO][PARA_REPORTNAME_LEN]; /* prog #22 */
WCHAR ParaSpeMnemo[MAX_SPEM_NO][PARA_SPEMNEMO_LEN]; /* prog #23 */
WCHAR ParaPCIF[MAX_PCIF_SIZE]; /* prog #39 */
WCHAR ParaAdjMnemo[MAX_ADJM_NO][PARA_ADJMNEMO_LEN]; /* prog #46 */
WCHAR ParaPrtModi[MAX_PRTMODI_NO][PARA_PRTMODI_LEN]; /* prog #47 */
WCHAR ParaMajorDEPT[MAX_MDEPT_NO][PARA_MAJORDEPT_LEN]; /* prog #48 */
// ... stuff deleted
} UNINIRAM;
현재 접근 방식은 템플릿을 사용하여 각 배열에 대한 프록시 클래스를 정의한 다음 배열을 나타내는 프록시 객체를 사용하여 특정 배열을 반복하는 데 사용할 수있는 단일 반복자 클래스를 사용하는 것입니다.
메모리 상주 데이터의 사본은 디스크에서 메모리 상주 데이터를 읽고 쓰는 것을 처리하는 객체에 저장된다. 이 클래스 CFilePara
에는 템플릿 프록시 클래스 ( MnemonicIteratorDimSize
및 파생 클래스 인 하위 클래스 MnemonicIteratorDimSizeBase
)와 반복자 클래스가 포함 MnemonicIterator
됩니다.
작성된 프록시 오브젝트는 모든 프록시 클래스가 파생 된 기본 클래스가 설명하는 인터페이스를 통해 필요한 정보에 액세스하는 반복자 오브젝트에 첨부됩니다. 결과적으로 서로 다른 프록시 클래스가 모두 동일한 인터페이스 (프록시 기본 클래스의 인터페이스)를 표시하므로 여러 가지 다른 프록시 클래스와 함께 사용할 수있는 단일 유형의 반복자 클래스가 있습니다.
첫 번째는 해당 유형의 니모닉에 대한 특정 프록시 객체를 생성하기 위해 클래스 팩토리에 제공되는 식별자 세트를 작성하는 것이 었습니다. 이러한 식별자는 사용자가보고 수정하려는 특정 프로비저닝 데이터를 식별하기 위해 사용자 인터페이스의 일부로 사용됩니다.
const static DWORD_PTR dwId_TransactionMnemonic = 1;
const static DWORD_PTR dwId_ReportMnemonic = 2;
const static DWORD_PTR dwId_SpecialMnemonic = 3;
const static DWORD_PTR dwId_LeadThroughMnemonic = 4;
프록시 클래스
템플릿 프록시 클래스와 기본 클래스는 다음과 같습니다. 여러 종류의 wchar_t
텍스트 문자열 배열 을 수용해야했습니다 . 2 차원 배열은 니모닉의 유형 (목적)에 따라 다른 니모닉 수를 가졌으며, 니모닉의 다른 유형은 최대 길이가 다르며 5 개의 텍스트 문자와 20 개의 텍스트 문자 사이에서 다양합니다. 파생 된 프록시 클래스의 템플리트는 각 니모닉에서 최대 문자 수를 요구하는 템플리트와 자연스럽게 맞았습니다. 프록시 객체가 생성 된 후 SetRange()
메소드를 사용하여 실제 니모닉 배열과 범위를 지정합니다.
// proxy object which represents a particular subsection of the
// memory resident database each of which is an array of wchar_t
// text arrays though the number of array elements may vary.
class MnemonicIteratorDimSizeBase
{
DWORD_PTR m_Type;
public:
MnemonicIteratorDimSizeBase(DWORD_PTR x) { }
virtual ~MnemonicIteratorDimSizeBase() { }
virtual wchar_t *begin() = 0;
virtual wchar_t *end() = 0;
virtual wchar_t *get(int i) = 0;
virtual int ItemSize() = 0;
virtual int ItemCount() = 0;
virtual DWORD_PTR ItemType() { return m_Type; }
};
template <size_t sDimSize>
class MnemonicIteratorDimSize : public MnemonicIteratorDimSizeBase
{
wchar_t (*m_begin)[sDimSize];
wchar_t (*m_end)[sDimSize];
public:
MnemonicIteratorDimSize(DWORD_PTR x) : MnemonicIteratorDimSizeBase(x), m_begin(0), m_end(0) { }
virtual ~MnemonicIteratorDimSize() { }
virtual wchar_t *begin() { return m_begin[0]; }
virtual wchar_t *end() { return m_end[0]; }
virtual wchar_t *get(int i) { return m_begin[i]; }
virtual int ItemSize() { return sDimSize; }
virtual int ItemCount() { return m_end - m_begin; }
void SetRange(wchar_t (*begin)[sDimSize], wchar_t (*end)[sDimSize]) {
m_begin = begin; m_end = end;
}
};
반복자 클래스
반복자 클래스 자체는 다음과 같습니다. 이 클래스는 현재 필요한 모든 정방향 반복자 기능 만 제공합니다. 그러나 추가 사항이 필요할 때 변경되거나 확장 될 것으로 기대합니다.
class MnemonicIterator
{
private:
MnemonicIteratorDimSizeBase *m_p; // we do not own this pointer. we just use it to access current item.
int m_index; // zero based index of item.
wchar_t *m_item; // value to be returned.
public:
MnemonicIterator(MnemonicIteratorDimSizeBase *p) : m_p(p) { }
~MnemonicIterator() { }
// a ranged for needs begin() and end() to determine the range.
// the range is up to but not including what end() returns.
MnemonicIterator & begin() { m_item = m_p->get(m_index = 0); return *this; } // begining of range of values for ranged for. first item
MnemonicIterator & end() { m_item = m_p->get(m_index = m_p->ItemCount()); return *this; } // end of range of values for ranged for. item after last item.
MnemonicIterator & operator ++ () { m_item = m_p->get(++m_index); return *this; } // prefix increment, ++p
MnemonicIterator & operator ++ (int i) { m_item = m_p->get(m_index++); return *this; } // postfix increment, p++
bool operator != (MnemonicIterator &p) { return **this != *p; } // minimum logical operator is not equal to
wchar_t * operator *() const { return m_item; } // dereference iterator to get what is pointed to
};
프록시 객체 팩토리는 니모닉 식별자를 기반으로 생성 할 객체를 결정합니다. 프록시 오브젝트가 작성되고 리턴되는 포인터는 표준 니즈 닉 섹션 중 어느 것이 액세스되는지에 상관없이 균일 한 인터페이스를 갖도록 표준 기본 클래스 유형입니다. 이 SetRange()
방법은 프록시 객체가 프록시가 나타내는 특정 배열 요소와 배열 요소의 범위를 지정하는 데 사용됩니다.
CFilePara::MnemonicIteratorDimSizeBase * CFilePara::MakeIterator(DWORD_PTR x)
{
CFilePara::MnemonicIteratorDimSizeBase *mi = nullptr;
switch (x) {
case dwId_TransactionMnemonic:
{
CFilePara::MnemonicIteratorDimSize<PARA_TRANSMNEMO_LEN> *mk = new CFilePara::MnemonicIteratorDimSize<PARA_TRANSMNEMO_LEN>(x);
mk->SetRange(&m_Para.ParaTransMnemo[0], &m_Para.ParaTransMnemo[MAX_TRANSM_NO]);
mi = mk;
}
break;
case dwId_ReportMnemonic:
{
CFilePara::MnemonicIteratorDimSize<PARA_REPORTNAME_LEN> *mk = new CFilePara::MnemonicIteratorDimSize<PARA_REPORTNAME_LEN>(x);
mk->SetRange(&m_Para.ParaReportName[0], &m_Para.ParaReportName[MAX_REPO_NO]);
mi = mk;
}
break;
case dwId_SpecialMnemonic:
{
CFilePara::MnemonicIteratorDimSize<PARA_SPEMNEMO_LEN> *mk = new CFilePara::MnemonicIteratorDimSize<PARA_SPEMNEMO_LEN>(x);
mk->SetRange(&m_Para.ParaSpeMnemo[0], &m_Para.ParaSpeMnemo[MAX_SPEM_NO]);
mi = mk;
}
break;
case dwId_LeadThroughMnemonic:
{
CFilePara::MnemonicIteratorDimSize<PARA_LEADTHRU_LEN> *mk = new CFilePara::MnemonicIteratorDimSize<PARA_LEADTHRU_LEN>(x);
mk->SetRange(&m_Para.ParaLeadThru[0], &m_Para.ParaLeadThru[MAX_LEAD_NO]);
mi = mk;
}
break;
}
return mi;
}
프록시 클래스 및 반복자 사용
프록시 클래스와 해당 반복기는 다음 루프와 같이 CListCtrl
니모닉 목록으로 객체 를 채우는 데 사용됩니다 . 내가 사용하고 std::unique_ptr
프록시 클래스가 내가하지 이상 필요하고,이 때 너무 std::unique_ptr
범위를 벗어나, 메모리가 정리됩니다.
이 소스 코드가 struct
하는 것은 지정된 니모닉 식별자에 해당하는 배열에 대한 프록시 객체를 만드는 것 입니다. 그런 다음 해당 개체의 반복자를 만들고 범위 for
를 사용하여 CListCtrl
컨트롤 을 채우고 정리합니다. 이들은 모두 wchar_t
배열 요소의 수일 수있는 모든 원시 텍스트 문자열이므로 텍스트가 0으로 종료되지 않도록 문자열을 임시 버퍼에 복사합니다.
std::unique_ptr<CFilePara::MnemonicIteratorDimSizeBase> pObj(pFile->MakeIterator(m_IteratorType));
CFilePara::MnemonicIterator pIter(pObj.get()); // provide the raw pointer to the iterator who doesn't own it.
int i = 0; // CListCtrl index for zero based position to insert mnemonic.
for (auto x : pIter)
{
WCHAR szText[32] = { 0 }; // Temporary buffer.
wcsncpy_s(szText, 32, x, pObj->ItemSize());
m_mnemonicList.InsertItem(i, szText); i++;
}