FOR 语句基础篇:把循环控制流从根上拆明白(基础篇)
🔁

FOR 语句基础篇:把循环控制流从根上拆明白(基础篇)

(1/2)· 很多人以为 FOR 是第三种循环就多记一套语法,其实它和 WHILE 同宗不同用

案例拆解新手友好 第 1/2 篇
初学者常把 FOR、WHILE、DO WHILE 当成三套独立语法死记,结果写嵌套循环时逻辑乱成一团。其实控制流语句核心极少,FOR 只是把初始化、判断、步进压进同一行的语法糖。先吃透前提,后面中级篇的复杂结构才扛得住。

FOR 循环在 MT5 里的真实跑法

MQL5 里 FOR 语句是批量处理 K 线或订单的最直接结构,语法和 C 语言一致:初始化、条件判断、迭代三步写在同一行。对做价格行为回测的交易者来说,它比 while 更不容易写出死循环。 下面这段是最小可运行骨架,用来遍历最近 100 根柱体并打印它们的收盘价。你在 MT5 里新建脚本粘进去,编译后拖到图表就能在专家日志看到输出。 外汇与贵金属杠杆高、滑点随机,回测结论只代表历史概率,实盘可能偏离。 循环上限写死 100 只是示例;真做策略时建议用 Bars() 或 iBars() 动态取可用柱数,避免越界报错 4806。

MQL5 / C++
for(class="type">int i=class="num">0; i<class="num">100; i++)
   Print(Close[i]);

「为什么先把基础嚼碎再碰 FOR」

这部分内容定位在教育培训,除了搞懂思路和写法,不建议直接拿去实盘跑任何样例程序。外汇和贵金属杠杆高、滑点大,光会语法不等于能赚钱,这点先说在前头。 上篇讲了 SWITCH 的最简用法,重点不是背结构,而是想清楚它和 IF、WHILE 之间怎么替、怎么选。基础不牢,后面看复杂框架会一直卡壳。 有人觉得目前材料太浅,想直接上高阶。以多年写 MQL5 的经验看,概念在最根本那一层通了,复杂主题往往一眼就透。这也是拆开逐篇讲的原因。 控制执行流的语句里,现在只剩 FOR 没聊。它确实是 MQL5 里这类操作符的最后一环,但我会单开一节慢慢拆,不跟前面混着讲。

◍ 为什么 MQL5 里还要多一个 FOR

控制流命令在任一门语言里都极少,MQL5 同样如此:WHILE、DO WHILE 加上 FOR 就覆盖了绝大多数循环需求,而库函数与保留字的数量却能以千计。多数交易者写 EA 时卡住的从不是语句种类,而是没吃透这几条基础控制流。 FOR 之所以和 WHILE、DO WHILE 并存,是因为在某些场景里后两者并不顺手。典型差异在 CONTINUE 的使用:当循环控制要素需要集中声明时,FOR 把初值、条件和步进都收在头部,WHILE 的控制逻辑却常散落在循环体某行,改起来要翻完整段。 统计社区代码风格可见,FOR 是程序员偏好最高的循环写法,原因就是可读性——只看声明就能修控制逻辑,不必进循环体找边界。外汇与贵金属杠杆高、滑点突发,EA 逻辑若因循环混乱出错,实盘可能瞬间回撤,验证代码前务必在 MT5 策略测试器跑历史段。 我们先从最基础的 FOR 形式切入,假设你已用过 WHILE 和 DO WHILE,理解头部三要素会快很多;后面谈运算符优先级时再回头看,会发现 FOR 某些写法藏着坑。

用 FOR 改写 while 时 info 的值去哪了

把一段 while 循环原样翻译成 FOR,最常踩的坑不是语法,而是变量生命周期和打印时机。下面这段是原始 while 版:循环前 info 被赋为 10,每次迭代先自减再打印,跑完 10 到 1,循环结束后 info 实际值为 0。 [CODE] //+------------------------------------------------------------------+ #property copyright "Daniel Jose" //+------------------------------------------------------------------+ void OnStart(void) { char info = 10; Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); while (info) { info = info - 1; Print(__FUNCTION__, " : ", info); } Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ #property copyright "Daniel Jose" //+------------------------------------------------------------------+ void OnStart(void) { char info = 10; Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway..."); for( ; info; ) { info = info - 1; Print(__FUNCTION__, " : ", info); } } [/CODE] 第一行 OnStart 里 char info = 10; 是局部变量,仅在函数栈内活;while (info) 靠 info 非零做条件;循环体先 info = info - 1 再打印,所以首行打出 9。 改写成 for( ; info; ) 只动第 10 行,条件段留空、迭代段也留空,完全复用 while 的判断逻辑。MT5 里跑出来和图 01 一致:打印 9 到 1,循环后 info 同为 0。 别把空段当摆设 FOR 的三个括号段(初始化、条件、迭代)任一段都能空着,但空着不代表不执行——条件段每次迭代前仍被求值。若你把自减挪进迭代段写成 for( ; info; info = info - 1) 却在循环体内又打印 info,首行就会是 10 而非 9,因为自减发生在打印之后。 另一个易错版是把 char info = 10 保留、循环体内不碰 info 而靠别处改,结果可能直接死循环或只打一次 10。想验证的话,把第 6 行改成 9 再跑,会看到打印从 8 开始——这证明输出完全绑在 info 的初始值与自减次序上,不关 FOR 本身什么事。外汇与贵金属脚本里这种计数错一位,可能导致 K 线遍历漏根,实盘前务必在策略测试器单步核对。

MQL5 / C++
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart(class="type">void)
{
    class="type">char info = class="num">10;

    Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");

    while (info)
    {
        info = info - class="num">1;
        Print(__FUNCTION__, " : ", info);
    }

    Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class="macro">#class="kw">property copyright "Daniel Jose"
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">void OnStart(class="type">void)
{
    class="type">char info = class="num">10;

    Print(__FUNCTION__, " ", __LINE__, " It will be executed anyway...");

    for( ; info; )
    {
        info = info - class="num">1;
        Print(__FUNCTION__, " : ", info);
    }
}
让小布替你跑这套
这些诊断小布盯盘的 AIGC 已内置,打开对应品种页即可看到循环逻辑在策略回测里的实际表现,你专注判断边界条件就好。

常见问题

常见控制流主要是 IF、SWITCH、WHILE、DO WHILE 和 FOR 等少数几个;库函数成千上万但那是另一回事,语言骨架靠这几样撑起来。
有必要。FOR 把计数器初始化和步进写在头部,适合确定次数的遍历,代码更短也更不易漏写自增导致死循环。
可以,小布盯盘的 AIGC 模块能对相关品种页的策略代码做结构诊断,标出可能的越界与空转循环,省去人工逐行核对。
因为库和范式一直在变,但控制流这类根基二十年没大动,扎实底子才能快速适配新任务,而不是背 API。