龙听期货论坛's Archiver

C
+
+


 微信: QQ:

龙听 发表于 2020-3-23 10:39

MQL4 语言入门 简单词组中的难题

简介[p=30, 2, left]这是“MQL4 语言入门”系列的第二篇文章。第一篇文章[url=https://www.mql5.com/zh/articles/1475]“MQL4 语言入门简介”[/url]描述了 MQL4 的功能,我们学习编写简单脚本,了解变量含义,学习使用变量,分析函数、数组、内置数组和变量、循环“for”以及简单和复杂的条件。现在我们将探讨该语言更复杂、更高级的构造,学习新内容,并了解如何将它们应用到日常实践中。您将了解新循环类型“while”,新条件类型“switch”,运算符“break”和“continue”。此外,我们将学习编写您自己的函数和使用多维数组。作为餐前甜点,我还准备了一份有关预处理器的说明。[/p]建议[p=30, 2, left]请在充分理解上一篇文章之后,再来阅读本文。否则您会犯很多错误,同时也学不到什么。本文要以上一篇文章为基础,所以别太心急!放轻松 - 学习这些新东西时碰到的难题都不过是纸老虎。总有那么一天,您无需再三考虑循环怎么编写,要放上哪些条件等等问题,所有东西都会按部就班地完成。多多使用 MQL4 语言,它就会变得越来越简单。
[/p]新的循环类型 - while[p=30, 2, left]我想提一下,上一篇文章中讲到的循环“for”是一个[b]通用[/b]循环,可以替代我们现在要学的任何其他循环类型。但它也并不是适用于所有情况的。有时用[b] while 会更高效。[/b]。很快您就会知道使用哪种循环类型会比较合理。我们用两种方式做一个任务:使用两种循环找出所有条柱的总成交量,看看有什么区别:[/p]// using the cycle for double sum = 0.0; for(int a = 0; a < Bars; a++)     sum += Volume[a]; // now using while, the result is the same double sum = 0.0; int a = 0; while(a < Bars)     {       sum += Volume[a];       a++;     }[font=Tahoma, Verdana, Arial, Helvetica, sans-serif][size=13px]看,现在计数器被声明并被单独使用。这里的“While”表示,当条件为真时,循环将继续。以下是常规格式:
[/size][/font]
[font=Tahoma, Verdana, Arial, Helvetica, sans-serif][size=13px]while(condition of cycle fulfillment)   {    code;   }[/size][/font]
[p=30, 2, left]更简单的示例如下:[/p]while(I havent eaten up the apple)  {   bite more;   }[font=Tahoma, Verdana, Arial, Helvetica, sans-serif][size=13px]实际上,循环“while”与循环“for”的不同之处仅在于[b]缺少一个计数器[/b]。如果不需要计数器,用 while,尽管它并不是必要的。比如我经常使用 while 搭配一个计数器,这只关乎个人喜好。就像在使用 for 的案例中,如果循环主体只包括一个指令,那就可以省略大括号。要想自己开发,还要记住迭代一词的含义。它是由循环执行的一种多重操作(重复)。执行一次循环主体即表示执行一次迭代。
[/size][/font]
新的循环类型 - switch[p=30, 2, left]在使用循环的案例中,应注意[b]switch[/b]可替代为一组您熟悉的“if”和“else”条件。当您需要根据变量值执行一些操作时,就可以使用“switch”结构。这就像微波炉上常见的模式开关。例如,假设您在编写一个 EA,它的行为会根据市场情况进行变化。就用变量[b]int marketState[/b]来执行这个任务。它可拥有以下含义:[/p][font=Tahoma, Verdana, Arial, Helvetica, sans-serif][size=13px][list][*]1 - 上升趋势[*]2 - 下跌趋势[*]3 - 平盘趋势[/list][/size][/font]
[p=30, 2, left]无论这个价位是怎么定义的,我们的任务是实现某种机制,以便 EA 根据市场情况执行对应的操作。您知道该怎么做。以下是最明显的变体:
[/p]if(marketState == 1)  {// trading strategy for an uptrend} else if(marketState == 2)  {// strategy for a downtrend}     else if(marketState == 3)  {// strategy for a flat}     else  {// error: this state is not supported!}[p=30, 2, left]这里有一些特性:[/p][list][*]所有条件采用的是同一个变量;[*]所有条件都在将该变量与其可接受的意义之一进行比较。[/list][p=30, 2, left]因此,所有这些还都涉及到 switch 结构。以下是使用 switch 的一个代码,结果是相同的:[/p]switch(marketState)     {  case 1:// trading strategy for an uptrend   break;       case 2:// strategy for a downtrend   break;       case
3:// strategy for a flat   break;       default:// error: this state is not supported!   break;     }[p=30, 2, left]注意,我们首先定义要比较的变量:[/p]// switch - key word, marketState - a variable for comparison switch(marketState)[p=30, 2, left]然后指示特定情况下应执行的操作:[/p]case 1:// trading strategy for an uptrend   break;     case 2:// strategy for a downtrend   break;     case 3:// strategy for a flat   break;     default:// error: this state is not supported!   break;  [p=30, 2, left]在一般视图中,[b]switch[/b]采用以下格式:[/p]switch(a variable for comparison)     {  case [a variable value]:// a code for this case    break;         case [another value of the variable]:// a code for this case    break;         default:// a code for all other cases    break;     }[p=30, 2, left]在将[b]switch[/b]进行比较,和将特定代码块与一个值进行比较时,使用 switch。其他情况下,使用“if”和“else”条件的常用组合。有时您需要根据某个变量的多个值执行一个代码。例如,如果 marketState == 1 或 2,则执行某个特定代码。以下就是这个任务中 [b]switch[/b]:[/p]switch(marketState)     {       case 1:  // if marketState is equal to 1       case 2:  // or if marketState is equal to 2, then perform this  break;   default: // in any other case perform  this code   break;     }运算符:continue 和 break[p=30, 2, left]我们刚才就看到了这个 [b]break 运算符[/b]。它用于跳出 [b]switch[/b]。除此以外,您可用它跳出一个循环。例如在某些条件下您不需要执行某个循环时就能用到。假设我们需要找出第一批条柱的金额,这批条柱需要包括 1000 个点。我们可以编写以下代码:[/p]int a = 0; double volume = 0.0; while(volume < 1000.0)     {       volume += Volume[a]; // equivalent to volume = volume + Volume[a];       a++;     } // now variable "a" includes the amount of bars, the volume of their sums is no less than 1000 points[p=30, 2, left]现在让我们用[b]break 运算符[/b]:[/p]int a = 0; double volume = 0.0; while(a < Bars)     {   // if the volume is exceeds 1000 points, then       if(volume > 1000.0) // exit the cycle  break;                  volume += Volume[a];      a++;   }[p=30, 2, left]你看,[b]break 运算符[/b]运算符很好用,可以避免不需要的循环迭代。还有一个很有用的操作符[b]continue[/b],它主要用于“忽略”不需要的迭代。假设我们需要计算一个总金额,但我们必须把出现重大消息时的交易量排除在外。如你所知,重大消息的出现总是伴随着大量的点。举个简单的例子,假设条柱金额包括 50 个点,超过这 50 个点的都是针对消息的。要解决这个任务,让我们使用 continue 运算符:[/p]int a = -1; double volume = 0.0; while(a < Bars)     {       a++;  // if the volume exceeds 50 points, then it must  be news, omit it       if(Volume[a] > 50.0)  continue;                volume += Volume[a];     }[p=30, 2, left]你看,使用[b]continue[/b]操作符相当繁琐,但某些时候是很有用的。很明显,此脚本主要用于小时间框架。[/p]编写自己的函数[p=30, 2, left]但我们为何需要它们?事实上,您经常会发现重复的代码。也就是说,您会在不同的案例中使用同一套指令。要节省时间和精力,您可将这种重复的代码编写成一个单独的函数。需要时,只要写下该函数的名称,它就会帮你搞定一切。让我们看看它们是怎么工作的。假设您需要找出某个烛台的颜色。已知一根白色烛台的收盘价高于开盘价,一根黑色烛台的收盘价低于开盘价。我们来编写一段代码,确定烛台的颜色。[/p]bool color; // as there are only 2 variants (white or black candlestick), then suppose that the velue false corresponds to a black candlestick, and true - white if(Close[0] > Open[0])  color = true;// white candlestick      if(Open[0] > Close[0])  color = false;// black candlestick[p=30, 2, left]好了,现在变量颜色包含最后一根烛台的颜色。要确定另一根烛台的颜色,例如倒数第二根,您需要将指数 0 更改为 1。但难道您每次需要查找烛台的颜色,就要编一次这些代码?如果出现大量这种情况呢?所以我们需要函数。想想看应该怎么做。此类函数应接受一个参数 - 需要确定其颜色的烛台的指数,并返回该颜色 - 一个布尔型变量。想象一下,我们编写了这个函数并激活它:[/p]bool color; // here will be the color of a wanted candlestick color = GetColor(0);[p=30, 2, left]如您预料的那样,我们的函数名为 GetColor。我们调用此函数是为了查找最后一根烛台的颜色。所以这个唯一的参数等于 0。此函数返回一根烛台的颜色,以便我们立即进行分配。这是一个非常重要的时刻!将在函数内部创建一个变量,然后该变量值将取代此函数调用。最终,上述的函数调用和函数确定代码会产生相同的结果 - 变量颜色将包含最后一根烛台的颜色,但使用函数我们会更省力。[/p][p=30, 2, left]现在我们回头说说空脚本的代码。实际上,空脚本的代码已经包含了函数 start() 的完整说明。最有趣的一点是,您其实一直是在这个函数中编写代码。当您打开脚本时,终端就会激活函数 start()。我们来看看空脚本的代码:[/p]int start()[p=30, 2, left]这一行非常关键!它包括[b]函数名称[/b],即一个用于激活此函数的关键字。在我们的示例中,它是“start”。它还包含[b]返回值类型[/b]- int。它的意思是,执行此函数之后,此函数将向我们返回一些 int 类型的值。括号中包含[b]参数列表[/b],但在我们的实例中,此函数不接受任何参数。[/p][p=30, 2, left]然后在大括号中可以看到函数描述,即在函数调用时执行的代码。[/p]{    // a code that will be performed at the function call.  return(0); }[p=30, 2, left]很明显,我们是在 start() 函数的主体内编写代码。在函数末尾,我们看到运算符[b]return[/b],它返回函数值。在我们的示例中,它返回 0。[/p][p=30, 2, left]以下是编写一个函数时的常用格式:[/p][type of return value] [function name] ([list of arguments])     {       // function code       return([a value, which the function returns]);     }[p=30, 2, left]现在返回到我们的烛台和[b]GetColor [/b]函数。看看此函数的代码:[/p]bool GetColor(int index)     {       bool color;       if(Close[index] > Open[index]) color = true;// white candlestick       if(Open[index] > Close[index]) color = false;// black candlestick       return(color);     }[p=30, 2, left]我们仔细想想第一行:[/p]bool GetColor(int index)[p=30, 2, left]里面有:[b]bool[/b] - 返回值的类型;[b]GetColor[/b]- 函数名称;[b]int[/b]- 参数类型;[b]index[/b]- 参数名称。注意,我们在函数主体内使用[b]index[/b],但在函数调用时,不会再提到此名称。例如:[/p]bool lastColor = GetColor(0);[p=30, 2, left]然后:[/p]{    bool color;    if(Close[index]>Open[index]) color=true;// white candlestick    if(Open[index]>Close[index]) color=false;// black candlestick[p=30, 2, left]此函数主体是一个通用代码,每次函数调用时都可执行此代码。之后:[/p]return(color); }[p=30, 2, left]运算符 [b]return[/b]。返回值应与最开头确定的类型相对应。必要时,可以在一个函数中使用多个运算符“return”,例如:[/p]bool GetColor(int index)     {      if(Close[index] > Open[index]) return(true);// white candlestick      if(Open[index] > Close[index]) return(false);// black candlestick     }[p=30, 2, left]很明显,使用多个[b]return[/b]运算符可避免使用变量[b]color[/b]。此外,在运算符 [b]return[/b]中,您甚至可以使用逻辑表达式:[/p]return(Close[index] > Open[index]);[p=30, 2, left]这是可行的,因为比较运算符也会像一些其他常用函数一样返回布尔型的变量(true 或 false)。看上去有点难,但用用就很快习惯了。
[/p][p=30, 2, left]现在让我们返回参数列表。我们的函数中仅使用了参数 [b]int index [/b]。如果您需要使用多个参数,列举它们,并用逗号隔开:[/p]bool SomeСomplicatedFunction(int fistArgument, int secondArgument, sting stringArgument)[p=30, 2, left]要参考参数,像在上一个函数中那样使用其名称。调用使用多个参数的名称时,注意[b]参数顺序序列[/b]:切勿混淆任何东西!如果函数不应返回任何值,使用[b][u]关键字 void 指示这一点。注意,这种情况下不使用 return运算符[/u][/b]:[/p]void function()   {   // code   }[p=30, 2, left]还有个细节:[b][u]您可设置函数参数默认值。[/u][/b]这是什么?假设您编写了一个复杂函数,其中包括 5 个影响函数行为的参数。但最后几个参数几乎总是使用相同的值。只有在二三十个函数调用中才需要使用不同的值。为了不必每次都指示最后几个参数几乎总是相同的值,我们使用参数的默认值。在这种情况下,您只是忽略了最后几个参数,就像它们不存在一样,尽管实际上使用了这些参数,但它们的值是默认分配的。碰到特殊情况时,您还是需要指示所有函数。让我们看看如何声明使用默认值的函数:
[/p]void someFunction(int argument1, int argument2, int specialArgument = 1)  {   // code   }[p=30, 2, left]你看,一些都很简单:我们向需要的参数分配一个需要的值,现在可以在调用函数时忽略这个参数:[/p]someFunction(10,20);// we omitted the last argument, but actually it is assigned a value by default someFunction(10,20,1);// this activation is fully identical to the previous onesomeFunction(10,20,2);// here we indicate another value,it is a rare case[p=30, 2, left]对于参数默认值,您想要分配多少就可以分配多少。但记住一条重要的规则:[b][u]它们都要放在末尾[/u][/b]。例如:[/p]void someFunction(int argument1, int argument2, int specialArgument = 1)   // all right void someFunction(int argument1, int argument2 = 10, int specialArgument=1)   // all right void someFunction(int argument1, int argument2 = 10, int specialArgument)// wrong! defaultvalues must stay
at the end of the list of arguments                                                                            void someFunction(int argument1 = 0, int argument2 = 10, int specialArgument = 1) // you can assign default values to all arguments多维数组[p=30, 2, left]编程期间常常会用到数组,大部分情况下,一维数组就够用了。但在某些情况下,您需要二维数组、三维数组。现在我们来学习如何使用它们。[/p][p=30, 2, left]我们先来看看一维数组、修改声明、初始化、指数和值的相关图片:[/p][p=30, 2, center][img=270,200]https://c.mql5.com/2/14/screen1.png[/img]语言入门 简单词组中的难题" style="margin: 0px; padding: 0px; border: 0px; list-style: none; max-width: 100%; height: auto !important;">[/p][p=30, 2, left]任何一维数组都可显示为一个类型的一行值。以下是一维数组的不同参考的处理方式:
[/p][p=30, 2, center][img=265,194]https://c.mql5.com/2/14/screen2.png[/img]语言入门 简单词组中的难题" style="margin: 0px; padding: 0px; border: 0px; list-style: none; max-width: 100%; height: auto !important;">[/p][p=30, 2, center][img=265,194]https://c.mql5.com/2/14/screen3.png[/img]语言入门 简单词组中的难题" style="margin: 0px; padding: 0px; border: 0px; list-style: none; max-width: 100%; height: auto !important;">[/p][p=30, 2, left]二维数组就像一般的表格,如下:[/p][p=30, 2, center][img=316,372]https://c.mql5.com/2/14/screen4.png[/img]语言入门 简单词组中的难题" style="margin: 0px; padding: 0px; border: 0px; list-style: none; max-width: 100%; height: auto !important;">[/p][p=30, 2, left]从图片上来看,二维数组已有[b]两个指数[/b]用于值的参考:[b]第一个指数[/b]确定一行,[b]第二个指数[/b]确定一列。像在一维数组中那样,使用[b]值列表[/b]进行[b]初始化[/b]。以下是参考表格单元的值的方式:[/p][p=30, 2, center][img=316,322]https://c.mql5.com/2/14/screen5.png[/img]语言入门 简单词组中的难题" style="margin: 0px; padding: 0px; border: 0px; list-style: none; max-width: 100%; height: auto !important;">[/p][p=30, 2, center][img=316,322]https://c.mql5.com/2/14/screen6.png[/img]语言入门 简单词组中的难题" style="margin: 0px; padding: 0px; border: 0px; list-style: none; max-width: 100%; height: auto !important;">[/p][p=30, 2, center][img=316,322]https://c.mql5.com/2/14/screen7.png[/img]语言入门 简单词组中的难题" style="margin: 0px; padding: 0px; border: 0px; list-style: none; max-width: 100%; height: auto !important;">[/p][p=30, 2, center][img=316,322]https://c.mql5.com/2/14/screen8.png[/img]语言入门 简单词组中的难题" style="margin: 0px; padding: 0px; border: 0px; list-style: none; max-width: 100%; height: auto !important;">[/p][p=30, 2, left]一切都很清楚。我们来看看如何遍历一个二维数组的所有值。应使用 2 个循环:[/p]int array2D[3][3]={10,20,30, 40,50,60, 70,80,90}; for(int y=0;y<3;y++)    for(int x=0;x<3;x++)       MessageBox("array2D["+y+"]["+x+"]="+array2D[y][x]);[p=30, 2, left]此例中,参考是从上到下,从左到右进行的。可以做个练习,试着更改方向,例如从下到上。[/p][p=30, 2, left][b]三维数组[/b]的区别仅在于[b]多了一个指数[/b]用于参考单元值。一个三维数组可以轻松呈示为几个表格(二维数组)。我们来看看如何遍历一个三维数组的所有元素:[/p]int array3D[3][3][3] = {11, 12, 13,   14, 15, 16,   17, 18, 19,   21, 22, 23,    24, 25, 26,  27, 28, 29,   31, 32, 33,   34, 35, 36,   37, 38, 39}; for(int z = 0; z < 3; z++)     for(int y = 0; y < 3; y++)         for(int x = 0; x < 3; x++)             MessageBox("array3D["+z+"]["+y+"]["+x+"]=" +                        array3D[z][y][x]);[p=30, 2, left]彻底理解二维和三维数组 - 这一点非常重要。再次非常认真地浏览说明图片。很多不同的任务都可以用数组解决,所以请投入足够时间理解这些数组,将来它们会给你带来极大的帮助。如果您理解了数组的工作原理,那么任何多维数组都可以手到擒来。[/p]使用数组时所用的一些函数[p=30, 2, left]我们从简单的函数开始说起。[/p]int ArraySize(object array[]);[p=30, 2, left]此函数返回该数组包含的元素数量。它适用于所有类型。例如:[/p]// create two different arrays int arrayInt[] = {1, 2, 3, 4};           double arrayDouble[] = {5.9, 2.1, 4.7};// here store the amount of elements int amount;                         amount = ArraySize(arrayInt);// note: to define a specific array, you need to indicate only its name.  Now amount is equal to 4 amount = ArraySize(arrayDouble); // amount is equal to 3[p=30, 2, left]下一个函数:[/p]int ArrayInitialize(object array[],double value);[b]ArrayInitialize[/b]
[p=30, 2, left]分配一个值到所有数组元素,返回所有分配到值的元素的数量。将此函数用于 int 和 double 类型的数组。[/p][p=30, 2, left]下一对函数:[/p]int ArrayMaximum(double array[], int count = WHOLE_ARRAY, int start = 0); int ArrayMinimum(double array[], int count = WHOLE_ARRAY, int start = 0);[p=30, 2, left]这两个函数返回最大和最小单元值的指数。要使用它们,只需指示应在什么数组中查找它们:
[/p]int array[] = {10, 100, 190, 3, 1}; // will be returned 1, because array[1] - maximal value ArrayMaximum(array); // will be returned 4, because array[4] - minimal value ArrayMinimum(array);[p=30, 2, left]下一对函数:[/p]int ArrayDimension(object array[]);[p=30, 2, left]使用这些函数,您可确定数组的[b]维数[/b],即您可确定它是一维、二维还是 n 维数组。使用这些函数,您可确定数组的维数,即您可确定它是一维、二维还是 n 维数组。例如:[/p]int array1D[15]; int array4D[3][3][3]; ArrayDimension(array1D);// get 1 ArrayDimension(array3D);// 3[p=30, 2, left]以下还有更多复杂而有用的函数:[/p]int ArraySort(double&array[],int count=WHOLE_ARRAY,int start=0,int sort_dir=MODE_ASCEND);[p=30, 2, left]此函数[b]对元素[/b]进行排序。如果没有直接指示参数的默认值,如下例:[/p]int array[5] = {1, 10, 5, 7, 8}; ArraySort(array);[p=30, 2, left]元素将按[b]升序排序[/b]。您可使用其他参数指定此函数行为:[/p][list][*]int count - 要排序的元素数量。[*]int start - 排序起始元素的指数[*]int sort_dir - 排序方向(升序 - MODE_ASCEND 或降序 - MODE_DESCEND)[/list][p=30, 2, left]这里您可能会问:什么是 MODE_ASCEND 和 MODE_DESCEND??根据 int,它必须是一个[b]整数[/b]!别紧张,所有问题都会在下一部分“预处理器”中得到解答。例如,如果您需要从第 2 个元素开始对 5 个元素进行升序排序,进行如下指示:[/p]ArraySort(array, 5, 1, MODE_DESCEND);[p=30, 2, left]今天的最后一个函数:[/p]int ArrayCopy(object&dest[],object source[],int start_dest=0,int start_source=0,int count=WHOLE_ARRAY);[p=30, 2, left]它用于将一个数组[b]复制到[/b]另一个数组。我们来看必要的参数:[/p][list][*]dest[] - 目的地数组[*]dest[] - 复制的数组[/list][p=30, 2, left]可选参数:[/p][list][*]start_dest - 复制到的目的地数组元素的指数[*]start_source - 开始复制的数组元素的指数[*]int count - 要复制的元素数量[/list][p=30, 2, left]此函数返回复制元素的数量。非常小心地使用 ArrayCopy:确保目的地数组有[b]足够的容量[/b]容纳复制的数组。[/p]预处理器[p=30, 2, left]这是什么?[b]预处理器[/b]是一种特殊的机制,旨在用于处理源代码。也就是说,首先是由预处理器[b]准备[/b]代码,然后[b]传达[/b]此代码用于编译。今天我们再学一个有用的选项 - [b]常数[/b]。[/p][p=30, 2, left]它主要讲什么?要了解这个选项,我们回忆一下 switch 部分中的一个示例:[/p]switch(marketState)     {       case 1:     // trading strategy for an uptrend     break;       case 2:     // strategy for a downtrend     break;       case 3:     // strategy for a flat     break;       default:     // error: this state is not supported!     break;     }[p=30, 2, left]这里我们激活了一个机制,它会根据市场状态进行不同的操作。还记得吗?那么,我们只需编写诸如 TREND_UP、TREND_DOWN、FLAT 的项目来取代 1、 2 、3,非常简单,只是更具描述性而已。[/p]switch(marketState)     {       case TREND_UP:     // trading strategy for an uptrend     break;       case TREND_DOWN:     // strategy for a downtrend     break;       case FLAT:     // strategy for a flat     break;       default:     // error: this state is not supported!     break;     }[p=30, 2, left]在这种情况下,源代码看起来更易读也更生动,不是吗?所以,在编译之前,常数允许将 TREND_UP、TREND_DOWN 和 FLAT 用对应的值 1、2 和 3 替代。您要做的只是指示预处理器应更改的内容。这个工作可通过[b]预处理器指令[/b]来完成,此指令以特殊符号“#”开头。预处理器指令应放在源文件的开头,与其他指令放在一起。来看一个完整的常数示例:[/p]//+------------------------------------------------------------------+//|                                                 preprocessor.mq4 | //|         Copyright © 2007, Antonio Banderass. All rights reserved |//|                                               [email]banderassa@ukr.net[/email] | //+------------------------------------------------------------------+ #property copyright "Copyright © 2007, Antonio Banderass. All rights reserved" #property link      "banderassa@ukr.net" #define TREND_UP   1 #define TREND_DOWN 2 #define FLAT      3 //+------------------------------------------------------------------+ //| script program start function                                    | //+------------------------------------------------------------------+ int start()   {    MessageBox("TREND_UP=" + TREND_UP + " TREND_DOWN=" + TREND_DOWN +  " FLAT=" + FLAT);   return(0);   }[p=30, 2, left]注意,我们将常数声明放在文件开头的其他预处理器指令之下。让我们更进一步检查该声明:[/p]#define TREND_UP 1[p=30, 2, left]首先我们编写[b]关键字[/b]#define.它向预处理器表明,之后的内容是[b]常数声明[/b]。然后我们编写[b]常数名称[/b](标识符[b]),[/b]即一个可通过其参考常数值的词。在我们的示例中,它是“TREND_UP”。值 - [b]1[/b]紧跟其后。现在,当预处理器看到源代码中的 TREND_UP 时,它会将其替换为 1,并对所有其他常数执行相同的操作。以下是被预处理器处理前的源代码示例:[b]处理[/b]前[/p]int start()     {      MessageBox("TREND_UP=" + TREND_UP + " TREND_DOWN=" +  TREND_DOWN + " FLAT=" + FLAT);      return(0);     }[p=30, 2, left]与[b]处理后的源代码示例:[/b]:
[/p]int start()     {      MessageBox("TREND_UP=" + 1 + " TREND_DOWN=" + 2 +   " FLAT=" + 3);      return(0);     }[p=30, 2, left]现在您应该理解上一部分中 MODE_ASCEND 和 MODE_DESCEND 所代表的含义了。它们是带相应值的常数。[/p]总结[p=30, 2, left]您已在本文中学习了很多新知识:新循环类型 - while;新条件类型 - switch;运算符 break 和 continue。您学习编写自己的函数和使用多维数组,了解如何使用常数。所有这些都是您的主要工具,是您编写更高级代码(例如用户的指标和 EA)的基础。所以,您要确保完全掌握本文的内容,因为它非常重要,在将来会经常用到。[/p]

页: [1]