简介通常,电子表格指的是表格处理程序(存储和处理数据的应用程序),例如 EXCEL。尽管文中显示的代码不是那么强大,它可以用作表格处理程序的全功能实现的一个基类。我不是要使用 MQL5 创建 MS Excel,我希望实现一个类,以便在二维数组中操作不同类型的数据。 尽管我实现的类在性能上无法比拟单一类型数据的二维数组(可直接访问数据),但该类的出现是为了方便使用。此外,该类可视作以 C++ 实施的 Variant 类,作为表格简化为一列的特殊情况。 对于迫不及待的读者和想要跳过实施的算法分析的读者,我将从可用方法开始 CTable 类的介绍。 1. 类的方法的说明首先,我们考虑类的可用方法,让我们从更细节的层面了解它们的目的和使用原则。 1.1. FirstResize 表格布局,列类型的描述,TYPE[] - ENUM_DATATYPE 类型数组,它确定行的大小和单元格类型。 void FirstResize(const ENUM_DATATYPE &TYPE[]); 实际上,该类是具有一个参数的另一个构造函数。这很方便,原因有两个:首先,它解决了在构造函数内部传递参数的问题;其次,它提供了将对象作为参数传递,然后执行必要的数组划分的可能性。此功能允许将类作为 C++ 中的 Variant 类使用。 实施的特殊性包括:虽然函数设置了第一个维度和列的数据类型,它不需要将第一个维度的大小作为参数指定。此参数取自传递的数组 TYPE 的大小。 1.2. SecondResize 将行数更改为 "j"。 void SecondResize(int j); 函数为第二个维度的所有数组设置了一个指定的大小。因此,我们可以说它增加了表格的行数。 1.3. FirstSize 该方法返回第一个维度的大小(行的长度)。 int FirstSize(); 1.4. SecondSize 该方法返回第二个维度的大小(列的长度)。 int SecondSize(); 1.5. PruningTable 它为第一个维度设置新的大小;此改变在初始大小的范围内是可能的。 void PruningTable(int count); 实际上,函数并未改变行的长度;它只是改写了一个变量的值,该变量用于存储行的长度的值。该类包含另一个变量,用于存储在表格初始划分时设置的分配内存的实际大小。在该变量的值的范围内,虚拟改变第一个维度的大小是可能的。当复制一个表格到另一个表格时,该函数可删去不需要的部分。 1.6. CopyTable 将一个表格的第二个维度的整个长度复制到另一个表格的方法: void CopyTable(CTable *sor); 该函数将一个表格复制到另一个表格。它启动接收表格的初始化,可用作另一个构造函数。排序变体的内部结构并未复制,只是从初始表格复制了大小、列的类型以及数据。函数将 CTable 类型的复制对象的引用作为一个参数接收,该参数由 GetPointer 函数传递。 复制一个表格到另一个表格时,一个新的表格根据 "sor" 示例创建。 void CopyTable(CTable *sor,int sec_beg,int sec_end); 使用其他参数覆盖上述函数:sec_beg - 复制初始表格的起点,sec_end - 复制的终点(请不要与复制的数据量混淆)。两个参数均针对第二个维度。数据将添加至接收表格的起始处。接收表格的大小设置为 sec_end-sec_beg+1。 1.7. TypeTable 返回第 "i" 列的 type_table 值(ENUM_DATATYPE 类型)。 ENUM_DATATYPE TypeTable(int i) 1.8. Change Change() 方法执行列的交换。 bool Change(int &sor0,int &sor1); 正如上文所述,该类交换列(操作第一个维度)。由于信息并未实际移动,该函数的操作速度不会受第二个维度的大小的影响。 1.9. Insert 此插入方法在指定位置插入列, bool Insert(int rec,int sor); 该函数与上面介绍的函数相同,除了它基于指定列应移至的位置执行其他列的移动。参数 "rec" 指定列应移至的位置,"sor" 指定列将移出的位置。 1.10. Variant/VariantCopy 接下来是 "varian" 系列的三个函数。表格处理的变体的识记在类中实现。 变体起到类似笔记本的提醒作用。例如,如果您按第三列执行排序,而您不希望在下次处理时重置数据,您应切换变体。要访问处理的上个变体,调用 "variant" 函数。如果下次处理应基于上次处理的结果,您应复制变体。默认情况下,设置编号为 0 的变体。 设置变体(如果没有这样的变体,将创建该变体以及所有缺失的变体直到 "ind")和获取活动变体。"variantcopy" 方法将 "sor" 变体复制到 "rec" 变体。 void variant(int ind); int variant(); void variantcopy(int rec,int sor); variant(int ind) 方法切换所选变体。执行自动内存分配。如果指定的参数少于上次指定的参数个数,将不会重新分配内存。 variantcopy 方法允许复制 "sor" 变体到 "rec" 变体。该函数被创建用于安排变体。如果 "rec" 变体不存在,它自动增加变体的数目,并且切换至新复制的变体。 1.11. SortTwoDimArray SortTwoDimArray 方法按选定的行 "i" 排序表格。 void SortTwoDimArray(int i,int beg,int end,bool mode=false); 按指定列排序表格的功能。参数:i - 列,beg - 排序起点,end - 排序终点(包含),mode - 布尔变量,确定排序方向。如果 mode=true,它表示值随索引增大而增大("false" 是默认值,因为索引从表的顶部到底部逐渐增大)。 1.12. QuickSearch 该方法按与 "element" 模式相等的值在数组中快速搜索元素的位置。 int QuickSearch(int i,long element,int beg,int end,bool mode=false); 1.13. SearchFirst 在排序数组中搜索与模式相等的第一个元素。返回与 "element" 模式相等的第一个值的索引。有必要指定在此范围早前执行的排序类型(如果没有这样的元素,则返回 -1)。 int SearchFirst(int i,long element,int beg,int end,bool mode=false); 1.14. SearchLast 在排序数组中搜索与模式相等的最后一个元素。 int SearchLast(int i,long element,int beg,int end,bool mode=false); 1.15. SearchGreat 在排序数组中搜索大于模式的最接近的元素。 int SearchGreat(int i,long element,int beg,int end,bool mode=false); 1.16. SearchLess 在排序数组中搜索小于模式的最接近的元素。 int SearchLess(int i,long element,int beg,int end,bool mode=false); 1.17. Set/Get Set 和 Get 函数具有空类型;它们被表格使用的四种数据类型所覆盖。该函数识别数据类型,如果 "value" 参数不符合列类型,将显示一则警告消息且不会进行分配。唯一的例外是字符串类型。如果输入参数为字符串类型,它将被转换为列类型。该例外在不可能设置一个接收单元格的值的变量时,为使传输信息更加方便而量身定做。 设置值的方法(i - 第一个维度的索引,j - 第二个维度的索引)。 void Set(int i,int j,long value); // setting value of the i-th row and j-th column void Set(int i,int j,double value); // setting value of the i-th row and j-th columns void Set(int i,int j,datetime value);// setting value of the i-th row and j-tj column void Set(int i,int j,string value); // setting value of the i-th row and j-th column 获取值的方法(i - 第一个维度的索引,j - 第二个维度的索引)。 //--- getting value void Get(int i,int j,long &recipient); // getting value of the i-th row and j-th column void Get(int i,int j,double &recipient); // getting value of the i-th row and j-th column void Get(int i,int j,datetime &recipient); // getting value of the i-th row and j-th column void Get(int i,int j,string &recipient); // getting value of the i-th row and j-th column 1.19. sGet 从第 "j" 列第 "i" 行获取字符串类型的值。 string sGet(int i,int j); // return value of the i-th row and j-th column Get 系列的唯一函数通过 "return" 运算符而不是参数变量返回值。返回一个字符串类型的值(不考虑列类型)。 1.20. StringDigits 当类型转换为“字符串”,您可以通过函数使用精度设置: void StringDigits(int i,int digits); 来设置“双精度”的精度,以及 int StringDigits(int i); 设置在“日期时间”中显示秒数的精度;任何不等于 -1 的值都通过。指定的值为列而记忆,因此您不必每次在显示信息时指出值。您可以多次设定精度,因为该信息存储在原始类型中,并只在输出期间转换为指定的精度。精度值不会在复制时存储,因此,当复制表格至新的表格时,新表格的列的精度将与默认精度相符。 1.21. 使用示例: #include <Table.mqh> ENUM_DATATYPE TYPE[7]= {TYPE_LONG,TYPE_LONG,TYPE_STRING,TYPE_DATETIME,TYPE_STRING,TYPE_STRING,TYPE_DOUBLE}; // 0 1 2 3 4 5 6 //7 void OnStart() { CTable table,table1; table.FirstResize(TYPE); // dividing table, determining column types table.SecondResize(5); // change the number of rows table.Set(6,0,"321.012324568"); // assigning data to the 6-th column, 0 row table.Insert(2,6); // insert 6-th column in the 2-nd position table.PruningTable(3); // cut the table to 3 columns table.StringDigits(2,5); // set precision of 5 digits after the decimal point Print("table ",table.sGet(2,0)); // print the cell located in the 2-nd column, 0 row table1.CopyTable(GetPointer(table)); // copy the entire table 'table' to the 'table1' table table1.StringDigits(2,8); // set 8-digit precision Print("table1 ",table1.sGet(2,0)); // print the cell located in the 2-nd column, 0 row of the 'table1' table. } 操作结果是打印单元格 (2;0) 的内容。读者可能已注意到,复制数据的精度不会超出初始表格的精度。 2011.02.09 14:18:37 Table Script (EURUSD,H1) table1 321.01232000 2011.02.09 14:18:37 Table Script (EURUSD,H1) table 321.01232 现在,我们开始算法本身的说明。 2. 选择模型有两种方式组织信息:连接列方案(本文所实施的结构)及其呈连接行形式的替代选择如下所示。 由于通过一个中间物引用信息(在 p. 2 中说明),上范围的实施没有太大的差异。但我选择列模型,因为它允许在存储数据的对象中的下范围上实施数据方法。而替代方案可能要求覆盖用于在上类 CTable 中处理信息的方法。并且这会使类的增强复杂化(如果必要的话)。 因此,两种方案都可使用。建议的方案允许快速移动数据,而替代方案可更快地添加数据(因为信息往往是逐行添加至表格)和获取行。 还有另一种安排表格的方式 - 结构数组。虽然它最容易实现,但却有一个重大缺陷。结构必须由程序表说明。因此,我们失去了通过自定义参数设置表格属性的机会(无需更改源代码)。
|
|