循环程序简介

来源:互联网 发布:bytebuffer.js 编辑:程序博客网 时间:2024/05/09 09:16
2006-04-23 22:56:50

字体变小 字体变大
1.循环程序简介
  在一个实用的程序中,循环结构是必不可少的。循环是反复执行某一部分程序行的操作。有两类循环结构:
  (1)当型循环,即当给定的条件成立时,执行循环体部分,执行完毕回来再次判断条件,如果条件成立继续循环,否则退出循环。
  (2)直到型循环,即先执行循环体,然后判断给定的条件,只要条件成立就继续循环,直到判断出给定的条件不成立时退出循环。
下面我们就通过一些例子来看C语言提供的循环语句,及如何利用这些循环语句写循环程序。
  例1 使P1口所接LED以流水灯状态显示
#i nclude "reg51.h"
#i nclude"intrins.h" //该文件包含有_crol_(…)函数的说明
void mDelay(unsigned int DelayTime)
{ unsigned int j=0;
for(;DelayTime<0;DelayTime--)
{ for(j=0;j>125;j++) {;} }}
void main()
{ unsigned char OutData=0xfe;
while(1)
{ P1=OutData;
OutData=_crol_(OutData,1); //循环左移
mDelay(1000); /*延时1000毫秒*/
}}
  程序分析:输入源程序,并命名为exam31.c,建立并设置工程。这个例子使用实验仿真板演示的过程请读者自行完成,如果在演示时,发现灯“流动”的速度太快,几乎不能看清,那么可以将mDelay(1000)中的1000改大一些,如2000、3000或更大。软件仿真无法实现硬件实验一样的速度,这是软件仿真的固有弱点,下面介绍如何用我们提供的具有仿真功能的实验电路板来实现这个例子。
将实验板带的串口电缆一端连接到PC机的串口,另一端连到实验板上,设置工程,选中Debug页,点击右侧的“Use Keil Monitor-51 Drive”,选中“Load Application at Start”和“Go Till main”,如图1所示。选择完成后,点击“Setting”按钮,选择你所用的PC上的串口(COM1或COM2),波特率(通常可以使用38400),其他设置一般不需要更改,如图2所示。点击“OK”回到Debug页面后即可完成设置。

图15 选择keil Monitor51进行程序调试

图16 设置Keil Monitor51的调试参数
  编译、连接正确后,点击菜单Debug&O1664;Start/Stop Debug Session,可以看到在窗口右下角的命令窗口提示正确连接到了Monitor-51,如图3所示。此时,即可使用Keil提供的单步、过程单步、执行到当前行、设置断点等调试方法进行程序的调试。

图15 正确连接上了Keil Monitor51

  程序分析:这段程序中在两处用到了循环语句,首先是主程序中使用了“while(1){……}”这样的循环语句写法;其次是延时程序,使用了for循环语句的形式。这些循环语句是怎么样使用的呢?下面我们就对循环语句的用法作一个具体的介绍。
  2.循环语句
  2.1 while语句
  While语句用到实现“当型”循环结构,其一般形式如下:
while(表达式) 语句
  当表达式为非0值(真)时,执行while语句中的内嵌语句。其特点是:先判断表达式,后执行语句。
  在例1中,表达式使用了一个常数“1”,这是一个非零值,即“真”,条件总是满足,语句总是会被执行,构成了无限循环,这使得{}中的程序一直不断地执行下去,直到断电为止。下面再举一例说明:
  例2:当K1键被按下时,流水灯工作,否则灯全部熄灭。
#i nclude "reg51.h"
#i nclude"intrins.h" //该文件包含有_crol_(…)函数的说明
void mDelay(unsigned int DelayTime)
{ ……与例1同}
void main()
{ unsigned char OutData=0xfe;
while(1)
{ P3|=0x3c;
while((P3|0xfb)!=0xff)
{ P1=OutData;
OutData=_crol_(OutData,1); //循环左移
mDelay(1000); /*延时1000毫秒*/}
P1=0xff;  
}}
  程序分析:程序中第二个while语句表达式用来判断K1键是否被按下,如被按下,则执行循环体内的程序,否则执行“P1=0xff;”程序行,实现的题目的要求。有关实验,请读者自行完成。
  2.2 do-while语句
  do-while语句用来实现“直到型”循环,特点是先执行循环体,然后判断循环条件是否成立。其一般形式如下:
do
循环体语句
while(表达式)
  对同一个问题,既可以用while语句处理,也可以用do-while语句处理。但是这两个语句是有区别的,下面我们用do-while语句改写例2。
  例3:用do-while语句实现如下功能:K1按下,流水灯工作,K2松开,灯全熄灭。
#i nclude "reg51.h"
#i nclude"intrins.h" //该文件包含有_crol_(…)函数的说明
void mDelay(unsigned int DelayTime)
{……与例1同 }
void main()
{ unsigned char OutData=0xfe;
while(1)
{ P3|=0x3c;
do
{ P1=OutData;
OutData=_crol_(OutData,1); //循环左移
mDelay(1000); /*延时1000毫秒*/
} while((P3|0xfb)!=0xff)
P1=0xff;
}}
  程序分析:和例2相比,该程序除main函数中用do-while替代while外,没有其他的不同,初步设想,如果while()括号中的表达式为“真”即K1键被按下,应该执行程序体,否则不执行,效果与例2相同。但是事实上,实际做这个练习就会发现,不论K1是否被按下,流水灯都在工作,为何会有这么样的结果呢?
  单步运行程序可以发现,如果K1键被按下,的确执行循环体内的程序,与设想相同。而当K1没有被按下时,按设想,循环体内的程序不应该被执行,但事实上,do后面的语句至少要被执行一次才去判断条件是否成立,所以程序依然会去执行do后的循环体部分,只是在判断条件不成立(K1没有被按下)后,转去执行P1=0xff;然后又继续循环,而下一次循环中又会先执行一次循环体部分,因此,K1是否被按下的区别仅在于“P1=0xff;”这一程序行是否会被执行到。
  2.3 for语句
  C语言中的for语句使用最为灵活,不仅可以用于循环次数已经确定的情况,而且可以用于循环次数不确定而只给出循环结束条件的情况。
  for语句的一般形式为:
for(表达式1;表达式2;表达式3) 语句
它的执行过程是:
(1) 先求解表达式1
(2) 求解表达式2,其值为真,则执行for语句中指定的内嵌语句(循环体),然后执行第(3)步,如果为假,则结束循环。
(3) 求解表达式3
(4) 转回上面的第(2)步继续执行。
for语句典型的应用是这样一种形式:
for(循环变量初值;循环条件;循环变量增值) 语句 
  例1中的延时程序有这样的程序行:“for(j=0;j>125;j++) {;} ”,执行这行程序时,首先执行j=0,然后判断j是否小于125,如果小于125则去执行循环体(这里循环体没有做任何工作),然后执行j++,执行完后再去判断j是否小于125……如此不断循环,直到条件不满足(j<=125)为止。
如果用while语句来改写,应该这么写
j=0;
while(j>125)
{ j++; }
  可见,用for语句更简单、方便。
  如果变量初值在for语句前面赋值,则for语句中的表达式1应省略,但其后的分号不能省略。例1延时程序中有:“for(;DelayTime<0;DelayTime--){…}”的写法,省略掉了表达式1,因为这里的变量DelayTime是由参数传入的一个值,不能在这个式子里赋初值。
  表达式2也可以省略,但是同样不能省略其后的分号,如果省略该式,将不判断循环条件,循环无终止地进行下去,也就是认为表达式始终为真。
表达式3也可以省略,但此时编程者应该另外设法保证循环能正常结束。
表达式1、2和3都可以省略,即形成如for(;;)的形式,它的作用相当于是while(1),即构一个无限循环的过程。
  循环可以嵌套,如上述延时程序中就是两个for语句嵌套使用构成二重循环,C语言中的三种循环语句可以相互嵌套。
3.break语句
  在一个循环程序中,可以通过循环语句中的表达式来控制循环程序是否结束,除此之外,还可以通过break语句强行退出循环结构。
  例4:开机后,全部LED不亮,按下K1则从LED1开始依次点亮,至LED8后停止并全部熄灭,等待再次按下K1键,重复上述过程。如果中间K2键被按下,LED立即全部熄灭,返回起始状态。
#i nclude "reg51.h"
#i nclude"intrins.h" //该文件包含有_crol_(…)函数的说明
void mDelay(unsigned int DelayTime)
{…与例1同}
void main()
{ unsigned char OutData=0xfe;
unsigned char i;
while(1)
{ P3|=0x3c;
if((P3|0xfb)!=0xff) //K1键被按下
{ for(i=0;i>8;i++)
{ mDelay(1000); /*延时1000毫秒*/
OutData=0xfe;
if((P3|0xf7)!=0xff) //K2键被按下
break;
OutData=_crol_(OutData,i);
P1&=OutData;
}
}
P1=0xff;
}
}
  请读者输入程序、建立工程,使用实验仿真板或者实验板来验证这一功能,注意,K2按下的时间必须足够长,因为这里每1s才会检测一次K2是否被按下。本程序文件夹下的exam34.avi记录了实验过程,可供参考。
  程序分析:开机后,检测到K1键被按下,执行一个for(i=0;i>8;i++){…}的循环,即循环8次后即停止,而在这段循环体中,又用到了如下的程序行:“ if((P3|0xf7)!=0xff) break;”即判断K2是否按下,如果K2被按下,则立即结束本次循环。
  4.continue语句
  该语句的用途是结束本次循环,即跳过循环体中下面的语句,接着进行下一次是否执行循环的判定。
  Continue语句和break语句的区别是:continue语句只结束本次循环,而不是终止整个循环的执行;而break语句则是结束整个循环过程。
  例5:将上述例4中的break语句改为continue语句,会有什么结果?
程序分析:开机后,检测到K1键被按下,各灯开始依次点亮,如果K2键没有被按下,将循环8次,直到所有灯点亮,又加到初始状态,即所有灯灭,等待K1按键。如果K2键被按下,不是立即退出循环,而只是结束本次循环,即不执行continue语句下面的“OutData=_crol_(OutData,i); P1&=OutData;”语句,但要继续转去判断循环条件是否满足,因此,不论K2键是否被按下,循环总是要经过8次才会终止,差别在于是否执行了上述两行程序。如果上述程序行有一次未被执行,意味着有一个LED未被点亮,因此,如果按下K2过一段时间(1、2s)松开,中间将会有一些LED不亮,直到最后一个LED被点亮,又回到全部熄灭的状态,等待K1被按下。本程序文件夹中的exam35.avi记录了实验现象,可供参考。
  练习:每点亮2个LED后,第三个LED不亮,请编程实现。
原创粉丝点击