深入“自顶向下,逐步求精”——面向过程程序设计方法

  程序设计初学者常常受困于不会想问题:“不知道让计算机解决这个问题该如何做”。其实,程序员的一个基本功是,能够将复杂的问题分解开来。学会分解任务,因超级大分为大的、中的、小的、超小的,直到能用很直接的方法解决。记住一个很管用的策略:自项向下,逐步求精。不管做何事,都拿这个策略套一套,程序能编好,其他事也都能做。

  本讲的主要目标在于:

  (1)让你建立“自顶向下,逐步求精”的思维方式,你的大脑先能“机械化”,为指挥计算机“一步一步”地完成任务打下基础;

  (2)让循环的概念在头脑中扎根:在顺序、选择、循环三种控制结构中,循环是最复杂的(只要你掌握了,也就不复杂,而成为一种自然的思维方式了),也是解决问题的最有效的结构,我们就先在此力求先期得到体会。

  (3)C++程序的基本单位是函数,用函数解决更小的问题,这是求精实现的途径。

  这部分内容并未对应到课本上的某一段。要学会“跳跃”的学习方式,自己构建知识,跳出所谓课本的框框。课本给出了一种知识的组织形式,然而知识本身并不本来就呈现这种关系的,这样组织只是作者的一种思路而已。工科学生要学会查阅资料,因为你所需的知识“背”不会,也不应该是用“背书”的方式学的。将课本看成是手册、工具书,无论学到哪儿,能随时恰当、准确地找到书中能够给你启示和参考的地方。不要迷信老师讲过就如何如何,只要你需要,消除心理障碍,你就能读下去,获得自己需要的知识。

  先探讨一个最典型的用循环解决的问题。重点是从中体会用多种方式表示对同一个问题的解决。实际上,我们需要做到的是,很熟练地用随便一种方式将脑袋里形成想法表达出来。   

  【例1】求1+2+3+…+100

  解题思路为:

  • 设:和用sum表示,循环100次,第i次循环将i累加到sum
  • sum初值为0;
  • i初始为1,每循环一次增加1,直到100

  下面是解决这个问题的算法的不同描述形式:

           

  用while循环语句写的程序

#include <iostream>
using namespace std;
int main( )
{
	int i=1,sum=0;
	while (i<=100)
	{	sum=sum+i;
			i++;
	}
	cout<<"sum="<<sum<<endl;
	return 0;
}

  用for循环语句写的程序

#include <iostream>
using namespace std;
int main( )
{
	int i,sum=0;
	for (i=1;i<=100;i++)
			sum=sum+i;
	cout<<"sum="<<sum<<endl;
	return 0;
}

  后面遇到的问题,会用一种形式写出来了,学着用其他方式写一写,用不了多久,脑子就活起来。

  下面,我们用例子体验开始“自顶向下,逐步求精”。如果你现在已经能顺利编出这些程序,也需要再次体会这种思维。

  【例2】在屏幕上输出如图所示的星号图形

  

  程序员不能只看到一堆星星,要用分解的思想,整理出关于图的规律来,或者说,会分层次地看这个问题。这要训练“自顶向下,逐步求精”的思维方式。

  思路:首先看到的是一个图;这个图有6行;每一行有若干个星号。可喜的是,每一行星号的个数还有规律:第i行星号的个数是2*i-1个!

  算法就出来了:

输出6行星号

  这是我们“自顶向下,逐步求精”的第一次分解:将一个图分成了若干行;

  输出6行用一个循环结构解决,循环每执行1次就输出1行,写成伪代码是:

//程序片段(1)
i=1;
While(i<=6)
{
  输出第i行;
  换行
  i=i+1;
}

  “输出第i行”的问题还需要分解下去。实际上,输出“输出第i行”就是要“重复输出2*i-1个星号”,也用一个循环结构完成。

//程序片段(2)
j=1;
While(j<=2*i-1)
{
 输出一个*;
 j=j+1;
}

  将程序片段(1)中的“输出第i行”替换为程序片段(2),整个算法也就清晰了。

i=1;
While(i<=6)
{
  j=1;
  While(j<=2*i-1)
  {
    输出一个*;
    j=j+1;
  }
 换行 i=i+1;
}
	

  用图示再表达一次上述过程,体会“自顶向下,逐步求精”。



  我们可以写出完整的算法,据此写程序也就容易了。无论用while语句,还是for语句。


//用while循环的程序
#include <iostream>
using namespace std;
int main( )
{
  int i,j,n=6;//n可以赋别的值
  i=1;
  while(i<=n)
  {
    j=1;
    while(j<=2*i-1)
    {
      cout<<'*';
      j++;
    }
    cout<<endl;
    i++;
  }
  return 0;
}

  体会本例的任务:将输出一个“星号组成的图案”,分解为“循环输出若干行”,找出各行的规律,能够逐步细化到“输出第i行”这个任务,最终问题细化到只输出一个字符’*’。从“顶层”出发,“向下”(即编程中能直接实现的细节)考虑,“逐步”地“求精”得到达到用C++语句直接描述的程度。对复杂的问题,可能需要更多层次的分解。想一想,我们做任何工作,对大学生活做一宏观的规划、制定一天的学习计划、组织一次班级活动、将来的工程项目开发、做老板后策划一项商业活动、做官员后……无论复杂还是简单,有意或无意地,都是在“自顶向下,逐步求精”的伟大思想的光芒中行走的。只是现在,你需要用心体会,将其成为你的思维惯性。

  好了,回到技术层面,请用N-S图和流程图表示输出星号图的算法。直接用代码的形式在解决大问题时并不总是有效,学会这种表达方法仍是必要的。我们在实践中学习。

  接下来,进一步体验让“自顶向下,逐步求精”更加灿烂的程序部件——函数。请阅读下面的两个函数的定义:

//(1)定义能输出一行m个星号的函数
void printstar(int m)
{
  int j=1;
  while(j<=m)
  {
    cout<<'*';
    j++;
  }
  cout<<endl;
}
//(2)定义在当前行能输出若干指定符号的函数
void printch(char c, int m)
{
  int j=1;
  while(j<=m)
  {
    cout<< c;
    j++;
  }
  cout<<endl;
}

  读懂这段代码应该已经不算难事。接下来,试着在程序中,引入某个函数为你服务吧。比如,可以像下面的程序:

//while循环中调用函数的程序
#include <iostream>
using namespace std;
int main( )
{
  int i,n=6;
  i=1;
  while(i<=n)
  {
    printstar(2*i-1);//调用函数
    i++;
  }
  return 0;
}

  这段代码的功能与前面完全一样,但由于用函数printstar(2*i-1);完成若干个星号的输出,显然,程序简洁了很多。

  还可以这样写:

//while循环中调用函数的程序
#include <iostream>
using namespace std;
int main( )
{
  int i,j,n=6;
  for(i=1;i<=n;i++)
    printch('*',2*i-1);
  return 0;
}

  这时,功能与上述是一样的,换了种循环语句,程序更短些,更重要的是,for循环适合于这种循环次数固定的问题。“计数型”循环用for,要习惯这样。

  另外,printch('*',2*i-1);要换成printch('#',2*i-1);呢?输出的是'#'号图!我们可以很方便地输出其他符号的图。函数就是专门为完成一些通用任务而设的,函数就是为“自顶向下,逐步求精”而生的。

  在面向过程的结构化程序设计中,“模块”是构成程序的基本单元,好比是一座大楼中的各个房间,有办公室、实验室、会议室、门房,各自独立,但共同组成了大楼。有了这样的模块,程序不需要写得很长,将一段功能独立的代码写成一个函数,让别的函数调用就是了(冒昧地用上术语了,定义的函数是要被调用的,于是有了主调函数和被调函数,如例子中,主调函数是main(),被调函数,你懂的)。在对问题分解后,并不一定需要把各级分解的结果堆在一起,组装出一个长长的貌似高水平的程序。“简单”是工程中的第一法则,用函数构造出的程序,结构简单、易读,易于多人合作分工完成,好处是不容易出错,将来的维护也就容易了。

  本节练习:输出各种星号图。针对任务设计算法,并画出流程图。实现时,可以编出不使用函数和使用函数的两种版本。

  每做出一个程序,停下来再看一看程序,默念“自顶向下,逐步求精”。

 

 

 

 

 

 

 

时间: 2024-10-24 14:08:38

深入“自顶向下,逐步求精”——面向过程程序设计方法的相关文章

软件工程之面向过程的软件设计方法

   面向过程,是一种以过程为中心的编程思想,这个过程有人也称之为面向记录,他们不支持丰富的面向对象的特性,比如继承多态等,还有重要的一点是,他们不允许混合持久化状态和域逻辑.   简单的来说,面向过程就是分析解决问题所需要的步骤,然后再用函数把这些步骤一步一步实现,使用的时候一个一个一次调用即可,我想大家都有乘坐动车的经历,比如说,从廊坊站到北京南,面向过程就是动车从廊坊站启动是一个事件,动车到达北京南是另一个事件,在编程序的时候我们关心的是某一个事件,而不是动车本身,我们分别对动车启动和到站

连载:面向对象葵花宝典:思想、技巧与实践(3) - 面向过程 vs 面向对象

面向过程 在介绍面向对象之前,我们首先要介绍"面向过程",首先是因为"面向过程"是软件思想中的鼻祖:其次是因为只有了解了面向过程,你才能更好的了解面向对象!正所谓:知己知彼百战百胜!  面向过程是一种以"过程"作为中心的编程思想,其中过程的含义就是"完成一件事情的步骤".  面向过程其实是一种"机械的思想",它就像流水线一样,一个阶段衔接一个阶段,每个阶段都有自己的输入.处理.输出,而在流水线上流动的就是我

软件工程——面向过程的软件设计方法

  面向过程的软件设计方法是一种最为实际的设计方法.面向过程是一种以过程为中心的编程思想,就是先分析整个程序所需要的步骤,然后通过函数把这些步骤一个一个实现,在程序设计的时候有需要直接调用就行了.我们常用的面向对象的设计方法也包含面向过程的思想,面向过程是一种最基础的设计方法.面向过程的软件设计方法考虑的是实际的实现,一般是自顶向下逐步实施.因此面向过程最重要的是模块化设计,而面向对象主要是把事务付给对象,对象具有属性和方法,抽象出来的是一个类.因此对于规模不是很大的程序,面向过程的设计方法相对

php面向对象与面向过程两种方法给图片添加文字水印_php实例

目前绝大多数PHP程序员使用面向过程的方式,因为解析WEB页面本身就非常"过程化"(从一个标签到另一个标签).在HTML中嵌入过程处理代码是很直接自然的作法,所以PHP程序员通常使用这种方式. 如果你是刚接触PHP,用面向过程的风格来书写代码很可能是你唯一的选择.但是如果你经常上PHP论坛和新闻组的话,你应该会看到有关"对象"的文章.你也可能看到过如何书写面向对象的PHP代码的教程.或者你也可能下载过一些现成的类库,并尝试着去实例化其中的对象和使用类方法--尽管你可

《C++程序设计教程(第3版)》——第1章,第3节程序设计方法

1.3 程序设计方法C++语言的两个组成部分是过程性语言部分和"类"部分.过程性语言部分和C语言没有本质差别."类"部分是C语言中没有的,它是面向对象程序设计的主体.要学好面向对象程序设计,首先必须具有过程性语言的基础.所以学习C++,首先必须学习其过程性语言部分,然后再学习"类"部分.过程性语言部分采用的是结构化程序设计方法,"类"部分采用的是面向对象程序设计方法,程序设计方法正在从结构化方法向面向对象方法演变.C语言仅支持

PHP中的面向对象和面向过程

对象|过程 简介"真正的天才具有正确评价不确定的,有风险的和矛盾的信息的能力.--邱吉尔" 使用许多编程语言时,你通常只能使用面向对象或面向过程二者之一的编程方式.而在PHP中,你可以自由选择或混用.目前绝大多数PHP程序员使用面向过程的方式,因为解析WEB页面本身就非常"过程化"(从一个标签到另一个标签).在HTML中嵌入过程处理代码是很直接自然的作法,所以PHP程序员通常使用这种方式. 如果你是刚接触PHP,用面向过程的风格来书写代码很可能是你唯一的选择.但是如

jQuery删除一个元素后淡出效果展示删除过程的方法

 这篇文章主要介绍了jQuery删除一个元素后淡出效果展示删除过程的方法,实例分析了jQuery中fadeTo及slideUp等方法的使用技巧,非常具有实用价值,需要的朋友可以参考下     本文实例讲述了jQuery删除一个元素后淡出效果展示删除过程的方法.分享给大家供大家参考.具体分析如下: 当我们删除一个元素时希望能看到删除的过程,这个效果通过对元素进行淡出展示动态化删除过程. ? 1 2 3 4 5 6 7 $("#myButton").click(function() { $

java-通俗解释:什么是面向对象?与面向过程区别在哪?

问题描述 通俗解释:什么是面向对象?与面向过程区别在哪? 什么是面向对象?与面向过程区别在哪?用通俗的话语解答,不要理论性的专业术语,最好是拿生活中的熟知的事物去类比解释!!!多谢~ 解决方案 面向对象和面向过程不矛盾,事实上,Java也是面向过程的编程语言. 面向过程是指,允许在程序中定义函数或者方法.也许你觉得奇怪,难道还有语言不能定义函数方法么?早期的basic就不可以,只能用跳转来实现函数调用. 面向对象更近一步,允许你将"过程"(函数.方法)以及它们的上下文相关的数据封装成对

面向对象与面向过程有什么区别

问题描述 面向对象与面向过程有什么区别 面向过程难道就是面向对象的执行过程吗?这感觉有点像按词解释新手请教 解决方案 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了. 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为. 例如五子棋,面向过程的设计思路就是首先分析问题的步骤:1.开始游戏,2.黑子先走,3.绘制画面,4.判断输赢,5.轮到白子,6.绘制画面,7.