假设我有这样的伪代码:
bool conditionA = executeStepA();
if (conditionA){
bool conditionB = executeStepB();
if (conditionB){
bool conditionC = executeStepC();
if (conditionC){
...
}
}
}
executeThisFunctionInAnyCase();
函数executeStepX当且仅当前一个成功时执行。
在任何情况下,executeThisFunctionInAnyCase函数都应该在最后被调用。
我在编程方面是一个新手,所以很抱歉提出一个非常基本的问题:有没有一种方法(例如在C/ c++中)以代码易读性为代价,避免长if链产生那种“金字塔式代码”?
我知道如果我们可以跳过executeThisFunctionInAnyCase函数调用,代码可以简化为:
bool conditionA = executeStepA();
if (!conditionA) return;
bool conditionB = executeStepB();
if (!conditionB) return;
bool conditionC = executeStepC();
if (!conditionC) return;
但是约束是executeThisFunctionInAnyCase函数调用。
break语句可以以某种方式使用吗?
因为你也有……代码块…]在执行之间,我猜你有内存分配或对象初始化。通过这种方式,你必须关心在退出时你已经初始化的所有东西,如果你遇到问题,任何函数都会返回false,也要清理它。
在这种情况下,根据我的经验(当我使用CryptoAPI时),最好的方法是创建小类,在构造函数中初始化数据,在析构函数中反初始化数据。下一个函数类必须是前一个函数类的子类。如果出错-抛出异常。
class CondA
{
public:
CondA() {
if (!executeStepA())
throw int(1);
[Initialize data]
}
~CondA() {
[Clean data]
}
A* _a;
};
class CondB : public CondA
{
public:
CondB() {
if (!executeStepB())
throw int(2);
[Initialize data]
}
~CondB() {
[Clean data]
}
B* _b;
};
class CondC : public CondB
{
public:
CondC() {
if (!executeStepC())
throw int(3);
[Initialize data]
}
~CondC() {
[Clean data]
}
C* _c;
};
然后在你的代码中你只需要调用:
shared_ptr<CondC> C(nullptr);
try{
C = make_shared<CondC>();
}
catch(int& e)
{
//do something
}
if (C != nullptr)
{
C->a;//work with
C->b;//work with
C->c;//work with
}
executeThisFunctionInAnyCase();
我想这是最好的解决方案,如果每次调用ConditionX初始化一些东西,分配内存等。最好确保所有东西都被清理干净。
有几个回答暗示了我看到并使用过很多次的模式,尤其是在网络编程中。在网络堆栈中,经常有很长的请求序列,其中任何一个都可能失败并停止进程。
常见的模式是使用do {} while (false);
我使用宏while(false)使它做{}一次;常见的模式是:
do
{
bool conditionA = executeStepA();
if (! conditionA) break;
bool conditionB = executeStepB();
if (! conditionB) break;
// etc.
} while (false);
这种模式相对容易阅读,并且允许使用能够正确销毁的对象,还避免了多次返回,从而使步进和调试更容易一些。
这看起来像一个状态机,这很方便,因为您可以使用状态模式轻松实现它。
在Java中,它看起来像这样:
interface StepState{
public StepState performStep();
}
实现如下所示:
class StepA implements StepState{
public StepState performStep()
{
performAction();
if(condition) return new StepB()
else return null;
}
}
等等。然后你可以将大if条件替换为:
Step toDo = new StepA();
while(toDo != null)
toDo = toDo.performStep();
executeThisFunctionInAnyCase();
一个简单的解决方案是使用一个条件布尔变量,同一个变量可以重复使用,以检查顺序执行的所有步骤的结果:
bool cond = executeStepA();
if(cond) cond = executeStepB();
if(cond) cond = executeStepC();
if(cond) cond = executeStepD();
executeThisFunctionInAnyCase();
并不是说在此之前没有必要这样做:bool cond = true;... 然后后跟if(cond) cond = executeStepA();cond变量可以立即赋值给executeStepA()的结果,因此使代码更短,更易于阅读。
另一个更奇特但有趣的方法是这样的(有些人可能认为这是IOCCC的一个很好的候选,但仍然如此):
!executeStepA() ? 0 :
!executeStepB() ? 0 :
!executeStepC() ? 0 :
!executeStepD() ? 0 : 1 ;
executeThisFunctionInAnyCase();
结果是完全相同的,如果我们做什么OP张贴,即:
if(executeStepA()){
if(executeStepB()){
if(executeStepC()){
if(executeStepD()){
}
}
}
}
executeThisFunctionInAnyCase();