当前位置:C++技术网 > 资讯 > 练习项目:2 基本框架扩展转换功能实现

练习项目:2 基本框架扩展转换功能实现

更新时间:2015-06-25 22:48:55浏览次数:1+次

    前两篇文章:控制台的项目的建立,请阅读《VS中控制台项目创建方法步骤》。然后阅读基本框架的构建文章《控制台项目(练习项目)基本框架实现》,请先阅读这两篇文章后再阅读本文。
    在VS中为了控制台程序运行完后一闪即过,那么为了方便,也不用使用《控制台项目(练习项目)基本框架实现》文章讲到的在主函数中使用输入暂停,我们在写一个框架函数包装一下,这样使用就很简单了。当然在框架中,你可以使用系统的一个函数来停止。为了减小程序大小,那么就只使用输入暂停就可以了。
    扩展转换功能函数,我们就单独添加功能函数文件。使用时包含以下功能函数的头文件,即可使用。本文实现长度的互换。头文件和源文件分别取名为"Lenght.h"和"Lenght.cpp",添加方法在前两篇中讲过了。
    这里问题来了,看看什么问题?
    我们要实现毫米、厘米、分米和米之间的互换,根据排列组合,一共有12组。如果不假思索的直接写12组函数,那么代码就太冗余了,开发效率就太低了。并且在后续的扩展和选择模式时就很麻烦了。所以,打开头文件时,我就迟迟没有动手。在干什么呢?我在寻找一个合适的模式,以最少的代码实现所有的转换。要达到少一个函数嫌少,多一个函数嫌多。
    几分钟后,我想到了一种方式。因为涉及到的转换单位有4个,那么最低要四个函数来实现。所以我就定义了四个函数,分别表示转换到一个单位,然后从哪个单位转换过来,则使用函数中的第一个参数作为标志,这样就可以区别,在函数内部实现条件转换,使用switch来实现。
    而在4个函数中,每一个函数中的代码基本相同,都有4个情况(case)。你可能会问,转换到自己为什么还要加上一种情况呢?如果不要,那不是可以省掉一种情况吗?为了让代码整洁,不容易出错,提高代码的统一风格,综合考虑,使用统一的方式来使用,有利于降低代码的维护成本,减少了出错的可能性。每个代码结构差不多,变动的地方也是有规律的,这样很容易检查代码是否出错,这也可以给代码精简提供一个很好的基础。
    这些实现分析,可以让你很好的了解到扩展功能的背景和开发应该遵循的好的习惯,不要上来就写代码,规划好代码,为日后写代码可以节约大量时间,可以让程序 稳定性大大提升,代码质量也提高很多。不同水平的人写同样一个功能的代码,代码风格和质量也不一样,所以,即使简单,也要沉下心用心做。在此基础上,项目扩展会越来越大,在那个时候,如果有一个好框架的支持,增加模块,删除模块都是轻而易举的事情,而不会为改动模块头疼。

    框架中扩展了一个暂停程序,不让一闪而过的框架函数。函数声明在头文件"Afx.h"中,实现在"Afx.cpp"中。
    函数声明如下:

void AfxPause();// - 输入字符,回车结束程序

    函数实现如下:
void AfxPause()
{
    AfxMessage("输入任意键字符,回车键结束程序!");
    int i;
    cin>>i;
}

    代码说明:
    1.函数没有任何参数,没有返回值,调用非常简单,不用重复写代码,只要一个函数调用即可,使用很方便。
    2.代码实现中,还是调用框架的函数来实现。这也是代码重用的好处。虽然是简单的cout,但是使用起来也是挺麻烦的。

    框架中还扩展了一个重载的输出数字的输出函数。
    函数声明如下:

void AfxMessage(double d,bool bAddNewLine=true);// - 数字版本

     函数实现如下:

void AfxMessage(double d,bool bAddNewLine)
{
    cout<<d;
    if(bAddNewLine)cout<<endl;
}
     代码说明:
    1.使用double类型来输出数字,可以兼容整型等各种数字,都是默认转换成double,在输出,就减少了很多版本了。

    长度转换功能模块头文件如下:

/* - 设计开发编写:codexia ,分享自C++技术网 - */
/* 
  - 长度单位换算
  - 毫米、厘米、分米、米相互转换
*/
#define FROM_MM 0 // - 源数据单位为毫米
#define FROM_CM 1 // - 源数据单位为厘米
#define FROM_DM 2 // - 源数据单位为分米
#define FROM_M  3 // - 源数据单位为米

double LenConvertToMM(int iFlag,double uiSrc);// - 转换到毫米
double LenConvertToCM(int iFlag,double uiSrc);// - 转换到厘米
double LenConvertToDM(int iFlag,double uiSrc);// - 转换到分米
double LenConvertToM (int iFlag,double uiSrc);// - 转换到米

    头文件说明:
    1.注释要在最开头写清楚,表明此功能模块实现什么功能,现在有哪些功能,为日后维护一看便知,每次修改模块时,要修改顶部的说明。
    2.使用宏来定义几个转换模式,以后使用宏就不容易将标志弄错。在宏后面一定要加好注释,让代码便于维护,是一个很好的代码风格。
    3.转换中会出现“除”操作,所以,不能定义为整型。又为了支持所有数字的转换,那么就使用double得到更大的范围和精度。
    4.功能函数前面带上Len表示是长度模块的。ConvertTo表示转换到,后面的大写字母表示目标单位。
    5.参数中第一个表示转换的起源单位,第二个参数输入要转换的数字,返回值为转换后的结果。
    6.虽然每个函数名字比较清楚,但是还是要写好注释,以免日后维护混淆。这都是好的编程习惯。


    长度转换功能模块源文件(CPP)如下:

#include "Lenght.h"

double LenConvertToMM(int iFlag,double uiSrc)
{
    double uiRet=-1;
switch(iFlag)
{
   case FROM_MM:
       uiRet = uiSrc;
       break;
                case FROM_CM:
       uiRet = uiSrc*10;
       break;
                case FROM_DM:
       uiRet = uiSrc*100;
       break;
                case FROM_M:
       uiRet = uiSrc*1000;
       break;
}
return uiRet;
}
double LenConvertToCM(int iFlag,double uiSrc)
{
    double uiRet=-1;
switch(iFlag)
{
    case FROM_MM:
       uiRet = uiSrc/10;
       break;
    case FROM_CM:
       uiRet = uiSrc;
       break;
    case FROM_DM:
       uiRet = uiSrc*10;
       break;
    case FROM_M:
       uiRet = uiSrc*100;
       break;
}
return uiRet;
}
double LenConvertToDM(int iFlag,double uiSrc)
{
double uiRet=-1;
switch(iFlag)
{
    case FROM_MM:
       uiRet = uiSrc/100;
       break;
    case FROM_CM:
       uiRet = uiSrc/10;
       break;
    case FROM_DM:
       uiRet = uiSrc;
       break;
    case FROM_M:
       uiRet = uiSrc*10;
       break;
}
return uiRet;
}
double LenConvertToM (int iFlag,double uiSrc)
{
double uiRet=-1;
switch(iFlag)
{
    case FROM_MM:
       uiRet = uiSrc/1000;
       break;
    case FROM_CM:
       uiRet = uiSrc/100;
       break;
    case FROM_DM:
       uiRet = uiSrc/10;
       break;
    case FROM_M:
       uiRet = uiSrc;
       break;
}
return uiRet;
}

    源文件说明:
    1.函数中都是使用统一的四个case来转换。简化代码,便于维护。对自己转到自己也提供统一的转换。
    2.使用一个临时变量,在case中设置这个变量,然后最后统一返回这个值。这里说一下,就是提供统一风格,不容易出错。如果在case中这里return,那里return,就容易漏掉一个return。

    主函数中使用功能函数如下:

#include "Afx.h"
#include "Lenght.h"
int main()
{
    AfxMessage("米转换到厘米:",false);// - 不换行输出
    int i;
    cin>>i;
    double dRet = LenConvertToCM(FROM_M,i);
    AfxMessage(dRet);
    AfxPause();
    return 0;
}
     使用框架函数输出提示,然后输入,然后使用功能模块转换,最后又使用框架函数输出,使用框架函数阻止一闪而过!这样主函数很简短,并且在主函数文件中没有多余的函数声明定义等,这样代码很好维护,逻辑清晰,这是普通代码所没有的特点。或许现在效果还不明显,等扩展多了,这个好处就越来越明显了。
    以后的扩展,都以这种功能模块扩展,方便简单。大家可以接见这个模式来扩展。