让你提前认识软件开发(16):如何对程序进行优化?

第1部分 重新认识C语言

如何对程序进行优化?

 

         对程序进行优化,是软件开发工程师必然会涉及到的问题。那么为什么要对程序进行优化呢?原因有以下几个:

        第一,在原程序基础之上新增、删除或修改了功能,需要改变原程序流程。客户需求随时可能会变化,今天已经实现的功能,说不定明天就要修改或去掉。落实到程序上面,就需要我们随时准备对写好的代码进行修改,而不要奢望写好之后就永远不要动了。

        第二,原程序有bug。这类情况出现得非常的频繁,很多软件有1.02.03.0等版本,部分原因就是前面版本中程序有问题,在修改程序的过程中使得软件版本不断升级。

        第三,原程序效率较低或不便于阅读,对程序进行优化之后可提高效率或更易于阅读。在软件项目中,对每个函数包含的代码行数都有一定的规定,如果超出了规定的行数,就要考虑对代码进行优化,将部分函数提取出来单独写成一个函数。

 

        有关程序优化,我们要遵循以下两个原则:

        第一,“小步快跑”原则。这个原则是指每修改一点点就对程序进行测试,测试通过之后再修改一点点,再进行测试。如此不断地循环下去,直到程序修改完成并测试通过。这样可以确保程序功能的正确性,减少后期重大变更所带来的成本。

        第二,“两顶帽子”原则。一顶是只重构代码而不新增功能,一顶是增加新的功能以实现新需求。即如果发现原程序存在诸多问题,需要先进行优化后再添加新的功能,那么第一步就优化原代码而不增加新功能,第二步在新代码的基础之上添加新代码以实现新功能。

 

        本文以一个实际的程序为例,详细介绍如何对程序代码进行优化。

 

1.优化之前的程序

       本程序实现将输入字符串中的大写字母变成小写字母的功能,具体代码如下:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

void main()

{

    char s[100];

    unsigned int  i;

         scanf("%s", s);

    for(i=0; i<strlen(s);i++)

       { s[i]=tolower(s[i]); }

    printf("%s\n", s);

}

 

        可以看出,本程序存在如下问题:

        (1)代码排版不工整且无注释。

        (2)变量命名不规范,且在定义的同时没有进行初始化。

        (3)代码缩进不规范,for语句的书写不规范。

        (4)对于输入和输出,没有相应的文字提醒。

        (5)对于大写转换为小写的功能,可考虑封装为一个函数,利于阅读和其它的模块调用。

        可以看出,虽然程序能够实现基本的功能,但并非最优的。以下我们将逐步对代码进行优化。

 

2.对代码进行优化

        Step 1:重新对程序排版,并添加注释

        对于排版不工整且注释过少的代码,优化的第一步就是规范排版并添加必要的注释。排版的规则是“{}”之内的语句相对于“{}”要缩进4个空格,同级的代码要对齐。在程序的头部、函数的头部及关键语句处要添加注释。

        修改之后的代码如下所示:

/**********************************************************************

*版权所有 (C)2014, Zhou Zhaoxiong

*

*文件名称: StrToLowerCase.c

*文件标识:无

*内容摘要:将输入字符串中的大写字母变成小写字母

*其它说明:无

*当前版本: V1.0

*  者: Zhou Zhaoxiong

*完成日期: 20140426

*

*修改记录1//修改历史记录,包括修改日期、版本号、修改人及修改内容

*修改日期: 20140426

*版本号: V1.0

*修改人: Zhou Zhaoxiong

*修改内容:创建

**********************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

/**********************************************************************

*功能描述:主函数

*输入参数:无

*输出参数:无

*返回值:无

*其它说明:无

*修改日期      版本号    修改人          修改内容

* ----------------------------------------------------------------------------------------------

*20140426        V1.0     Zhou Zhaoxiong      创建

***********************************************************************/

void main()

{

    char s[100];

    unsigned int  i;

 

    printf("Input the source string: ");

    scanf("%s", s);                        //读入原始字符串

 

    for (i = 0; i < strlen(s); i ++)

    {

        s[i] = tolower(s[i]);   //将字符串中的大写字母变成小写字母,其它字符不变

    }

 

    printf("Output the destination string: %s\n", s);   //输出目的字符串

}

 

        修改之后,程序的排版工整,在重要的地方添加了注释,且代码的缩进更为合理。

        这里要注意for语句的书写规范。在“for”关键字和“(”之间,要留有一个空格,以区分出关键字。“{}”要与“for”关键字在同一列,“{}”里面的语句不能与“{}”在同一行,并且里面的语句要缩进4个空格。

 

        Step 2:规范变量、函数等的命名及变量初始化

        在实际的软件开发项目中,规定在定义变量的同时要进行初始化,防止变量被错误地引用。

        在上步的基础之上,对代码进一步优化之后如下所示:

/**********************************************************************

*版权所有 (C)2014, Zhou Zhaoxiong

*

*文件名称: StrToLowerCase.c

*文件标识:无

*内容摘要:将输入字符串中的大写字母变成小写字母

*其它说明:无

*当前版本: V1.0

*  者: Zhou Zhaoxiong

*完成日期: 20140426

*

*修改记录1//修改历史记录,包括修改日期、版本号、修改人及修改内容

*修改日期: 20140426

*版本号: V1.0

*修改人: Zhou Zhaoxiong

*修改内容:创建

**********************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

//重新定义数据类型

typedef unsigned char  UINT8;

typedef         int   INT32;

typedef unsigned int   UINT32;

 

/**********************************************************************

*功能描述:主函数

*输入参数:无

*输出参数:无

*返回值:无

*其它说明:无

*修改日期      版本号    修改人          修改内容

* -----------------------------------------------------------------------------------------------

* 20140426        V1.0     Zhou Zhaoxiong      创建

***********************************************************************/

INT32 main()

{

    UINT8  szString[100] = {0};    //用于存放字符串,在定义的同时进行初始化

    UINT32 iLoopFlag   = 0;     //用于表示循环变量,在定义的同时进行初始化

    UINT32 iStrLen     = 0;     //用于表示字符串长度,在定义的同时进行初始化

  

    printf("Input the source string: ");

    scanf("%s", szString);                        //读入原始字符串

 

    iStrLen = strlen(szString);

 

    for (iLoopFlag = 0; iLoopFlag < iStrLen; iLoopFlag ++)

    {

        //将字符串中的大写字母变成小写字母,其它字符不变

        szString[iLoopFlag] = tolower(szString[iLoopFlag]);   

    }

 

    printf("Output the destination string: %s\n", szString);   //输出目的字符串

 

    return 0;               // main函数返回0

}

 

        修改之后,代码更加的规范。以下方面值得注意:

        (1)在前面的文章中,提到了重定义数据类型、变量命名规范等,在此处就有所体现。

        (2)一行代码尽量只完成一个功能,不要企图在一行代码里面完成多个功能。

        (3) main函数有返回值,在函数执行完成之后返回0

 

        Step 3:对代码进行重构,提取关键语句封装为函数

        在经过第二步的优化之后,程序基本达到了规范性、易于阅读性等要求。

        对于代码中的大写字母变成小写字母的语句,我们考虑将它们封装成一个独立的函数,以后程序有类似的功能要求可以直接调用函数。这就涉及到对代码进行重构。

        重构之后的代码如下所示:

/**********************************************************************

*版权所有 (C)2014, Zhou Zhaoxiong

*

*文件名称: StrToLowerCase.c

*文件标识:无

*内容摘要:将输入字符串中的大写字母变成小写字母

*其它说明:无

*当前版本: V1.0

*  者: Zhou Zhaoxiong

*完成日期: 20140426

*

*修改记录1//修改历史记录,包括修改日期、版本号、修改人及修改内容

*修改日期: 20140426

*版本号: V1.0

*修改人: Zhou Zhaoxiong

*修改内容:创建

**********************************************************************/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

 

//重新定义数据类型

typedef unsigned char  UINT8;

typedef          int  INT32;

typedef unsigned int   UINT32;

 

INT32 StrToLowerCase(UINT8 *pszInStr, UINT32 iInLen);     //对函数进行声明

 

/**********************************************************************

*功能描述:主函数

*输入参数:无

*输出参数:无

*返回值:无

*其它说明:无

*修改日期      版本号    修改人           修改内容

* -------------------------------------------------------------------------------------------

* 20140426        V1.0     Zhou Zhaoxiong      创建

***********************************************************************/

INT32 main()

{

    UINT8  szString[100] = {0};    //用于存放字符串,在定义的同时进行初始化

    UINT32 iLoopFlag   = 0;      //用于表示循环变量,在定义的同时进行初始化

    UINT32 iStrLen     = 0;     //用于表示字符串长度,在定义的同时进行初始化

    UINT32 iRetVal     = 0;    //表示调用函数的返回值,在定义的同时进行初始化

   

    printf("Input the source string: ");

    scanf("%s", szString);                        //读入原始字符串

 

    iStrLen = strlen(szString);

 

    iRetVal = StrToLowerCase(szString, iStrLen);            //调用封装好的函数

    if (iRetVal == -1)

    {

        printf("exec StrToLowerCase failed!");

 

        return -1;              //返回-1表示调用StrToLowerCase函数执行失败

    }

 

    printf("Output the destination string: %s\n", szString);   //输出目的字符串

 

    return 0;               // main函数返回0

}

 

 

/**********************************************************************

*功能描述:将字符串中的大写字母变为小写字母

*输入参数: *pszInStr-输入/输出字符串

                           iInLen-字符串长度

*输出参数: *pszInStr-输入/输出字符串

*返回值:      0-成功  -1-失败

*其它说明:无

*修改日期      版本号    修改人          修改内容

* ------------------------------------------------------

* 20140426        V1.0     Zhou Zhaoxiong      创建

***********************************************************************/

INT32 StrToLowerCase(UINT8 *pszInStr, UINT32 iInLen)

{

    UINT32 iLoopFlag = 0;

 

    if (pszInStr == NULL)       //异常保护,判断输入字符串是否为空

    {

        printf("Input string is NULL!");

        return -1;              //返回-1表示该函数执行失败

    }

 

    for (iLoopFlag = 0; iLoopFlag < iInLen; iLoopFlag ++)

    {

        pszInStr[iLoopFlag] = tolower(pszInStr[iLoopFlag]);

    }

 

    return 0;                  //返回0表示该函数执行成功

}

 

         修改之后的代码与最开始的代码相比,无论是代码的整洁程度、注释、变量的命名,还是程序逻辑,都更上一层楼了。

         需要注意以下几个地方:

         (1)函数在被调用之前,一定要进行声明。

         (2)对于传入的指针变量,在使用之前一定要检查该变量是否为空,也就是要进行异常保护。

         (3)代码重构的目的是使得代码的逻辑更加的清晰,并不是说一个函数中代码行数多了,就要将部分代码挑出来写成一个新的函数。

        (4)对于有返回值的函数,在调用的时候一定要对返回值进行处理。如本程序中对StrToLowerCase函数返回的-1进行了判断处理。

 

3.总结

        写出完美的、无bug的代码是每一个软件开发工程师的梦想,因此,掌握基本的对代码进行优化的方法是我们的必修课。

      “实践出真知”,只有通过不断的实践,我们才能够总结出更加实用和有效的代码优化的方法。

 

 

(欢迎访问南邮BBS:http://bbs.njupt.edu.cn/)
(欢迎访问重邮BBS:http://bbs.cqupt.edu.cn/nForum/index)

(本系列文章每周更新两篇,敬请期待!本人新浪微博:http://weibo.com/zhouzxi?topnav=1&wvr=5,微信号:245924426,欢迎关注!)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

周兆熊-IT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值