美文网首页
1 变量 和 预处理程序

1 变量 和 预处理程序

作者: 牛在汇上飞 | 来源:发表于2018-10-23 12:02 被阅读0次

    变量
    变量必须在使用之前定义(声明)。变量必须拥有唯一的标识名。变量的声明包括要定义的变量名及其类型。变量的声明不是语句。

    基本类型如下:
    bool -布尔值 true 和 false;
    string – 字符串;
    double – 带有浮点双精度数字;
    int – 整数;

    变量声明
    示例:
    string 信息;
    int 总单数;
    double 价格;
    bool 买信号;

    其他类型:
    color - RGB颜色的整数编码;
    datetime – 日期和时间,起始时间从1979年1月0:00开始以来的秒数。
    其它的数据类型仅仅在输入参数说明时才有意义,可以更方便地在属性窗口查看。
    示例:
    datetime 始时 = D'2004.01.01 00:00';
    color 修箭色 = C'0x44,0xB9,0xE6';

    数组
    数组是有下标的同类型的一组数据。
    示例:
    int a[50]; // 50个元素的一维整数数组。 引用数组的最后一个元素是a [49]。
    double m[7][50]; // 7个一维数组成二维数组 每一维数组由50个整数组成。引用数组的最后一个元素是m [6] [49]这样的下标。

    只有整数才能作为数组的下标。不允许使用四维以上的数组。数组元素的下标从0开始。
    一维数组的最后一个元素下标是(数组大小-1).
    同样的规则也适用于多维数组:任一维数组下标都是从0开始,到(数组大小-1)结束。
    如果访问超出数组下标范围, 执行时系统将产生下标越界错误 ERR_ARRAY_INDEX_OUT_OF_RANGE。

    局部变量
    在一个函数内部定义的变量是局部变量。其作用范围仅被限定在所定义的函数内。局部变量可以用任意一个表达式值进行初始化。每次调用函数都会初始化一次局部变量。局部变量存储在函数申请的临时空间中。
    示例:
    int somefunc()
    {
    int 值= 0; // 内部变量(局部变量)
    ....
    return(值);
    }

    形式参数

    传递给函数的参数都是局部变量。作用范围限制在函数内。

    形式参数名称应与外部定义的变量名和函数内部定义的局部变量名不同。调用函数时形参变量必须赋值,当然,在函数内,这些形参变量也可以被赋值。

    示例:
    void func(int x[], double y, bool z) // 形参有三个
    {
    if(y>0.0 && !z)
    Print(x[0]);
    ...
    }

    当调用形参变量可用常数进行初始化。在这种情况下,初始化值被当作默认值。并且紧随其后的其它形参变量也必须初始化。
    函数时,初始化过的参数可能被省略不写,默认值会代替它们。
    示例:
    //----------子函数-------------+
    void func(int x, double y=0.0, bool z=true)
    {
    ...
    }

    // 调用情况
    ....
    func(123, 0.5); // 参数z被省略,函数内使用z的默认值
    从外部模块导入的MQL4库函数无法初始化参数的默认值。

    参数采用值传递方式。即在被调用函数内部,如果修改了参数值,这种修改结果将不会带回主调用函数内。
    数组可以作为函数的参数,但是,如果以数组作为参数,修改数组元素值是不允许的。
    它还可能通过引用进行参数传递(称之为引用传递或地址传递)。通过引用传递,这些参数的修改将被传递给调用函数中对应的变量。通过引用传递参数只能在一个模块内进行,库并不提供引用传递。为了表明参数是通过引用传递,在定义时必须在数据类型后放置(&)符号。 数组元素无法通过引用传递给参数。
    (如果有需要 在变量传入由参数传入函数内操作后 保留修改在函数外生效的情况的话,可以在参数定义的类型名称后加上修饰符(&)。MT4没有指针,如果要地址传递的话只能用引用参数调用后;用&还能再得到,相当于调用一个函数返回了你多个值 MT4可以试用DLL里的函数,但是那些很多函数都是地址传递,在MT4里只能用引用来实现。)
    示例:
    void func(int& x, double& y, double& z[])
    {
    double calculated_tp;
    ...
    for(int i=0; i<OrdersTotal(); i++)
    {
    if(i==ArraySize(z))
    break;
    if(OrderSelect(i)==false)
    break;
    z[i]= OrderOpenPrice();
    }
    x= i;
    y= calculated_tp;
    }

    数组也可以使用引用传递,同理,所有修改将反映在源数组中。不同于简单的参数,数组也可以通过引用传递给库函数。
    采用引用传递方式的参数无法初始化默认值。
    传递给函数的最大参数个数不得超过64个。

    静态变量
    “static(静态)”存储类型用于定义一个静态变量。在数据类型前指定”static”说明符说明定义的是一个静态变量。
    示例:
    int somefunc()
    {
    static int flag= 10;
    ....
    return(flag);
    }

    静态变量被存放在内存静态存储区里,在函数运行结束后静态变量的值不会丢失。
    同一模块内所有变量,除函数的形参变量外,都能定义成静态变量。
    静态变量只能由相应类型的常量初始化,这点与一般的局部变量有所不同,局部变量可由任意类型的表达式进行初始化。如果静态变量没有明确地初始化,它将被初始化为零。
    静态变量只可在”init()”函数之前初始化一次。当从定义了静态变量的函数内部退出时,静态变量值不会丢失。

    全局变量
    全局变量是指在整个程序中都能够调用的变量,被定义在各函数之外,与函数同级。只需将变量定义卸载所有嵌套之外即可。
    示例:
    iint s= 10; // 全局变量
    int start()
    {
    ...
    }
    全局变量的作用域是整个程序。全局变量可从任意函数内访问。如果它的值没有被明确定义,初始化值就为零。一个全局变量只能由相应类型的常量进行初始化。全局变量只可以在程序装入到客户机内存时初始化一次。
    (注:全局定义的变量不是指那些能被冠以“GlobalVariable”…()函数(访问的客户端全局变量)!)

    定义外部变量
    外部存储类型extern可以定义一个外部变量。在数据类型之前冠以”extern”说明符指明其为外部变量。
    示例:
    extern double InputParameter1 = 1.0;
    extern color InputParameter2 = red;
    int init()
    {
    ...
    }
    外部变量决定程序的数据输入,他们会直接显示在程序属性窗口,允许由用户自己输入。数组本身不能作为外部变量。

    初始化变量
    定义变量时可以初始化值。如果变量的初始值未被明确指定,它就被初始化为零(0)。全局变量和静态变量仅能被相应类型的常量初始化,而局部变量可以被任意类型的表达式初始化,并不局限于常量。
    全局变量和静态变量只能初始化一次。局部变量在被相应的函数调用时每次都会初始化。
    示例:
    int n = 1;
    double p = MarketInfo(Symbol(),MODE_POINT);
    string s = "hello";
    double f[] = { 0.0, 0.236, 0.382, 0.5, 0.618, 1.0 };
    int a[4][4] = { 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4 };

    数组元素值列表必须被包含在大括号{}内,省略初始化的值被认为零。
    如果初始化定义时没有指定数组大小,编译器将根据初始化值列表的大小来定义。
    多维数组按照一维数组的顺序进行初始化,即初始化序列中不需要另加大括号。
    所有数组,包括那些在局部范围内定义的数组,只能用常数进行初始化。

    外部函数定义
    定义在程序其它部分内的外部函数类型必须明确地说明。缺乏这样定义也许导致在程序的编译、连接、运行时出错。说明一个外部对象时,必须使用关键字#import。
    示例:
    .#import "user32.dll"
    int MessageBoxA(int hWnd ,string szText,
    string szCaption,int nType);
    int SendMessageA(int hWnd,int Msg,int wParam,int lParam);
    .#import "lib.ex4"
    double round(double value);
    .#import

    import语句清楚地说明这些函数是从外部DLL库或编译过的EM4库中引用的。
    变量的指针能传给导入的DLL函数。字符串型数据能作为指针传给相应的内存块(我们应该记住,字符串数据的内部表示分为两个部分:内存块长度和内存块的指针)。如果有必要传递整型或双精度型数据,那么这些类型的一维数组也能作为参数引用传递。
    示例:
    .#import "some_lib.dll"
    void PassIntegerByref(int& OneInt[]);
    .#import
    int start()
    {
    int array[1];
    //...
    PassIntegerByref(array);
    Print(array[0]);
    //...
    }

    预处理程序
    预处理程序是MQL4编译程序的一个特殊的组成部分,用于在程序被编译之前预先准备好程序源码。
    预处理程序能增强程序源码的可读性。在MQL4程序中,通过包含指定的文件可以获得结构化源码,给常量取一个易于记忆的名字有助于增强源码的可读性。
    预处理程序也允许MQL4程序定义特定的参数。
    如果#号置于程序的第一行,那么该行就是预处理程序的控制指令。预处理程序指令以回车换行结束。

    预定义常量
    使用 #define 命令,我们可以在程序中定义符号名或符号常量代表特定的字符串。随后,编译程序会把所有符号名替换成相应的字符串。事实上,这些名称可以被任意的文本替换,并不局限于数字:

    .#define 标示符 值
    常量符号名同样遵守变量名的命名规则,值可以是以下任意类型, 常量在程序中不可更改。

    示例:
    .#define ABC 100
    .#define 圆周率 0.314
    .#define 公司名 "myEAtrade Inc."
    ...
    void ShowCopyright()
    {
    Print("版权所有 ? 2001-2007, ",公司名);
    Print("http://www.myeatrade.com");
    }

    编译控制
    .#property 识别值
    每个MQL4程序允许指定额外的特定参数,这些参数用#property命名,它不需要用户明确地启动程序,就可帮助客户端提供合适的服务。要注意的是,这个功能还与技术指标的外部设定有关。

    示例:
    .#property link "http://www.metaquotes.net"
    .#property copyright "MetaQuotes Software Corp."
    .#property stacksize 1024

    以下是所有的参数名称:
    link string 公司网站的相关连接
    copyright string 公司名称
    library 库
    stacksize int 堆栈大小
    indicator_chart_window void 指标在主图上显示
    indicator_separate_window void 指标在副图上显示
    indicator_buffers int 计算指标的缓冲区个数,最大为8
    indicator_minimum int 副图窗口显示区间最低点
    indicator_maximum int 副图窗口显示区间最高点
    indicator_styleN int 第N根线的 显示样式 (N为1到8)
    indicator_widthN int 第N根线的显示宽度 (N为1到8)
    indicator_colorN color 第N根线的显示颜色 (N为1到8)
    indicator_levelN double 自定义指标的第N条水平线 (N为1到8)
    show_confirm void 在脚本运行之前显示确认框
    show_inputs void 脚本运行前呈现属性表; 禁用show_confirm属性

    示例:
    .#property link "http://www.myeatrade.com"
    .#property copyright "myEAtrade Inc."
    .#property library
    .#property stacksize 1024
    在所执行模块的设置中,编译程序将会保存这些已说明的值。

    文件嵌入包含
    .#include 命令行可以放置在程序的任意部分,但是所有的“文件包含”通常都被统一放置在源代码的开头。调用格式:
    .#include <file_name>
    .#include "file_name";
    示例:
    .#include <WinUser32.mqh>
    .#include "mylib.mqh"

    预处理程序将用WinUser32.mgh文件内容替换这一行。尖括号表示WinUser32.mqh文件将会从默认目录调用(通常默认目录为terminal_ directory\experts\include)。不会搜索当前目录。
    如果文件名用引号括起来,将在当前目录中搜索该文件(源码主文件所在位置)。不会搜索标准目录。

    函数导入
    函数可从MQL4编译过的模块(.EX4文件)和操作系统文件模块(.DLL文件)导入过来。
    模块名需要在#import指令中指定。因为编译程序能够以适当的方式生成被导入的函数调用和传递参数,函数的完整说明是必需的。函数说明要紧跟在 #import "module name” 命令后而,以新的#import命令(不带参数)结束导入函数说明块。
    .#import "file_name"
    func1 define;
    func2 define;
    ...
    funcN define;
    .#import

    导入函数必须有唯一的名称。相同名称的函数无法从不同的模块同时导入。导入的函数名称不能与那些内置函数冲突。

    由于导入函数是在模块之外编译的,编译程序无法检查参数传递的正确性。这就是为什么,为了避免运行时错误,有必要精确地说明参数类型定义和参数顺序的原因。传递到导入函数(从EX 和从DLL模块)的这些参数不能通过默认值获得值。

    示例:

    .#import "user32.dll"
    int MessageBoxA(int hWnd, string lpText, string lpCaption, int uType);
    .#import "stdlib.ex4"
    string ErrorDescription(int error_code);
    int RGB(int red_value, int green_value, int blue_value);
    bool CompareDoubles(double number1, double number2);
    string DoubleToStrMorePrecision(double number, int precision);
    string IntegerToHexString(int integer_number);
    .#import "Expert示例.dll"
    int GetIntValue(int);
    double GetDoubleValue(double);
    string GetStringValue(string);
    double GetArrayItemValue(double arr[], int, int);
    bool SetArrayItemValue(double& arr[], int,int, double);
    double GetRatesItemValue(double rates[][6], int, int, int);
    int SortStringArray(string& arr[], int);
    int ProcessStringArray(string& arr[], int);
    .#import

    对于在MQL4程序执行期间导入的函数,采用了所谓的“后期联编”。这就意味着只要导入的函数未被调用,相应的模块(EX4或DLL)就不会被加载。

    不推荐使用全路径文件名Drive:\Directory\FileName.Ext加载模块。MQL4库会从terminal_dir\experts\libraries文件夹中载入进来。如果没有找到库,就会尝试从terminal_dir\experts文件夹中加载。

    相关文章

      网友评论

          本文标题:1 变量 和 预处理程序

          本文链接:https://www.haomeiwen.com/subject/qlszaftx.html