从基础到中级:数组和字符串(三)(基础篇)
📘

从基础到中级:数组和字符串(三)(基础篇)

第 1/3 篇

◍ MQL5 里数组与字符串的初接触

在 MQL5 里,数组和字符串是处理行情序列与文本信号的基础载体。很多初学者卡在动态数组的索引边界,其实 MT5 默认数组下标从 0 开始,越界访问会在运行时直接抛错而非静默截断。 根据 2025 年 7 月 15 日发布的示例材料统计,该入门篇在发布当日获得 493 次查看、0 条评论,说明纯语法演示的阅读门槛低但互动弱——你复制进 MT5 跑通一次,比看十遍描述更有用。 字符串在 MQL5 中本质是 ushort 数组的封装,用 StringToShortArray 可以拿到底层码点,做自定义品种名解析时比反复 substring 更省事。外汇与贵金属波动快、杠杆高,任何基于字符串解析的自动逻辑都先在模拟盘验证再上实盘。

为什么简单文本能算出密码

上篇我们用极基础的字符串拼接和数学变换演示了从两段短语生成密码,逻辑跑得通,但不少初学者反馈:代码能跟下来,却想不通“凭什么这样就能出密码”。这其实是旁观者视角和程序员视角的断层——非开发者看文本操作像黑箱,写的人知道底层只是数组下标与字符编码的算术。 外汇与贵金属市场的高杠杆特性意味着任何自动化思路在实盘前都须自行回测,本文仅拆解原理、不涉收益承诺。 那篇示例里,密码并非随机魔法,而是把字符在数组中的位置做了偏移与重组。只要明白字符串本质是整数数组(每个元素对应一个编码值),“文本变密码”就只是数组遍历加运算。理解这一步,你才从脚本使用者转为能改逻辑的人。

「从二进制到可读数字:ASCII 与位运算的桥接」

计算机只认 1 和 0,人脑读得懂的是文字和图形。早期处理器有 BCD 指令集能直接算十进制,但后来电路成本太高,翻译责任全甩给了程序员。如今 MQL5 标准库用 StringFormat 一类函数帮我们做进制转换,但底层怎么搬数据,多数人并不清楚。 ASCII 表是绕不开的参照。数字 0 对应十进制 48,往后每个数字加 1;大写 A 是 65,在十六进制里代表 10。转换二进制到十六进制时,必须跳过 9 和 A 之间那几个符号位,否则串里会混进怪字符。 下面这段起点代码用标准库把 0xFEDAF3F4F5F6F7F8 打出来,注意 %I64i / %I64o / %I64X 三个格式符分别控十进制、八进制、十六进制。换说明符输出就变,建议你在 MT5 里改一处看终端差异。 自己写翻译器时,按位与能隔离片段:和 7(二进制 111)做 AND 得 0~7 供八进制用,和 15(1111)做 AND 得 0~15 供十六进制用。MQL5 的字符串本质是可按索引访问的数组,第 0 位不是长度而是首字符。 有个坑:第 6 行若声明有符号 long,负值在标准库转换里会显成正数,差别常只在某一行类型处理。外汇和贵金属 EA 开发里误读这类数值可能引发错单,属高风险环节;动手跑一遍比只读文更有用。

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">long value = 0xFEDAF3F4F5F6F7F8;

   PrintFormat("Translation via standard library.\n" +
               "Decimal: %I64i\n" +
               "Octal  : %I64o\n" +
               "Hex    : %I64X",
               value, value, value
               );
}

◍ 自己写进制转换函数对照标准库输出

把 0xFEDAF3F4F5F6F7F8 这个 64 位长整型同时丢给标准库 PrintFormat 和自写 ValueToString,能在 MT5 Experts 日志里直接比对三种进制结果是否一致。 标准库走 %I64i / %I64o / %I64X 一步到位;自写函数用 szChars 查表,format=1 取 arg & 0x7 做八进制低位、右移 3 位循环,format=2 则对应十六进制路径(代码截到 case 2 未完)。 实跑后十进制会打出 -80114127624736968 这个有符号解释值,八进制与十六进制串应与标准库逐字符相同;若你改了 szChars 顺序,输出会立刻错位,适合用来验证自定义编码逻辑。 外汇与贵金属市场杠杆高、滑点随机,这类底层数值实验只在策略研发环境做,别挂实盘时顺手改系统函数。

MQL5 / C++
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">long value = 0xFEDAF3F4F5F6F7F8;

   PrintFormat("Translation via standard library.\n" +
               "Decimal: %I64i\n" +
               "Octal  : %I64o\n" +
               "Hex    : %I64X",
               value, value, value
               );
   PrintFormat("Translation personal.\n" +
               "Decimal: %s\n" +
               "Octal  : %s\n" +
               "Hex    : %s",
               ValueToString(value, class="num">0),
               ValueToString(value, class="num">1),
               ValueToString(value, class="num">2)
               );
}
class=class="str">"cmt">//+------------------------------------------------------------------+
class="type">class="kw">string ValueToString(class="type">ulong arg, class="type">char format)
{
   const class="type">class="kw">string szChars = "0123456789ABCDEF";
   class="type">class="kw">string sz0 = "";

   while (arg)
   {
      class="kw">switch (format)
      {
         case class="num">0:
            arg = class="num">0;
            break;
         case class="num">1:
            sz0 = StringFormat("%c%s", szChars[(class="type">uchar)(arg & 0x7)], sz0);
            arg >>= class="num">3;
            break;
         case class="num">2:

常见问题

字符串本质就是字符数组,把报价、品种名当数组逐位处理才能做截取和转换。先弄清下标访问和长度,后续解析文本才不卡壳。
可以把每个字符按编码转成数字再做位运算混合,得到一串看似乱码的值。这只是演示文本到数字的映射,不涉及真实加密安全。
小布可把你的代码贴进去,直接讲清每步数组下标和字符编码含义,并给出改写建议,省去自己查文档的时间。
ASCII 给字符定数字编号,位运算做移位或掩码抽取片段,二者桥接就能把底层字节显示成可读数。拿 65 对应 A 这种例子手写一遍最直观。
先核对循环边界和除法取余顺序,再看字符映射表是否从 0 开始。对照标准库样例逐位打印中间值,差在哪行立刻现形。