আমি বেশ কয়েকটি বিভিন্ন পাঠ্য অ্যারেগুলিতে পুনরাবৃত্তি করতে সক্ষম হওয়ার সমস্যাটি সমাধান করার চেষ্টা করছিলাম যা সমস্তই একটি মেমরি বাসিন্দার ডাটাবেসের মধ্যে সংরক্ষণ করা হয় যা একটি বিশাল struct
।
নিম্নলিখিতটি একটি এমএফসি পরীক্ষা অ্যাপ্লিকেশনটিতে ভিজ্যুয়াল স্টুডিও 2017 সম্প্রদায় সংস্করণ ব্যবহার করে কাজ করা হয়েছিল। আমি এটি উদাহরণ হিসাবে অন্তর্ভুক্ত করছি কারণ এই পোস্টিংটি এমন বেশ কয়েকটিগুলির মধ্যে একটি যা আমি দৌড়ে গিয়েছিলাম যে এখনও কিছু সহায়তা সরবরাহ করা হয়েছে যা এখনও আমার প্রয়োজনের জন্য অপর্যাপ্ত ছিল।
struct
ধারণকারী মেমরির বাসিন্দা ডেটাকে নিম্নলিখিত ভালো কিছু লাগছিল। আমি বংশবৃদ্ধির জন্য বেশিরভাগ উপাদানগুলি সরিয়ে দিয়েছি এবং ব্যবহৃত প্রিপ্রসেসর সংজ্ঞায়িতগুলিও অন্তর্ভুক্ত করি নি (ব্যবহৃত এসডিকে সি এর পাশাপাশি সি ++ এবং পুরানো)।
আমি যা করতে আগ্রহী তা হল বিভিন্ন WCHAR
দ্বিমাত্রিক অ্যারেগুলির জন্য আইট্রেটারগুলি রাখা যা স্মৃতিবিদ্যার জন্য পাঠ্য স্ট্রিং রয়েছে।
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
পাঠ্য স্ট্রিং অ্যারে সমন্বিত করা দরকার। দ্বিমাত্রিক অ্যারে মিমোনমিকের ধরণ (উদ্দেশ্য) এবং বিভিন্ন ধরণের স্মৃতিবিজ্ঞানের বিভিন্ন ধরণের বিভিন্ন স্তরের স্তরের স্তরের পাঁচটি পাঠ্য অক্ষর এবং বিশটি পাঠ্য অক্ষরের মধ্যে পৃথক পৃথক পৃথক সংখ্যা ছিল। উত্সযুক্ত প্রক্সি শ্রেণীর জন্য টেমপ্লেটগুলি প্রতিটি স্মৃতিবিদ্যায় সর্বাধিক সংখ্যক অক্ষরের প্রয়োজন টেমপ্লেট সহ একটি প্রাকৃতিক ফিট ছিল। প্রক্সি অবজেক্টটি তৈরি হওয়ার পরে, আমরা তারপরে 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;
}
প্রক্সি ক্লাস এবং Iterator ব্যবহার করে
প্রক্সি ক্লাস এবং তার পুনরুক্তিকরণগুলি স্মৃতিবিদ্যার CListCtrl
তালিকা সহ কোনও বস্তু পূরণ করতে নিম্নলিখিত লুপে প্রদর্শিত হিসাবে ব্যবহৃত হয় । আমি তাই ব্যবহার করছি std::unique_ptr
যাতে প্রক্সি ক্লাস যখন আমার আর প্রয়োজন হয় না এবং std::unique_ptr
সুযোগের বাইরে চলে যায়, তখন স্মৃতিটি পরিষ্কার হয়ে যায়।
এই উত্স কোডটি যা করে তা হ'ল অ্যারের মধ্যে একটি প্রক্সি অবজেক্ট তৈরি করা struct
যা নির্দিষ্ট স্তন্যপায়ী শনাক্তকরণের সাথে সম্পর্কিত। এটি তখন সেই অবজেক্টের জন্য একটি ইেটরেটর তৈরি করে, নিয়ন্ত্রণ for
পূরণের জন্য একটি ব্যাপ্তি ব্যবহার করে CListCtrl
এবং পরে পরিষ্কার করে। এগুলি সমস্ত কাঁচা wchar_t
পাঠ্য স্ট্রিং যা অ্যারে উপাদানগুলির সংখ্যা হুবহু তাই আমরা স্ট্রিংটি অস্থায়ী বাফারে অনুলিপি করতে পারি যাতে পাঠ্য শূন্য হয়ে যায়।
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++;
}