C++山寨C#中的DataTable
简单介绍一下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则全靠意淫。是这样吗?