文章 "在MQL5程序中使用断言" - 页 2

 
Sergey Eremin:

如果要通过条件编译轻松删除 TEST_TEXT,我会考虑将 Prints 移到宏内部。在当前版本中,我认为删除 TEST_TEXT 很容易,但删除 Prints 本身却不容易。

是的,谢尔盖,我考虑过这个问题。不过,也许我只是考虑得不多,还没有 "想通"。

简单地说,根据具体情况和comment()Alert( ) 可以作为测试信息输出的来源(以便在不需要查看行的情况下及时通知某些事情,而且如果它不令人讨厌和/或已知它不会 "分离"),而不是Print()

这就是为什么我暂时从以下方面着手:

  • 如果代码中出现 #define c 关键字,只需注释掉或删除 #define;
  • 如果在包含文件中加入了带关键字的 #define,只需注释或删除关于包含文件的一行即可(我可能更喜欢包含文件的选项)、

然后编译器就会很快告诉你哪些行已经无法使用了。即使进行了搜索,您也可以通过按下 MetaEditor 面板上的按钮,完全注释掉暂时不需要的行。

不过,我同意最好能有一些通用的变体。

 
Dina Paches:
是的,谢尔盖,我想过这个问题。不过,也许我只是考虑得不多,还没有 "上手"。

不过,根据具体情况和comment()Alert() 可以代替Print(),作为测试信息的输出源(如果它不令人讨厌的话)。

所以现在我假设

  • 如果代码中出现 #define c 关键字,只需注释掉或删除 #define;
  • 如果将带有关键字的 #define 放在包含文件中,只需注释或删除有关包含文件的一行即可(我可能更喜欢包含文件的选项)、

然后编译器就会很快告诉你哪些行已经无法使用了。

但我同意,形成某种通用的变体当然更好。

从原则上讲,是的,这种方法有助于彻底清除代码中不相关的打印内容。的确,有多少次你似乎不需要它,但过了几个月你又需要它:)

但在这种情况下,您可以尝试从 git/svn(作为 svn 的特例 -MQL5 存储)回滚到所需的版本,但要有所保留(通过回滚一件事,我们可能会失去另一件事的相关性)。

 
Sergey Eremin:

原则上,是的,这种方法有助于完全清除代码中不相关的打印内容。然而,有很多次这样的情况:你似乎不再需要它了,但几个月后你又需要它了:)

但在这种情况下,您可以尝试从 git/svn 回滚到所需的版本(作为 svn 的一种特殊情况 -MQL5 存储),但要有所保留(通过回滚一件事,我们可能会失去另一件事的相关性)。

由于尚未看到您的回复,我在帖子中补充说明了这一点。但就意义而言,它保持不变,与您所说的并不对立。

是的......,你说得没错,过一段时间后,有必要再次这样做)。在工作版本中,这些行文已经被 "清理 "过了,回滚到以前的行文并不总是合理的。

 
Sergey Eremin:
但原则上,如果有必要,"测试 "检查的数量还是可以明显少于从头开始编写代码的数量。不过,这还是从一个自己编写代码、然后自己完善/修改代码的人的角度来判断的。也就是说,这是一种相当狭隘的观点。
 
Sergey Eremin:

附/附注:我想澄清一下,我指的不是 "搜索......",而是 "转到指定行 "或 "文件中的函数列表"。

P./S.:不过,回到这篇文章,再次感谢你在文章中引用的应用语句的能力,这非常有趣。谢谢。

 
Dina Paches:

同时,我下载了assert.mqh 文件,并在其中添加了一行:

然后在代码中看起来是这样的:

  Print(TEST_TEXT,"a = ",a);

也就是说,在构建代码时,只需应用输出的信息,并期望在代码工作结束时,可以轻松删除输出的 "工作 "信息(我相信,许多人在构建代码的各个阶段可能都是这样做的)。

您可能还会发现这个宏很有用

#define  PRINT(x)  Print(#x,"=",x)
//+------------------------------------------------------------------+
//| 脚本程序启动功能|
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   PRINT(ORDER_TYPE_BUY_STOP_LIMIT);
   PRINT(ORDER_TYPE_SELL_STOP_LIMIT);
   PRINT(ORDER_POSITION_ID);
   PRINT(POSITION_TYPE_BUY);
   PRINT(POSITION_TYPE_SELL);
   
   PRINT(POSITION_TIME);
   PRINT(POSITION_TIME_MSC);
   PRINT(POSITION_TIME_UPDATE);
   PRINT(POSITION_TIME_UPDATE_MSC);
   PRINT(POSITION_TYPE);
   PRINT(POSITION_MAGIC);
   PRINT(POSITION_IDENTIFIER);
 
Rashid Umarov:

您可能还会发现这个宏很有用

顺便说一句,我认为最好能添加有关 # 和多行宏的文档。没有学过 C 语言的人可能会对文章和注释中的代码感到困惑:)
 
Rashid Umarov:

这个宏可能有用

不可能,但家里确实需要这样一个东西。谢谢。

您提供了一个很好的基础,可以在此基础上构建 "肉"。除此以外,这也再次证明了天才就是简单。

我想,谢尔盖写 篇文章时,大概也是这个意思。

不过,我仍然需要了解/熟悉与这种结构有关的许多事情。

其中包括在打印前进行数据转换时(不仅要考虑到通过打印进行打印,还要考虑到在注释或提示中进行打印)。例如,在使用 DoubleToString 或 TimeToString 时,变量名不会丢失。

例如,我现在是这样写的:

#define  TEST_PRINT(x)   Print(__LINE__,", ",__FUNCTION__,", ",#x,"=",x)
#define  TEST_COMMENT(x) Comment(__LINE__,", ",__FUNCTION__,", ",#x,"=",x)
#define  TEST_ALERT(x)   Alert(__LINE__,", ",__FUNCTION__,", ",#x,"=",x)

在专家选项卡中,它是这样显示的:


而在图表上,如果是应用程序,也是同样的注释。

也就是说,price_0 变量在 DoubleToString 中 "丢失 "了。

不过,在代码中使用这种 #define 输出测试字符串已经比我之前给出 的方法更容易了。尽管这还不是最好的选择。


附/附注: 现在我想,转换函数的应用也会输出,并在测试文本中清晰可见--这反而可能是有用的。一般来说,变量名并不会丢失。只是之前我并不这么认为,而且在输出信息时眼睛也不太习惯。


Sergey Eremin:
顺便说一句,我觉得最好能添加有关 # 和多行宏的文档。没有学过 C 语言的人可能会对文章和评论中的代码感到困惑:)。
那就太好了。
 
附/附注:现在我越看输出,就越意识到,是的,输出和将数据 从一种格式转换 为另一种格式的函数在测试记录中肯定很方便。这只是一个尽可能优化的问题。
 
Andrey Shpilev:

1.为什么要使用宏?宏很不方便,不是所有的条件都可以输入宏,而且如果宏出了问题,调试起来也非常困难。实现琐碎的程序更容易。

在这种情况下,宏是唯一的选择。