c程序中多层if嵌套结构的几个优化方法(深度好文)

2/22/2017来源:ASP.NET技巧人气:1346

关于c程序中多层嵌套结构的优化方法,在百度中找来找去,发现写这方面的文章不多。下面就我个人总结出来的几个方法,写出来,与大家分享。也希望看到这篇文章的人,要是有更好的方法,也在底下评论留言。您的一点贡献,也许会帮到困扰中的程序员^_^。有什么不足,也麻烦指出来下,共同进步。最后,打字不易,希望转发的人,注明下原出处,谢谢!

方法一:并列法。

示例:

【优化前】:

void func(void)

{

    if( status1() ){

        if( status2() ){

            if( status3() ){

                do_function();

            }

        }

    }

}

想必看到这个东西的人都很痛苦吧微笑,怎么优化?其实很简单,仔细看这结构,1.都没有else;2.三个条件嵌套只做一件事情“do_function();”。那我们可以把这些条件给并列起来,即三个条件同时成立时,做“do_function();”。如下:

【优化后】:

void func(void)

{

    if( status1() \

    && status2() \

    && status3() ){

        do_function();

    }

}

就这样,三个if的嵌套结构,变成了1个if的普通条件判断。

方法二:if-else倒置法。

示例1:

【优化前】:

void func(void)

{

    if( status1() ){

do_function1();

        if( status2() ){

do_function2();

            if( status3() ){

                do_function3();

            }

            else{

                do_unfunction3();

            }

        }

        else{

            do_unfunction2();

        }

    }

    else{

            do_unfunction1();

    }

}

是不是又是心烦的一堆?仔细看这结构,可以发现:1.第二个if在第一个if条件里面,第三个if在第二个if条件里面,也就是说,if都是堆积在一块地方的;2.做完else的事情(do_unfunction1()或do_unfunction2()或do_unfunction3())就结束该函数,退出去了。这样,可以把else的条件改作if的条件,每次去除一层if嵌套结构。什么意思呢?看下面,我们一步一步解开:

【中间过程优化1】:

void func(void) {     if( !status1() ){         do_unfunction1();

        return ;     } //////////////////////////这里是为了便于看清结构     do_function1();     if( status2() ){         do_function2();         if( status3() ){             do_function3();         }         else{             do_unfunction3();         }     }     else{         do_unfunction2();     } //////////////////////////这里是为了便于看清结构 }

【中间过程优化2】:

void func(void)

{     if( !status1() ){         do_unfunction1();         return ;     }     do_function1();     if( !status2() ){         do_unfunction2();         return ;     } //////////////////////////这里是为了便于看清结构     do_function2();     if( status3() ){         do_function3();     }     else{         do_unfunction3();     } //////////////////////////这里是为了便于看清结构 }

【中间过程优化3】:

void func(void) {     if( !status1() ){         do_unfunction1();         return ;     }     do_function1();     if( !status2() ){         do_unfunction2();         return ;     }     do_function2();     if( !status3() ){         do_function3();         return ;     } //////////////////////////这里是为了便于看清结构     do_function3(); //////////////////////////这里是为了便于看清结构 }

咦,“解套了^o^”。没错,就是这样!

【优化后】:

void func(void) {     if( !status1() ){         do_unfunction1();         return ;     }     do_function1();     if( !status2() ){         do_unfunction2();         return ;     }     do_function2();     if( !status3() ){         do_function3();         return ;     }     do_function3(); }

【杂乱条件的规整】

示例2:

【优化前】:

void func(void)

{

    if( status1() ){

        do_function1();

        if( status2() ){

            do_function2();

            if( status3() ){

                do_function3();

            }

            else{

                if( status4() ){

                    do_function4();

                }

                else{

                    do_unfunction4();

                }

                do_unfunction3();

            }

        }

        else{

            do_unfunction2();

        }

    }

    else{

        do_unfunction1();

    }

}

【优化后】:

void func(void)

{

    if( status1() ){

        do_function1();

        if( status2() ){

            do_function2();

            if( !status3() ){

                if( status4() ){

                    do_function4();

                }

                else{

                    do_unfunction4();

                }

                do_unfunction3();

            }

            else{

                do_unfunction3();

            }

        }

        else{

            do_unfunction2();

        }

    }

    else{

        do_unfunction1();

    }

}

这样,又回到了 方法二【示例1】的那种“if都堆积在一块地方”的结构去了,又可以使用方法二来解套。没错,就是要这样! 这种方法的核心思想就是: 1.先把if-else嵌套结构中的if归到一块去(if1嵌套if2,if2嵌套if3,if3嵌套if4。。。); 2.else语句里面整到最后只能有简单的顺序执行语句或者函数调用。然后,就可以放心的使用方法二【if-else倒置法】。 方法三:查表法(这方法的一个好处就是:看懂了,很清晰)。 拿方法二的【示例2】【优化前】例子来作为示例:

【示例】:

【优化前】

void func(void)

{

    if( status1() ){

        do_function1();

        if( status2() ){

            do_function2();

            if( status3() ){

                do_function3();

            }

            else{

                if( status4() ){

                    do_function4();

                }

                else{

                    do_unfunction4();

                }

                do_unfunction3();

            }

        }

        else{

            do_unfunction2();

        }

    }

    else{

        do_unfunction1();

    }

}

这种方法有一个前提,func函数中各个if条件里面的判断都是独立的。即:status1() 结果不受status2()、status3()、status4()的影响,status2()结果也不受其他3个影响,status3()、status4()道理一样;

同时,status1() 、status2()、status3()、status4()也不能受“void func(void)”里面其他语句/函数(do_function1()、do_unfunction3()。。。)的影响。

下面的过程,要是看不懂,就慢慢去领悟吧,夜深了,不多说,抱歉!

【优化后】

struct {

    unsigned int s;

//这里有4个do_func的函数参数,原因是对应着4个if-else嵌套条件,并且抹掉每个if/else内部if-else的条件后,上下部只有一个函数。在设计do_func函数时,也只要有4个函数参数就够了

    void (*do_func_arg1)(void);

    void (*do_func_arg2)(void);

    void (*do_func_arg3)(void);

    void (*do_func_arg4)(void);

}handle_tbl[ ]={ //穷举

    {0,do_unfunction1,NULL,NULL,NULL}, //这里的数字0,最好用宏表示,来表达一个含义。不然也要在这里注释:0表示:AAA

    {1,do_unfunction1,NULL,NULL,NULL}, // 1:BBB

    {2,do_unfunction1,NULL,NULL,NULL}, // 2:CCC ,不注释,谁看得懂啊~,你说是吧!

    {3,do_unfunction1,NULL,NULL,NULL},

    {4,do_unfunction1,NULL,NULL,NULL},

    {5,do_unfunction1,NULL,NULL,NULL},

    {6,do_unfunction1,NULL,NULL,NULL},

    {7,do_unfunction1,NULL,NULL,NULL},

    {8,do_function1,do_unfunction2,NULL,NULL},

    {9,do_function1,do_unfunction2,NULL,NULL},

    {10,do_function1,do_unfunction2,NULL,NULL},

    {11,do_function1,do_unfunction2,NULL,NULL},

    {12,do_function1,do_function2,NULL,do_unfunction4},

    {13,do_function1,do_function2,NULL,do_function4},

    {14,do_function1,do_function2,do_function3,NULL},

    {15,do_function1,do_function2,do_function3,NULL}

};

void do_func(void (*func1)(void), void (*func2)(void), void (*func3)(void), void (*func4)(void))

{

    if(NULL != func1)

        func1();

    if(NULL != func2)

        func2();

    if(NULL != func3)

        func3();

    if(NULL != func4)

        func4();

}

void func(void)

{

    unsignedint i;

    unsigned int s=0;

    s = (s<<1) + (status1()?1:0);

    s = (s<<1) + (status2()?1:0);

    s = (s<<1) + (status3()?1:0);

    s = (s<<1) + (status4()?1:0);

    for(i=0;i<sizeof(handle_tbl)/sizeof(handle_tbl[0]);i++){

        if(i==s) { // s其实是可以自由发挥的,这时,这里的条件换个方式来表示

            do_func(handle_tbl[ i].do_func_arg1,handle_tbl[ i].do_func_arg2,handle_tbl[ i].do_func_arg3,handle_tbl[ i].do_func_arg4);

        }

    }

}

以上的这几个“解套”方法,个人的一点经验总结。希望对你有用。