关于循环的精确控制

请先思考以下两个问题:

例1.  有一个窗框长 160厘米 ,准备安装7根铁栏杆,栏杆的距离是多少厘米?

例2.    在一条长 40米 的马路的一边,从头到尾每隔 5米 种一棵树,一共可以种多少棵树?

 

本文准备通过以上两个小学问题讨论如下几个问题:

1C++中数组的下标为何从0开始?

2for循环中的控制条件应该如何规范,使之准确的控制循环,避免恼人的“差一错误”

3:何谓非对称边界法与对称边界法,以及它们的优缺点。

 

C++中数组的下标为何从0开始?

请见下图:当你解决上面的问题2后,并且植树后同学A已回学校,但工具未带走,请你帮他带回。他告诉你,我的工具遗忘在公路 20米 处。

你怎么办呢?我想聪明的你应该不会去丈量 20米 吧?既然前面我们已经知道两棵树相聚 5M ,那好

20 / 5 = 4

遗忘的工具确实是在第4棵树处吗?文章开篇引出的问题我想管用了。如果按上图的编号的话,准确地说在第5棵树的地方,计算应该是 20/5+1,举一反三的话, 30米 处应该在30/5+1=7棵树处。这不的确是一种方法。

现在如果我们换个思路呢?改变植物的编号,而不是改变我们的运算,我们看下图:

 

如果按上图编号的话,那我们就可以简单的计算了,不必再有加一的烦恼。而事实上计算机数组下标从零开始的原因之一也是如此,专业术语是“偏移量”如某数组Array[8],5个元素的地址为数据所占的长度*5=25,这也是本着效率之上的原则(让我们少做一次加法)。

 

另一个重要的原因为:

8位机器能表示的最大无符号整数范围应该是255,2^16方最大的数的范围是256,又是差一问题?差到哪去了呢,毫无疑问,又是0了。比如我的数组想存放256个元素,那怎么办?在计算机早期,资源是非常珍贵的,0号元素必须用上。

 

for循环中的控制条件应该如何规范,使之准确的控制循环?

让我们看一个案例:

定义一个10个整形数据的数组,并初始化为0

  1. #include <iostream.h>
  2. #define MAXSIZE 10 
  3. void main()
  4. {
  5. int i ;
  6. int a[MAXSIZE] ;
  7. for(i=0;i<=MAXSIZE;i++)
  8. {
  9.      a[i] = 0 ; 
  10.      cout<<a[i]<<endl;
  11. }
  12. }

 

运行看看,会发生什么?

 

出乎意料的这是一个死循环,究其原因,罪魁祸首是数组越界。而越界的结果是将循环控制变量i被改写为了0,使之又反复循环,无法退出。

 

那我们在程序编写的过程中应该如何去规范地写循环而少出错误呢?下面给大家介绍我收集的一些方法:

一:不对称边界法

先复习下初中数学[a,b),这叫左闭右开。如果我们在循环的过程中遵从左闭右开的原则,越界错误将不会发生。

  1. for(i=0;i < MAXSIZE;i++)
  2. {
  3.      a[i] = 0 ; 
  4.      cout<<a[i]<<endl;
  5. }

请再试试运行程序,结果一切正常。上面的程序至少有一下两个优点:

1 容易得出循环次数 终止点-初始点。

2 出循环后循环变量的值为终止点。

 

二:用不对称边界法修正<严蔚敏 数据结构>上顺序线性表的插入算法

有的朋友会有疑问,不对称边界法真可以做为一个循环条件的准则吗?有没有必须用双闭区间的循环条件的应用,数据结构教材上的算法很多都用的是双闭区间做循环条件。

据我认为,数据结构教材上的循环条件都可以更改来实现这一准则,不但可行,而且更优秀,下面为不熟悉数据结构的朋友附带一个简介,看下图:

   

           图1                                     2  

 

上图中水果是顺序摆放的,如果我们想插入苹果但又不破坏原有的结构,那么必须将插入点所在的水果依次后移,以便腾出位置。

严的算法:

  1. int a[6] = {1,1,1,1,1}; //定义存放水果的容器并放入5个草莓,(1代表草莓,)。
  2. //在位置1处插入苹果,2代表苹果
  3. int *q = &a[1] ; 
  4. for(int *p = a[4];p >=q;p--) *(p+1) =*p ; //给苹果挪出位置
  5. *q = 2 ; //大功告成,插入苹果

 

我的算法:

  1. int a[6] = {1,1,1,1,1}; //定义存放水果的容器并放入5个草莓,(1代表草莓,)。
  2. //在位置1处插入苹果,2代表苹果
  3. for(int *p = a[5];p > a[1];p--) *p =*(p-1) ; //给苹果挪出位置
  4. *p = 2 ; //大功告成,插入苹果 出循环后循环变量为终止点

这两算法没有大的区别。但我认为我的算法更为优秀,理由有下:

1 遵从了不对称边界的原则,为循环控制提供了一个准则。(循环次数为 终止点-初始点

2 相比严的算法少定义个指针变量,或者说少做一次运算(出循环后循环变量为终止点)。

3 为此类寻址提供一个准则,将边界定位到目的地会更易理解。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值