1。面向对象基本原理一 再论面向过程

面向对象与其说是一个计算机问题,倒不如说他是一个哲学问题。面向对象是用来描述客观世界的一种方法,而不仅仅是一种软件开发思想。

早期的BASIC,ALGOL,C,PASCAL被称为“面向过程”编程语言,这一点从BASIC的“过程”和C语言的“函数”中得到了明显的体 现。面向过程语言模拟的是工作的流水作业方式——定义好每一个流程节点的处理方法,然后把这些方法连接起来,组成一个完整的过程,做到这一步即完成编程。

下面用一个简单的范例来说明面向过程编程的方法(C语言范例):

我们要创建一个菜单项目,在控制台显示两组菜单,并根据菜单的提示完成相应的操作。

  • 第一组菜单两项,分别为:输入字符串、退出;
  • 第二组菜单四项,分别为:重新输入字符串、显示字符串、翻转字符串、退出。

要完成这一目的,我们把整个过程分为三步:

  1. 显示菜单
  2. 响应用户输入
  3. 根据用户输入进行对应处理

执行完第三步后,流程应该返回第一步,所以这三步组成了一个循环,循环肯定不能为死循环,所以应该有一个退出循环的布尔条件,项目要求要保存一个字 符串,所以还应该有一个保存字符串的缓冲区,代码如下:

0 主流程

#include   < stdio . h >
#include   < stdlib . h >
 
typedef   int   BOOL;
 
#define   TRUE   1
#define   FALSE   0
 
//   程序的退出条件变量
10  static   BOOL   g_bQuit   =   FALSE;
11   
12  //   保存用户输入字符串的 缓冲变量
13  static   char   g_szBuffer[ 1024 ]   =   " " ;
14   
15  int   main( int   argc,   char *   argv[])
16  {
17      //   用于接收用户输入菜单项的变量
18      int   nInput   =   - 1 ;
19   
20      //   循环三个流程
21      while   ( ! g_bQuit)   {
22          ShowMenu();
23          nInput   =   GetUserInput();
24          DoSomethingWithInput(nInput);
25   
26          //   在三步流程完毕后,输出一个空行
27          printf( " /n " );
28      }
29      system ( " pause " );
30      return   0 ;
31  }

OK,通过上面的代码,我们已经建立起来基本的流程,我们发现这其中缺少了三个重要子流程,ShowMenu,GetUserInput和 DoSomethingWithInput,那么我们进一步完善这三个子流程。

1 ShowMenu流程:在上述代码14行的位置加入如下代码:

/* *
  *   根据情况显示菜单
  */
void   ShowMenu()
{
    //   判断g_szBuffer中是否保存了字符串,根据这一条件,显示第一个菜单或第二个 菜单
    if   (g_szBuffer[ 0 ]   = =   ' /0 ' )   {
        ShowMenuFirst();
    }   else   {
10          ShowMenuSecond();
11      }
12      printf( " /n请输入您的选项: " );
13  }

好了,现在我们将ShowMenu流程进一步细化了,根据g_szBuffer变量中是否存储字符串这一条件,分支执行不同的流程:

1.1 ShowMenuFirst流程:在函数 ShowMenu之前 加入如下代码

/* *
  *   显示菜单1
  */
void   ShowMenuFirst()
{
    printf( " 1.   输入字符串 " );
    printf( " /n0.   退出/n " );
}

1.2 ShowMenuSecond流程:在函数 ShowMenuFirst之后 加入如下代码

/* *
  *   显示菜单2
  */
void   ShowMenuSecond()
{
    printf( " 1.   重新输入字符串 " );
    printf( " /n2.   显示字符串 " );
    printf( " /n3.   翻转字符串 " );
    printf( " /n0.   退出/n " );
10  }

至此,我们完成了流程一,ShowMenu流程。

接下来,我们进行GetUserInput 流程,这一步很 简单,从用户输入中获取输入的菜单项。

2 GetUserInput 流程:在函数ShowMenu 之 后 加入如下代码

/* *
  *   获取用户输入
  *   返回:用户输入的结果。
  */
int   GetUserInput()
{
    //   从输入流里读取一个字符
    int   nInput   =   fgetc(stdin);
    //   刷新输入流,清空输入流中的其它字符
10      fflush(stdin);
11      return   nInput;
12  }

好了,这就完成了GetUserInput 流程,对于面向 过程初学者来说,很容易犯得一个错误就是:流程冗余,很多同学在该流程中过多的考虑“是不是该判断一下用户输入是否正确”,那么切记,既然这一步流程的作 用就是获取用户输入,那么就不应该考虑任何其它内容。我们继续下一步流程:

3 DoSomethingWithInput流程:在函 数GetUserInput之后 输入如下代码

/* *
  *   根据用户输入执行对应的流程。
  *   参数:nInput,   用户输入的字符
  */
void   DoSomethingWithInput( int   nInput)
{
    switch   (nInput)   {
    case   ' 0 ' :
        AskIfCanQuit();
10          break ;
11      case   ' 1 ' :
12          GetInputString();
13          break ;
14      case   ' 2 ' :
15          if   (g_szBuffer[ 0 ]   = =   ' /0 ' )   {
16              ShowError();
17          }
18          ShowInputString();
19          break ;
20      case   ' 3 ' :
21          if   (g_szBuffer[ 0 ]   = =   ' /0 ' )   {
22              ShowError();
23          }
24          ReverseInputString();
25          break ;
26      default :
27          ShowError();
28      }
29  }

如上所示,我们进一步把DoSomethingWithInput流程细化为了如下几个子流程:

  • AskIfCanQuit流程:询问用户是否需要退出;
  • GetInputString流程:提示用户输入一个字符串;
  • ShowInputString流程:显示用户输入的字符串;
  • ReverseInputString 流程:翻转用户输 入的字符串;
  • ShowError流程:显示错误信息。

注意case ‘2’和case ‘3’的情况,因为这两部分处于菜单二的选项范围,所以要能够执行这两步,必须确保当前显示的是菜单二,于是这里采用了和ShowMenu内部同样的逻 辑,来判断当前显示的菜单种类。我们继续:

3.1 ShowError流程,在函数DoSomethingWithInput之前 加入如下代 码

/* *
  *   显示错误信息
  */
void   ShowError()
{
    printf( " 对不起,您输入的菜单项不存在,请重新输入。/n " );
}

3.2 AskIfCanQuit 流程,在函数ShowError之后 加入如下代码

/* *
  *   询问用户是否需要退出
  */
void   AskIfCanQuit()
{
    //   接收用户输入字符的变量
    int   nInput   =   - 1 ;
 
    printf( " /n是否要退出?[Y/N]: " );
10   
11      //   从用户输入中读取字符
12      nInput   =   fgetc(stdin);
13      fflush(stdin);
14   
15      //   判断字符是否为y(忽略大小写),如果是y,则设置全局变量g_bQuit的值,交给 主流程处理退出
16      if   (nInput   = =   ' y '   | |   nInput   = =   ' Y ' )   {
17          g_bQuit   =   TRUE;
18      }
19  }

3.3 GetInputString流程,在函数 AskIfCanQuit之后 加入如下代码

/* *
  *   获取用户输入字符串
  */
void   GetInputString()
{
    //   定义接收用户输入的字符
    int   nInput   =   EOF;
    //   统计用户输入字符个数
    int   i   =   0 ;
10   
11      printf( " /n请输入任意字符串: " );
12      //   循环,直到符合如下条件之一:1、读取到输入流结尾;2、用户输入了一个换行字符 (/n);3、用户输入字符数大于缓冲区长度
13      do   {
14          //   读取一个字符并存入缓冲区
15          nInput   =   fgetc(stdin);
16          g_szBuffer[i + + ]   =   ( char )nInput;
17      }   while   (nInput   ! =   EOF   & &   nInput   ! =   ' /n '   & &   i   <   1024 );
18   
19      //   在字符串末尾加上结束符,注意这里要覆盖掉最后一个字符,因为上一个循环导致最后一个 输入的总是无效字符
20      g_szBuffer[i   -   1 ]   =   ' /0 ' ;
21      printf( " 输入完毕。/n " );
22  }

3.4 ShowInputString流程,很简单不多说了,在函数GetInputString之后 加入如下代码

/* *
  *   显示用户输入字符串
  */
void   ShowInputString()
{
    printf( " 您输入的字符串为:%s/n " ,   g_szBuffer);
}
 

3.5 ReverseInputString流程,用了一个很简单的翻转算法,在函数ShowInputString 之 后 加入如下代码

/* *
  *   翻转字符串
  */
void   ReverseInputString()
{
    //   pH指向字符串起始位置
    char *   pH   =   g_szBuffer;
    //   pE指向字符串最后一个字符(/0字符)的前一个字符(即最后一个有效字符)
    char *   pE   =   g_szBuffer   +   strlen(g_szBuffer)   -   1 ;
10      //   定义临时变量
11      char   cTemp;
12   
13      //   循环,直到pH,pE指针指向内存地址重合
14      while   (pH   < =   pE)   {
15          //   交互字符位置
16          cTemp   =   * pH;
17          * pH   =   * pE;
18          * pE   =   cTemp;
19   
20          //   pH后移,pE前移
21          + + pH;
22          - - pE;
23      }
24      printf( " 翻转完毕/n " );
25  }

至此,我们完成了所有的代码。

这段代码很简单,得到需求后,我想大部分同学都能够实现出正确的结果。这里使用这个简单的例子只是想表达一个思想:面向过程的程序设计思想。

从整个代码的构思到书写的过程中,我们看到了一个重要的设计方法:自上而下的程序设计方法,我们一开始并没有过多的去考虑程序细枝末节的细节,而将 注意力全部放在如何完成主要流程上面。我们制定了三大步主要流程,然后将注意力放在流程1(ShowMenu)上,发现它又可以分解为两部流程,于是继续 分解完成ShowMenuFirst流程和ShowMenuSecond流程,而我们所有的代码,都是基于这个原则设计并书写出来的。

这种逐步细化的方法,很容易就将一个看似不容易完成的整体问题,分解为可以轻易完成的若干个小问题,然后各个击破,完成最终的代码设计。

我们其后要开始介绍面向对象,但永远牢记,我们的计算机本质是面向过程的,计算机做事情永远是一步一步的,所以无论我们使用多么先进的程序设计、开 发思想,这一课介绍的方法都将贯穿始终。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值