簡單介紹一下DataTable。DataTable主要基於表、行、單元格。行用集合包裝單元格,表用集合包裝行,大致就是這樣。DataColumn表示單元格,DataColumn中的字段還挺多的,在實際應用中我們可能只想用它來存一個int型的數據;DataColumnCollection中用一個ArrayList封裝DataColumn,表示一些單元格的集合;DataRow直接在DataColumnCollection的基礎上提供一些方法,成為行記錄。而DataRowCollection則用集合的方式封裝DataRow成為表,但它不是以線性、鏈表等方式,而是基於紅黑樹RBTree<DataRow>,主要是查詢和刪除比較方便,而DataTable則是DataRowCollection的封裝,對看了DataTable整個實現的大致代碼,我不得吐槽一下:這它媽是把牛刀,我們每天用它來切菜,用着還挺方便。DataTable提供了很強大的功能,但是我們基本不需要,有時候基本上是得到一個DataTable,啥都不做,直接綁定,最常用的也就Update和Insert,Select和Delete則次之。當然你會說避免使用DataTable,當然還有人說C#......
OK廢話到此結束,今天我想做說的是用C++來實現DataTable。大致思路還是按照C#中的來,功能沒有C#中的強大,但增刪改查的功能還是有的,基本還是個人練習,把代碼放出來跟大家討論一下。基本上是STL中幾個集合的運用。在我的實現在並沒有使用紅黑樹,而是用list<DataRow*>代替了,主要類的頭文件如下:
DataColumn的實現代碼如下,主要是對幾個字段的封裝。源碼共享
#pragma once class DataTable; #include <iostream> using namespace std; template<typename T> class TDataColumn { public: TDataColumn():columnName(string()),caption(string()) { } TDataColumn(const string& _columnName):columnName(_columnName),caption(string()) { } virtual ~TDataColumn() { } void Caption(const string& _caption) { caption=_caption; } string Caption() { return caption.size() ?caption:columnName; } void ColumnName(const string& _columnName) { columnName=_columnName; } string ColumnName() { return columnName; } void Value(const T& _value) { value=_value; } T Value() { return value; } int ObjectId() { return objectId; } void Table(DataTable* tb) { table=tb; } DataTable* Table() { return table; } string TypeName() { return typeid(T).name(); } protected: int objectId; string columnName; string caption; T value; DataTable* table; }; class DataColumn:public TDataColumn<string> { public: friend class DataColumnCollection; friend class DataTable; DataColumn():TDataColumn<string>() { objectId=++objectCountId; } DataColumn(const DataColumn& dc) { *this=dc; } DataColumn& operator=(const DataColumn& dc) { objectId=++objectCountId; columnName=dc.columnName; caption=dc.caption; value=dc.value; table=dc.table; return *this; } DataColumn(const string& _columnName):TDataColumn<string>(_columnName) { objectId=++objectCountId; } bool operator==(const DataColumn& dc) { return objectId==dc.objectId; } bool operator!=(const DataColumn& dc) { return objectId!=dc.objectId; } bool operator<(const DataColumn& dc) { return objectId<dc.objectId; } bool operator>(const DataColumn& dc) { return objectId>dc.objectId; } void Show() { cout<<"columnName:"<<columnName.data()<<",caption:"<<Caption().c_str()<<",value:"<<value.data()<<endl; } private: static volatile int objectCountId; };
其他文件的頭文件如下:
#pragma once #include <iostream> using namespace std; #include <assert.h> #include <vector> #include <list> #include <map> #include "DataColumn.h" #include "StringHelper.h" class DataColumnCollection; class DataRow; class DataRowCollection; class DataTable; class DataColumnCollection { public: friend class DataTable; friend class DataRow; friend class DataRowCollection; DataColumnCollection(DataTable* table); ~DataColumnCollection(); void Add(DataColumn* dc); void Add(DataColumn* dc,size_t index); DataColumn& Add(const string& columnName); bool Contains(const string& columnName); void Clear(); size_t Count(); int IndexOf(const string& columnName); void Remove(DataColumn& dc); void Remove(const string& columnName); void RemoveAt(size_t index); void CopyTo(DataColumnCollection* arr, size_t index); DataColumn& operator[](size_t index); DataColumn& operator[](const string& columnName); void Table(DataTable* tb); DataTable* Table(); private: void Add(DataColumn* dc,size_t index,DataColumnCollection* collect); void RemoveAt(size_t index,DataColumnCollection* collect); void InitData(); DataColumnCollection(); vector<DataColumn*> dlist; map<string,DataColumn*> nameList; DataTable* table; }; class DataRow { public: friend class DataTable; friend class DataRowCollection; friend class DataColumnCollection; ~DataRow(); void Table(DataTable* tb); DataTable* Table(); DataColumnCollection& Columns(); DataColumn& operator[](size_t index); DataColumn& operator[](const string& columnName); bool operator=(const DataRow& dr); private: DataRow(); void Remove(DataColumn& dc); void RemoveAt(size_t index); DataColumnCollection* columns; DataTable* table; int rowId; static volatile int rowIdCount; }; class DataRowCollection { public: friend class DataTable; friend class DataColumnCollection; DataRowCollection(DataTable* table); ~DataRowCollection(); void Add(DataRow* dc); void Clear(); size_t Count(); void Remove(DataRow* dc); void RemoveAt(size_t index); DataRow& operator[](size_t index); void Table(DataTable* tb); DataTable* Table(); private: DataRowCollection(); list<DataRow*> drlist; DataTable* table; }; class DataTable { public: friend class DataColumnCollection; friend class DataRowCollection; DataTable(); DataTable(const string& _tableName); ~DataTable(); DataColumnCollection& Columns(); DataRowCollection& Rows(); string TableName(); void TableName(const string& _tableName); DataRow& operator[](size_t index); void Clear(); DataRow* NewRow(); vector<DataRow*>* Select(const string& columnName,const string& value) ; private: void InitData(); DataColumnCollection* dcCollect; DataRowCollection* drCollect; string tableName; };
測試代碼如下:
#include <iostream> using namespace std; #include <sstream> #include "DataColumn.h" #include "DataTable.h" #include "OperationTimer.h" int main( ) { DataTable dt; for(size_t i=0;i<10;i++) { string s("column"); s.push_back(char('0'+i)); DataColumn *dc=new DataColumn(s); dt.Columns().Add(dc); } for(int j=0;j<10;j++) { DataRow* dr=dt.NewRow(); for(int i=0;i<10;i++) { string s("row"); s.push_back(char('0'+j)); s.push_back(char('0'+i)); (*dr)[i].Value(s) ; } dt.Rows().Add(dr); } int rowCount=dt.Rows().Count(); int columnCount=dt.Columns().Count(); cout<<"共"<<rowCount<<"行"<<columnCount<<"列"<<endl; rowCount=rowCount/2; columnCount=columnCount/2; cout<<"第"<<rowCount<<"行"<<columnCount<<"列的值為:"<<dt[rowCount][columnCount].Value().c_str()<<endl; dt.Columns().Add(new DataColumn("column10")); dt.Columns().Add(new DataColumn("column11")); cout<<"新增兩列后:"<<endl; rowCount=dt.Rows().Count(); columnCount=dt.Columns().Count(); cout<<"共"<<rowCount<<"行"<<columnCount<<"列"<<endl; rowCount=rowCount/2; columnCount=columnCount/2; cout<<"第"<<rowCount<<"行"<<columnCount<<"列的值為:"<<dt[rowCount][columnCount].Value().c_str()<<endl; cout<<"刪除一行一列后:"<<endl; dt.Columns().RemoveAt(4); dt.Rows().RemoveAt(2); rowCount=dt.Rows().Count(); columnCount=dt.Columns().Count(); cout<<"共"<<rowCount<<"行"<<columnCount<<"列"<<endl; rowCount=rowCount/2; columnCount=columnCount/2; cout<<"第"<<rowCount<<"行"<<columnCount<<"列的值為:"<<dt[rowCount][columnCount].Value().c_str()<<endl<<endl; cout<<"查詢列名為column3,值為row43的行,數據如下:"<<endl; vector<DataRow*>* vect=dt.Select("column3","row43"); for(size_t i=0;i<vect->size();i++) { DataColumnCollection& dcCollect= (*vect)[i]->Columns(); for(size_t j=0;j<dcCollect.Count();j++) { dcCollect[j].Show(); } } delete vect; getchar(); return 0; }
結構截圖:
在吐個槽,STL中的map<key,value>中的key竟然可以用string呢,好神奇哦,哈哈哈
C/C++程序員在自涅中需找快感;C#/JAVA則全靠意淫。是這樣嗎?