再重新判断,直到条件为假(即i>=N)时,结束循环。
可以看出,for循环其实就是一个当型循环结构(参见图1.11:
for循环例子)。
图1.11:
for循环例子
7、流程图的简化
一个繁琐的流程图,是画流程图的人的噩梦,同时也是阅读者所不愿意见到的。
因此,我们在画流程图时,不必拘泥于规则和形式,一板一眼。
在适当的地方进行简化,不但可以节省精力和幅面,而且可以让流程图更易于阅读。
让我们对比下面这两个图(参见图1.14:
繁琐的流程图和图1.15:
简洁的流程图)。
这是同一个程序的两种流程图表达方法。
程序的功能,是用查询法对脉冲输入口上输入的脉冲计数,当计数满100次后进行一些处理并退出。
图1.14:
繁琐的流程图
图1.15:
简洁的流程图
很显然,第一个图占用了更多的幅面,却并不易于理解。
而第二个图在经过简化处理后,节省了空间,程序思路反而表达得更加清晰。
我们甚至可以进一步抛弃那些细微末节(参见图1.16:
更简洁的流程图)。
反正这个流程图是给人看的,只要看得懂程序思路,能简化何乐而不为呢?
图1.16:
更简洁的流程图
简单的才是有效的。
适当的简化,是人性化的体现。
总结一下简化的方法:
(1)合并那些相互关联的条件判断。
比如:
当“条件1”满足,且“条件2”满足执行某个动作。
我们可以把这两个条件判断合并后,放入同一个条件判断框中(参见图1.17:
分支结构)。
(2)省去一些不必要的流程线。
对于不会产生歧义的顺序结构流程,可以把那些箭头省略。
节省空间,甚至可以把一些语句合并在一个执行语句框里面。
(参见图1.18:
顺序结构的简化)
4
三、N-S图(盒图)
1、N-S图简介
前面讲到流程图的简化时,匠人已经说过:
可以把一些不会产生歧义的流程线(箭头)省略。
持这种想法的显然不止是匠人一个,据说有两个美国佬走得更远。
这两位名叫I.Nassi和B.Shneiderman的“国际友人”经过潜心研究发现了个规律:
既然任何算法都是由前面介绍的三种基本结构组成,那么各基本结构之间的流程线就是多余的。
于是他们设计了一种新的算法表示法。
用若干个大大小小的框图,通过堆砌或嵌套,来表示程序的流程。
这种流程图被以两个美国天才的名字命名为“N-S图”。
(匠人发现天才也得赶早,否则好事都会被别人抢了去!
)
那一个个框,就像一个个封闭的盒子。
所以,N-S图又被形象地称为“盒图”。
N-S图(盒图)的特性就像盒子一样,结构性很强。
由于取消了流程线,象“goto”这样乱跳的语句,也就没有了表达的形式。
所以,N-S图又被人称为是“结构化流程图”。
也就是说,对于传统的流程图,结构化编程依赖于程序员的自觉自律;而对于N-S图,结构化编程则是由绘图规则来强制保证的。
你想不结构化都不行,呵呵。
N-S图除了表示几种标准结构的符号之处,不再提供其他如“流程线”这样的描述符号,这就有效地保证程序的质量。
NS图的另一个优点是形象直观。
例如循环的范围、条件语句的范围都是一目了然的,所以容易理解设计意图,为编程、排错、调试、维护都带来了便利。
2、N-S图的画法
在N-S图中,一个算法就是一个大矩形框,框内又包含若干小框。
其实只要掌握N-S图的3个基本结构画法,即可掌握N-S图。
匠人在这里简单介绍如下:
(1)顺序结构
顺序结构(参见图1.19:
顺序结构N-S图),语句1、语句2、语句3依次执行。
(2)选择(分支)结构
选择结构(参见图1.20:
选择(分支)结构N-S图),条件为真时执行语句1,条件为假时执行语句2。
如果条件为假时不需执行任何语句,则对应的执行语句框中留空。
散转(Switch)结构作为选择(分支)结构的一个特例,在N-S图方法中较少被人提及。
其实可以用下面这种方法来画(参见图1.7:
散转(switch)结构)。
当表达式结算结果等于某个对应的值时,执行该值下面的语句。
(3)循环结构
循环结构的两种常见形态,包括当型结构(参见图1.22:
当型(while)循环结构N-S图)和直到型结构(参见图1.23:
直到型(do-while)循环结构N-S图)。
3、N-S图的实例
我们把前面介绍过的一个“按键处理子程序”的流程图(参见图1.13:
人性化的流程图),用N-S图形式再来画一次,如下图(参见图1.24:
按键处理子程序N-S图):
4、N-S图的软肋
说了半天N-S图的花好稻好,那为什么在设计中,还是有许多人却放弃使用N-S图,仍旧选择了落后的带箭头的流程图呢?
这得说说N-S图的软肋。
要说这N-S图最大的缺点,就是手工画图时,修改起来没有流程图方便。
尤其是在分支嵌套层次较多时,就比较难画了。
手工画图不便,计算机画图也不便。
目前,匠人也没有找到比较适合画N-S图的计算机绘图软件。
这些,可能是阻碍N-S图进一步推广应用的原因。
四、PAD图(问题分析图)
1、PAD图简介
前面介绍的流程图和N-S图,都是自上而下的顺序描述(流程图也可以画成从左往右或从下往上的形式,不过那不太符合常规习惯)。
这种一维的算法描述方法只能表示程序的流向,而忽视了程序的层次。
为了避免它们的缺陷。
在上世纪七八十年代,日本日立公司发明了一种“问题分析法”PAM(ProblemAnalysisMethod),基于这种方法,他们提出了PAD图,即“问题分析图”(ProblemAnalysisDiagram)。
PAD图用二维树形结构图来表示程序的控制流,除了自上而下以外,还有自左向右的展开。
PAD的强项是能够展现算法的层次结构,更直观易懂。
据说是到目前为止最好的详细设计表示方法之一。
PAD图的优点如下:
(1)结构化的算法描述方法,有效保证程序质量;
(2)二维树型结构,层次清晰,结构明显,表达直观;
(3)既可用于表示程序流程,也可用于描述数据结构;
(4)支持自顶向下、逐步求精方法的使用。
2、PAD图的画法
前面已经反复介绍过结构化编程的三种基本结构了,此处不再浪费文字,直接上图。
3、N-S图的实例
我们把前面已经画过N遍的“按键处理子程序”的流程图用PAD图形式再来画一次(参见图1.30:
按键处理子程序PAD图),请读者对比一下流程图、N-S图、PAD三者间的一些区别。
读者如果没有接触过PAD图,可能一下不太适应。
那就让我们通过这个例图来看看PAD的执行顺序(参见图1.31:
按键处理子程序PAD图的执行顺序)。
具体的流程见图中的虚线箭头,不同粗细的虚线代表不同层次的流程。
从最左主干线的上端的结点开始,自上而下依次执行。
每遇到分支或循环结构,就自左而右进入下一层。
从表示下一层的纵线上端开始执行,直到该纵线下端,再返回上一层的纵线的转入处。
如此继续,直到执行到主干线的下端为止。
如果仔细观察一下PAD图的层次结构,就会发现它的层次与C语言程序的语法缩进层次是对应一致的。
这正是我们一直在强调的PAD的特色。
五、数据流图(DFD)
1、数据流图简介
前面介绍的三种程序规划方法,都是从算法的角度来分解程序的流程。
然而,把程序或软件理解为算法是片面的。
完整的理解是:
“程序=数据结构+算法”。
因此在程序规划的过程中,我们可以从另一个角度——数据的流向——来分析系统。
这就是这一节要介绍的数据流图。
数据流图,即DFD(dataflowdiagram),又被称为数据流程图。
是软件需求分析阶段的重要描述手段。
数据流图是从数据流向的角度来描写软件功能要求系统的组成和各部分之间联系的一种方法。
它的具有直观、简洁等优点,软件开发人员及用户易于理解和接受。
2、数据流图的4要素
在匠人看到的一些资料文献中一般都把数据流图分解为外部实体(数据源和数据终点)、处理(加工)过程、数据流、数据存储(文件)等四部分。
下面依次介绍:
(1)外部实体:
又被称为数据源(输入实体)和数据终点(输出实体)。
代表了数据的外部来源和去处。
也就是说,外部实体属于系统的外部和界面。
它是独立于系统之外,但又和系统有联系的人或事物。
(2)处理过程:
是对数据进行加工的环节。
这种加工处理包括算术、逻辑运算处理,或者进行数据变换。
它用来改变数据值。
每一个处理过程又包括了数据输入、加工和输出3个部分。
(3)数据流:
代表数据处理过程的输入或输出。
数据流指示了数据在系统中的传递流向。
(4)数据存储:
代表数据保存的地方,它用来存储数据。
系统处理从数据存储中提取数据,也将处理的数据返回数据存储。
以上介绍的这四个部分又被称为数据流图的4要素。
3、数据流图的画法
在不同的文献中,对4个要素的定义和描述都不同,甚至连它们的画法也不完全统一。
下面是数据流图的常见画法(参见图1.32:
数据流图举例):
数据流图的画法没有完全统一的规范,不过这并不影响我们用这一工具来分析我们程序中的数据流向。
4、数据流图的应用
软件中除了“程序流程”这条显性的主线,还有另一条隐性的主线,就是“数据流向”。
之所以说“数据流向”这条主线是隐性的,那是因为在系统中,对一个特定数据的输入、处理、存储、输出等过程,往往被分散在许多模块中。
“数据流向”很难通过流程图来描述。
甚至于你把流程图画的越详细,“数据流向”这条线索就越发显得不够清晰。
这时,我们就可以考虑用数据流图来描述,使得“数据流向”显得脉络清晰。
举一个例子,比如一个简单的温度检测与控制系统。
整个过程包括以下几个步骤:
(1)CPU先对负温度系数温度传感器(NTC)进行AD转换,取得采样值,并对这个采样值做递推平均滤波。
(2)然后利用查表方法,把上一步滤波后的采样值转变为温度值。
为了消除抖动,需要进一步做消抖滤波。
滤波后的结果即为当前的实际温度。
(3)另一方面,通过人机界面的按键输入系统,取得系统的设定温度。
(4)实际温度和设定温度分别送显,并把这二者做比较,决定加热控制继电器的状态(闭合/释放)。
整个系统虽然不复杂,但涉及到了数据的输入、加工、输出等诸多环节。
这些操作牵涉到多个模块,包括:
ADC模块、按键功能模块、滤波模块、显示模块、输出控制模块。
这些功能如果用流程图来描述,将需要用到多张流程图;如果用数据流图来描述的话,则只需要一张图就能把整个数据流表达清楚。
(参见图1.33:
温度检测与控制系统数据流图)。
在实际应用中,我们立足于描述一个实际问题,因此在画数据流图时可以不必太过于拘泥于某一个固定的规范。
只要能把思路表达清楚就好。
程序规划的方法有很多,流程图只是其中的一种。
除了流程图,还有N-S图、PAD图、数据流图、层次图、状态迁移图(表)、真值表、数轴、等等。
。
。
。
。
因此,我们后续要继续讲下去。
也希望大家不要把目光局限在流程图上。
欢迎所长、hotpower、HWM、圈圈等各路大虾继续发表真知灼见,兼听则明。
也欢迎其他网友继续互动讨论。