C语言程序开发中,if语句太多,整个程序太乱怎么办?

if 分支语句是C语言程序开发中不可缺少的控制结构之一,它广泛存在于各个C语言程序中。甚至有程序员认为写程序就是将各种情况都考虑到,然后使用if-else语句将这些情况描述出来。

问题

不过,在C语言程序开发中,滥用 if 语句常常会让整个代码变得啰嗦且不可读,C语言初学者小明也发现了这一点。下面是一段C语言代码示例,请看:

bool conditionA = executeStepA();
if (conditionA){
    bool conditionB = executeStepB();
    if (conditionB){
        bool conditionC = executeStepC();
        if (conditionC){
            ...
        }
    }
}
executeThisFunctionInAnyCase();


executeStepX() 函数只有在前一个函数执行结果为真时才会执行,而 executeThisFunctionInAnyCase() 函数则无论如何都会执行。小明觉得虽然这样写C语言代码可以实现需求,但是 if 语句链显然不是一种优雅的写法,他希望在自己的代码中避免 if 语句链出现,因此尝试对上述C语言代码做了如下修改,请看:

bool conditionA = executeStepA();
if (!conditionA) return;
bool conditionB = executeStepB();
if (!conditionB) return;
bool conditionC = executeStepC();
if (!conditionC) return;


修改后的C语言代码看起来简洁多了,但是却不能满足需求——原先 executeThisFunctionInAnyCase() 函数无论如何都会执行,而现在它只会在 executeStepX() 函数都成功才会执行。

怎样才能避免 if 语句链,并且完美实现小明的需求呢?

按照小明的思路,其实只要保证 executeThisFunctionInAnyCase() 函数无论如何都被执行就可以了,那完全可以多定义一个函数解决这个问题,相关的C语言代码如下,请看:

void foo()
{
  bool conditionA = executeStepA();
  if (!conditionA) return;

  bool conditionB = executeStepB();
  if (!conditionB) return;

  bool conditionC = executeStepC();
  if (!conditionC) return;
}

void bar()
{
  foo();
  executeThisFunctionInAnyCase();
}


这样就按照小明的思路解决了问题。当然了,问题的答案不止一个,另外一种非常推荐的做法是使用“短路表达式”,相关的C语言代码如下,请看:

关于“短路表达式”的概念,可以参考我之前的文章《》;
if (executeStepA() && executeStepB() && executeStepC()){
    ...
}
executeThisFunctionInAnyCase();


C语言程序的“短路表达式”决定了只有 executeStepA() 函数成功才会接着执行 executeStepB() 函数,只有 executeStepB() 函数也成功,才会执行 executeStepC() 函数。而无论如何,executeThisFunctionInAnyCase() 函数都会被执行,这样就以较为简洁的方式解决了小明遇到的问题。

另外,还有一种很多C语言程序员都鄙视的方法——使用 goto 语句。我知道很多学校很多教材都非常抵制 goto 语句的“使用”,这里的“使用”打上了引号,是因为我认为他们反对的应该是 goto 语句的滥用,事实上,恰当的使用 goto 语句能够在很多时候简化C语言代码,例如:

int foo() {
    int result = /*some error code*/;
    if(!executeStepA()) goto cleanup;
    if(!executeStepB()) goto cleanup;
    if(!executeStepC()) goto cleanup;

    result = 0;
cleanup:
    executeThisFunctionInAnyCase();
    return result;
}


这样的代码风格在 Linux 内核代码中相当常见。也有些程序员习惯使用 do{}while(0) 包裹代码,并且通过 break 关键字提前跳出代码块,但实际上两种方法是一致的。如果还有其他的一些工作需要处理,goto 语句更方便,例如:

int foo() {
    int result = /*some error code*/;
    if(!executeStepA()) goto cleanupPart;
    if(!executeStepB()) goto cleanup;
    if(!executeStepC()) goto cleanup;

    result = 0;
cleanup:
    innerCleanup();
cleanupPart:
    executeThisFunctionInAnyCase();
    return result;
}


这种情况下如果使用 do{}while(0) 方法,就需要使用不止一个循环体,要是如此类推下去,循环体本身也会带来代码复杂度,这样的技巧就显得有些鸡肋了。

小结

本节通过一个例子,简要的讨论了在C语言代码中避免 if 语句链的几种常用方法。当然了,本节只是抛砖引玉,相信读者肯定也有自己的技巧,欢迎在评论区讨论。同时,我们也能看出,C语言程序开发并不只是使用计算机语言描述“流水账”,多思考,总是能写出更加简洁优雅的代码的。

阅读更多:   C语言
添加新评论

icon_redface.gificon_idea.gificon_cool.gif2016kuk.gificon_mrgreen.gif2016shuai.gif2016tp.gif2016db.gif2016ch.gificon_razz.gif2016zj.gificon_sad.gificon_cry.gif2016zhh.gificon_question.gif2016jk.gif2016bs.gificon_lol.gif2016qiao.gificon_surprised.gif2016fendou.gif2016ll.gif