容器‎ > ‎

cxxlComposite

這個容器提供無限分枝、無限層級的樹狀結構,每個節點都是用 cxxlComposite 來組成,所以各節點的操作方式都一樣,cxxlComposite 的特性如下:

  • 有一個名稱,但名稱字串不可以含有 L"←┼→" 這個子字串,因內部用這字串做分隔識別
  • 每個節點可包裹 0 或 1 個 cxxlObject 的物件
  • 可包含 0 或 無限多個子節點
  • 子節點以建立的先後順序排列,也可指定新節點的插入位置
  • 尋找子節點的方法採用以名稱為鍵值的二分搜尋法,速度極快

cxxlComposite 的類別宣告格式如下:

/*
 T = 要包裝的物件型別,須是 cxxlObject 的延伸類別
 isUnique = 子節點的名稱不可重複設為 true,否則為 false 
*/
template <typename T, bool isUnique>
class cxxlComposite:virtual public cxxlObject
 
 

cxxlComposite 建構函數宣告如下:

cxxlComposite(UNICODE_String &idName,ISpirit *spirit = Spirit_Easy)

 

以下列出 cxxlComposite 提供的功能:

基本功能

 
GetCount() 取得子節點的個數
GetName() 取得這個節點自己的名稱
 
GetObj() 取得這個節點自己包裹的物件,若不存在回覆空物件,可用 Smart_Ptr::isNULL() 檢查
GetObj(const UNICODE_String &idName) 取得指定子節點包裹的物件,若不存在回覆空物件,可用 Smart_Ptr::isNULL() 檢查
   
SetObj(const Smart_Ptr<T> &Obj) 在這個節點設定物件
Add(const Smart_Ptr<T> &Obj, const UNICODE_String &idName) 將物件放入一個指定名稱的新子節點,成功傳回放入的節點,失敗傳回空物件,可用 Smart_Ptr::isNULL() 檢查
AddPrev(const Smart_Ptr<T> &Obj, const UNICODE_String &idName, cxxlComposite<T,isUnique> *pComposite) 在指定節點之前,將物件放入一個指定名稱的新子節點,成功傳回放入的節點,失敗傳回空物件,可用 Smart_Ptr::isNULL() 檢查
AddNext(const Smart_Ptr<T> &Obj, const UNICODE_String &idName, cxxlComposite<T,isUnique> *pComposite) 在指定節點之後,將物件放入一個指定名稱的新子節點,成功傳回放入的節點,失敗傳回空物件,可用 Smart_Ptr::isNULL() 檢查
 
Delete(cxxlComposite<T,isUnique> *pComposite) 放棄持有指定的子節點,pComposite 非 NULL 且是其子節點回覆 true

DeletePrev(const cxxlComposite<T,isUnique> *pComposite) 放棄持有指定的子節點的前一個節點,pComposite 及 前一個節點 非 NULL 且是其子節點回覆 true
DeleteNext(const cxxlComposite<T,isUnique> *pComposite) 放棄持有指定的子節點的下一個節點,pComposite 及 下一個節點 非 NULL 且是其子節點回覆 true
ClearAll() 放棄持有所有子節點
 
GetParent() 取得父節點,若不存在回覆空物件,可用 Smart_Ptr::isNULL() 檢查
GetComposite(const UNICODE_String &idName) 取得指定名稱的子節點,若不存在回覆空物件,可用 Smart_Ptr::isNULL() 檢查
GetCompositePrev(const cxxlComposite<T,isUnique> *pComposite)

取得指定的子節點的前一個節點,若不存在回覆空物件,可用 Smart_Ptr::isNULL() 檢查

GetCompositeNext(const cxxlComposite<T,isUnique> *pComposite)

取得指定的子節點的下一個節點,若不存在回覆空物件,可用 Smart_Ptr::isNULL() 檢查

 
CreateSelf(UNICODE_String idName,ISpirit *spirit) 虛擬函數,建立新子節點和自我複製時用來產生延伸類別的物件,所以延伸類別必須覆寫

巡行功能

採取和 cxxlAVL_Tree 相同的做法,利用 cxxlList 把所有子節點傳回給使用端,以建立或安排的先後順序排列

cxxlList_Create(ISpirit *spirit = Spirit_Easy) 將所有子節點放入串列後傳回,spirit 是建立 cxxlList 用的
   
Export(void *def) 將所有子節點匯出至 Composite_Export(),延伸類別藉由覆寫 Composite_Export() 以取得,注意順序是由後往前匯出,def 將被傳送給 Composite_Export()
virtual void Composite_Export(void *def, cxxlComposite<T,isUnique> *BeExported) 虛擬函數,延伸類別藉由覆寫此函數以取得 Export() 的匯出結果,def 功用由程式員自定

自我複製

Clone() 自我複製,傳回相同內容的同類形容器物件

 

 

範例一

#include <iostream>
#include <locale>
#include <CXXLCOMPOSITE.HPP>
using namespace std;
using namespace CxxlMan; 
class A:virtual public cxxlObject
{ 
  int m_i;
public:
  A(int i)
    : cxxlObject(Spirit_Urgent),
  {
    m_i = i;
  }
  virtual ~A()
  {
  }
  int Get() const
  {
    return m_i;
  }
};
 
int main(int argc, char* argv[])
{
  typedef cxxlComposite<A,true> ACompositeType; // 定義一個形別方便變更
  setlocale(LC_CTYPE, "");            // 指定系統現正使用中的地區語言做轉換
  Smart_Ptr<ACompositeType> result((ACompositeType*)NULL); 
  Smart_Ptr<ACompositeType > A_Composite(new ACompositeType(L"最上層節點"));
  cout << "A_Composite 現在所處的節點:" << MB_String(A_Composite->GetName()) << endl;
  cout << "建立子物件:" << endl;
  result = A_Composite->Add(new A(1),L"A 物件 001"); 
  cout << MB_String(result->GetName()) << endl;
  result = A_Composite->AddPrev(new A(2),L"A 物件 002",result); 
  cout << MB_String(result->GetName()) << endl;
  result = A_Composite->AddPrev(new A(3),L"A 物件 003",result); 
  cout << MB_String(result->GetName()) << endl;
  result = A_Composite->AddPrev(new A(4),L"A 物件 004",result); 
  cout << MB_String(result->GetName()) << endl;
  result = A_Composite->AddNext(NULL,L"子目錄 001",result); 
  cout << MB_String(result->GetName()) << endl;
  result = A_Composite->Add(new A(1),L"名稱後面加底線_");
  if(result.isNULL())
    cout << "名稱後面不可加底線 _" << endl << endl;
  A_Composite = A_Composite->GetComposite(L"A 物件 002");
  cout << "A_Composite 現在所處的節點:" << MB_String(A_Composite->GetName()) << endl;
  cout << "建立子物件:" << endl;
  result = A_Composite->Add(new A(21),L"A 物件 021"); 
  cout << MB_String(result->GetName()) << endl;
  result = A_Composite->Add(new A(22),L"A 物件 022"); 
  cout << MB_String(result->GetName()) << endl;
  result = A_Composite->Add(new A(23),L"A 物件 023"); 
  cout << MB_String(result->GetName()) << endl;
  A_Composite = A_Composite->GetParent();
  cout << endl << "A_Composite 現在所處的節點:" 
<< MB_String(A_Composite->GetName()) << endl;
  cout << "所有子節點:" << endl;
  Smart_Ptr<cxxlList<ACompositeType > > Composite_List = A_Composite->cxxlList_Create();
  Composite_List->ResetPT(toHead);
  for(Smart_Ptr<ACompositeType > Composite_Ptr = (*Composite_List)++; 
    !Composite_Ptr.isNULL(); Composite_Ptr = (*Composite_List)++)
  {
    cout << MB_String(Composite_Ptr->GetName()) << endl;
  }
 
  Smart_Ptr<ACompositeType > A_Composite2 = A_Composite->Clone(); // 複製一份
  A_Composite2 = A_Composite2->GetComposite(L"A 物件 002");
  cout << endl << "A_Composite2 現在所處的節點:" 
<< MB_String(A_Composite2->GetName()) << endl;
  Smart_Ptr<ACompositeType > A_022 = A_Composite2->GetComposite(L"A 物件 022");
   
  cout << MB_String(A_022->GetName()) << " = " << A_022->GetObj()->Get() << endl;
  system("pause");   
}
 
 
 
 

文字組合的匯出匯入

這裡提供 4 個針對包裹 UNICODE_String(其實是 string_wrapper<wchar_t>) 的 cxxlComposite,可以匯出成相應的特定結構文件,或是從這樣的文件匯入產生(或者說還原) cxxlComposite,這種文件簡稱為 TLC (Text List Composite),其結構和 cxxlComposite 是相對應的,也是由節點組成的階層式樹狀結構,節點的格式如下

[節點名稱] "此節點的文字內容" {子節點}

[ ] 是必須的,節點名稱可無。內容和子節點可有可無,但順序要正確,在 [ ] 和 " " 內的任何字元都是資料(除了轉換標示),在 [ ] 和 " " 之外的任何字元都視而不見。

在 [ ] 內若有 ' ] ' 字元須改為轉換標示 "&#93;",同樣 " " 內有 " 字元也要轉換為 "&#34;"。另外為了編排上的須求,斷行字元也可以做轉換(不轉換也不會有問題),把這些 轉換標示 表列於下:

字元 轉換標示

附註

]
&#93;
只在 [ ] 內有作用
"
&#34;
只在 " " 內有作用
'\n'
&#10;
不轉換也沒問題
'\r'
&#13;
不轉換也沒問題
&
&#38;
避免內容正好是以上標示就轉吧

以上這些轉換在匯出匯入的過程中會自動處理,除非要自行編寫 TLC 文件,否則不用去在意。

4 個函數的的宣告列於下:

// 匯出 名稱不可重複 包裹 UNICODE 字串的 cxxlComposite
void cxxlFASTCALL UniqueTxtCompositeExport(std::wostream &wout, 
const Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>,true> > &TxtComposite);
// 匯出 名稱可重複 包裹 UNICODE 字串的 cxxlComposite
void cxxlFASTCALL NonUniqueTxtCompositeExport(std::wostream &wout, 
const Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>,false> > &TxtComposite);
// 匯入 建立 包裹 UNICODE 字串 名稱不可重複的 cxxlComposite 後傳回,須藉
// 由 tempUniqueTxtComposite_Arg 指定
// 一個空的 cxxlComposite 樣版,將用它產生要傳回的 cxxlComposite 物件
// 須是 cxxlComposite<string_wrapper<wchar_t>,true> 或其延伸類別
// 若有錯誤回傳 NULL
extern CXXLCONTAINER_DLLEXPORT Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>,true> >
cxxlFASTCALL UniqueTxtCompositeImport(
  std::wistream &TLC,
  const Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>,true> > &tempUniqueTxtComposite_Arg =
  new cxxlComposite<string_wrapper<wchar_t>,true>(L"tempComposite", Spirit_Easy));
// 匯入 建立 包裹 UNICODE 字串 名稱可重複的 cxxlComposite 後傳回,須藉
// 由 tempNonUniqueTxtComposite_Arg 指
// 定一個空的 cxxlComposite 樣版,將用它產生要傳回的 cxxlComposite 物件
// 須是 cxxlComposite<string_wrapper<wchar_t>,false> 或其延伸類別
// 若有錯誤回傳 NULL
extern CXXLCONTAINER_DLLEXPORT Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>,false> >
cxxlFASTCALL NonUniqueTxtCompositeImport(
  std::wistream &TLC,
  const Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>,false> > &tempNonUniqueTxtComposite_Arg =
  new cxxlComposite<string_wrapper<wchar_t>,false>(L"tempComposite", Spirit_Easy));
 
 

範例二

#include <sstream>
#include <iostream>
#include <locale>
#include <CXXLCOMPOSITE.HPP>
using namespace std;
using namespace CxxlMan;
 
int main(int argc, char* argv[])
{
   
  setlocale(LC_CTYPE, "");       // 指定系統現正使用中的地區語言做轉換
  // 建立根節點,指定 名稱可重複
  Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>,false> > 
  rootTxtComposite_Ptr = new cxxlComposite<string_wrapper<wchar_t>,false>(L"root");
  // 第二層不包含內容的子節點
  Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>,false> > 
  TxtComposite_Ptr = rootTxtComposite_Ptr->Add(NULL,L"Dir 2.1");
  TxtComposite_Ptr->Add(UNICODE_String(L"HI"),L"路人甲");
  // 含有內容的第三層子節點
  TxtComposite_Ptr = TxtComposite_Ptr->Add(UNICODE_String(L"HI 有內容有子節點"),L"Dir 3.1");
  TxtComposite_Ptr->Add(UNICODE_String(L"HI..."),L"路人乙");
  TxtComposite_Ptr->Add(UNICODE_String(L"HI 名稱重複"),L"路人乙");
  // 回上層節點
  TxtComposite_Ptr = TxtComposite_Ptr->GetParent(); 
  TxtComposite_Ptr->Add(UNICODE_String(L"HI"),L"路人丙");
  TxtComposite_Ptr->Add(UNICODE_String(L"HI 無名稱"),L"");
  // 匯出成 TLC 文件
  wostringstream wosTLC;
  NonUniqueTxtCompositeExport(wosTLC, rootTxtComposite_Ptr);
  wcout << wosTLC.str() << endl;
 
  // 匯入建立第二個 Composite 容器
  wistringstream wisTLC(wosTLC.str());
  Smart_Ptr<cxxlComposite<string_wrapper<wchar_t>,false> > Chk_Ptr = 
NonUniqueTxtCompositeImport(wisTLC);
  // 再匯出檢查看看和本尊是不是一樣
  wostringstream wosTLC2;
  NonUniqueTxtCompositeExport(wosTLC2, Chk_Ptr);
  wcout << wosTLC2.str() << endl; 
  return 0;
}
 

執行結果:

 
 
 

 
引入檔

CXXLCOMPOSITE.HPP

 

程式庫

cxxlcontainer

 

 
 
Comments