从基础到中级:数组和字符串(一)(基础篇)
「MQL5 里数组和字符串的起步玩法」
在 MT5 的 MQL5 环境里,数组和字符串是绕不开的底层结构。2025 年 7 月 2 日发布的这组基础示例,上线当天就拿到 483 次查看,说明手动撸数据结构的交易者不少。 数组默认是固定大小的静态结构,声明时给定长度就不能随便扩;字符串本质是用 ushort 数组承载的 UTF-16 序列,直接用 string 类型会比自己管数组省事。 想验证很简单:开 MT5 按 F4 进 MetaEditor,新建脚本把下面代码贴进去编译跑一遍,能在日志里看到数组下标和字符串拼接的实际输出。外汇和贵金属品种波动大、点差跳变频繁,用数组缓存报价时得留好越界判断,这类底层错误在高杠杆账户上可能直接让 EA 崩掉。
先动手改代码再谈数据类型
这套材料只服务于学习目的,别把它当可直接上线的 EA 框架。前文讲运算符优先级时埋过一个雷:有些代码第一眼看着对,特定执行顺序下却吐出完全意外的结果,分解(decomposition)写得越多越烂,崩盘概率就越高。 理论部分我故意略过,直接给你路数:把附件里的示例尽可能跑起来,改分解、拧控制流,哪怕和原版只差一行也行。外汇与贵金属杠杆高、回测和实盘偏差大,这类练习只在 MT5 策略测试器里验证用,别贸然挂真实账户。 为什么要绕远路重写?因为附件代码本身能跑出有效结果,你的任务是从另一条路径复现同样输出。很多人觉得这是耗时间,其实这是最快建立自己写法直觉的方式,起初丑没关系。 进入正题前有个硬门槛:变量和常量的声明、初始化、使用你得先熟。本节重心虽在特殊数据类型而非变量本身,但前面那篇运算符优先级 + 本节的基底,是后面复杂领域的入场券。我们从最简角度切入,把底子打平再上难度。
◍ 字符串其实是带终止符的数组
MQL5 站在 C/C++ 与 Python/JS 的中间地带:不像 C/C++ 那样把数组和字符串完全混为一谈,也不像动态语言那样替你隐藏类型。它明确提供了 string 类型,但底层逻辑仍继承自 C/C++——字符串本质是 uchar 或 ushort 数组(取决于字符编码),并带一个特殊标记表示结束。 在 C/C++ 系里,字符串没有原生类型,靠空字符(0 值)当终止符。好处是字符串能撑到几乎占满内存,代价是你不能在内容里放空字符。MQL5 沿用这套逻辑,所以当你要做非常规数据操作,直接玩 string 会撞墙,改用数组更稳。 很多人抱怨“MQL5 做不到这个那个”,深挖下去往往是被困在标准库的基础用法里,没理解数组和字符串在内存里怎么建模。字符串是受限构造,数组才是几乎能装任何类型的通用容器——从 bool 到 class 都行。 对外汇、贵金属 EA 开发来说,这种类型约束直接决定你能否安全处理报价字节流;杠杆市场高风险,误用终止符可能导致缓冲区静默截断。先在 MT5 里敲一段代码看清本质:
「字符串拼接与转义符的实际玩法」
在 MT5 里声明 string 变量,底层其实是让系统自动管内存的字符数组,你不用手动分配。可以直接初始化,也能把两个字符串用加号连起来——加号是字符串少有的原生重载运算符,第 10 行 sz2 = sz0 + sz1 就是把两段话拼成一句送到终端。 想在字符串里换行,别光想着写两个 Print,直接在字面量里插 "\n" 转义序列就行,输出就会断行。MQL5 的转义符沿自 C/C++,比如 "\0" 会直接截断字符串:代码里 sz1 写了 "My first operation \0with strings...",终端就只显示到 \0 前为止。 数字和字符串互转得靠标准库函数,而不是加号。下面这段代码把整数和小数转成字符串再拼进一句话,跑完终端会原样打出带数值的句子。做价差统计或tick分析时,这种拼串方式基本绕不开。 外汇和贵金属行情跳动快、点差跳变频繁,用字符串缓存中间结果时,留意内存和系统自动回收的时机,避免高频循环里产生过多临时对象。
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">class="kw">string sz0 = "Hello world !!!", sz1 = "My first operation with strings...", sz2; sz2 = sz0 + sz1; Print(sz2); } class=class="str">"cmt">//+------------------------------------------------------------------+ 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">class="kw">string sz0 = "Hello world !!!", sz1 = "My first operation with strings...", sz2; sz2 = sz0 + "\n" + sz1; Print(sz2); } class=class="str">"cmt">//+------------------------------------------------------------------+ 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">class="kw">string sz0 = "Hello world !!!", sz1 = "My first operation \0with strings...", sz2; sz2 = sz0 + "\n" + sz1; Print(sz2); } class=class="str">"cmt">//+------------------------------------------------------------------+ class=class="str">"cmt">//+------------------------------------------------------------------+ class="macro">#class="kw">property copyright "Daniel Jose"