c++ - 优雅地尝试以特定方式执行各种功能
问题描述
我试图按顺序执行各种函数 n 次,只有在前一个函数没有返回 false (错误)的情况下才会继续前进,否则我会重置并重新开始。
一个序列的例子是:
- 打开模块 :
module.power(true)
, 3 次尝试 - 等待信号 :
module.signal()
, 10 次尝试 - 发送消息 :
module.sendSMS('test')
, 3 次尝试 - 关闭模块 :
module.power(false)
, 1 次尝试
这些操作中的每一个都以相同的方式完成,只是更改了 DEBUG 文本和启动函数:
DEBUG_PRINT("Powering ON"); // This line changes
uint8_t attempts = 0;
uint8_t max_attempts = 3; // max_attempts changes
while(!module.power(true) && attempts < max_attempts){ // This line changes
attempts++;
DEBUG_PRINT(".");
if(attempts == max_attempts) {
DEBUG_PRINTLN(" - Failed.");
soft_reset(); // Start all over again
}
delay(100);
}
DEBUG_PRINTLN(" - Success");
wdt_reset(); // Reset watchdog timer, ready for next action
有没有一种优雅的方式可以将这个过程放在一个函数中,我可以调用以这种特定方式执行所需的函数,例如:
void try_this_action(description, function, n_attempts)
这将使上面的动作 1-4 像:
try_this_action("Powering ON", module.power(true), 3);
try_this_action("Waiting for signal", module.signal(), 10);
try_this_action("Sending SMS", module.sendSMS('test'), 3);
try_this_action("Powering OFF", module.power(false), 1);
我遇到的一个困难是被调用的函数有不同的语法(有些带参数,有些不带......)。除了在我需要的任何地方复制/粘贴代码块之外,还有更优雅的可模块化方式吗?
解决方案
我遇到的一个困难是被调用的函数有不同的语法(有些带参数,有些不带......)。
这确实是一个问题。与它一起,您可能会在同一函数的实际函数参数中发生变化。
除了在我需要的任何地方复制/粘贴代码块之外,还有更优雅的可模块化方式吗?
我认为您可以制作一个可变参数函数,该函数使用函数的特定知识进行调度,以处理不同的函数签名和实际参数。不过,我怀疑我是否会认为结果更优雅。
我倾向于通过宏来完成这项工作,而不是:
// desc: a descriptive string, evaluated once
// action: an expression to (re)try until it evaluates to true in boolean context
// attempts: the maximum number of times the action will be evaluated, itself evaluated once
#define try_this_action(desc, action, attempts) do { \
int _attempts = (attempts); \
DEBUG_PRINT(desc); \
while(_attempts && !(action)) { \
_attempts -= 1; \
DEBUG_PRINT("."); \
delay(100); \
} \
if (_attempts) { \
DEBUG_PRINTLN(" - Success"); \
} else { \
DEBUG_PRINTLN(" - Failed."); \
soft_reset(); \
} \
wdt_reset(); \
} while (0)
用法就像您描述的那样:
try_this_action("Powering ON", module.power(true), 3);
等等.. 虽然效果就好像你确实在每个位置插入了每个动作的代码,但使用这样的宏会产生更容易阅读的代码,并且在词法上不是重复的。因此,例如,如果您需要更改尝试操作的步骤,您可以通过修改宏一劳永逸地完成。
推荐阅读
- r - R:如何将 rlangs .data 功能与 magrittrs 管道点结合使用?
- bash - 使用 bash 通过具有特定尺寸和位置的终端打开 google chrome
- c# - 试图在响应中隐藏一个属性,但仍然获得它的子属性
- arduino - Wemos D1 R2 板无法连接到 wifi 超过 10 秒
- php - 如何根据mysql中的最后一个条目创建序列号
- nginx - Nginx 在上游响应日志中显示 2 种不同的状态
- elasticsearch - 在logstash elasticsearch中将_Id设置为更新键
- arrays - 类的恒定动态数组的问题
- git - git中的拉取请求显示几个文件的完整差异,即使它在几行中发生了变化
- python - 带有蜻蜓的模态命令