Lazarus讲义5循环结构二.docx
- 文档编号:9327781
- 上传时间:2023-05-18
- 格式:DOCX
- 页数:27
- 大小:225.02KB
Lazarus讲义5循环结构二.docx
《Lazarus讲义5循环结构二.docx》由会员分享,可在线阅读,更多相关《Lazarus讲义5循环结构二.docx(27页珍藏版)》请在冰点文库上搜索。
Lazarus讲义5循环结构二
第六课循环结构程序设计
(二)
6.2while语句(当型循环)
一、语法:
while布尔表达式do语句;
或:
while布尔表达式do
begin
语句;
语句;
语句;
end;
二、说明:
1、语义:
当执行到while语句时
(1)计算布尔表达式的值
(2)如果布尔表达式的值是true,就执行do后面的语句
如果布尔表达式的值的false,则转到(4)
(3)转到
(1)(重新计算布尔表达式的值)
(4)退出循环,继续执行while后面的语句。
2、while循环是不定次数的循环,它的循环开始和结束,由布尔表达式决定。
3、while循环中由于没有循环控制变量,不能自动实现变量的递变,因此,初学者
极易发生死循环。
如:
t:
=true;
whiletdo循环体;
必须记住:
在循环体内,必须至少一次对布尔表达式中的某个变量重新赋值。
否则,每次计算布尔表达式的值相同。
4、正因为循环体内至少有一个语句需要改变一个变量的值,所以,一般循环会不
止一个语句,大多数情况下,循环体是一个复合语句。
5、while循环常用于查找“第一个符合要求的值”。
即在布尔表达式中进行判断,
循环体内对穷举对象递增(常用inc或dec),一旦找到对象就立即退出循环,
此时,相关变量保存的正好是所需的值。
三、例题:
16、求a,b的最大公约数。
(辗转相除法)
programxunhuan_ex16;
varinf,outf:
text;
a,b,c:
integer;
begin
assign(inf,'xunhuan_ex16.in');assign(outf,'xunhuan_ex16.out');
reset(inf);rewrite(outf);
read(inf,a,b);
ifa begin c: =a;a: =b;b: =c; end; whileamodb<>0do begin c: =amodb; a: =b; b: =c; end; write(outf,b); close(outf); end. 17、判断n是否是素数。 programxunhuan_ex17; varinf,outf: text; n,i: integer; begin assign(inf,'xunhuan_ex17.in');assign(outf,'xunhuan_ex17.out'); reset(inf);rewrite(outf); read(inf,n); i: =2; while(nmodi<>0)and(i<=trunc(sqrt(n)))doinc(i); ifi elsewrite(outf,true); close(outf); end. 18、求满足s=12+22+32+42+……+n2<=m的最大n值。 programxunhuan_ex18; varinf,outf: text; n,m,s,i: integer; begin assign(inf,'xunhuan_ex18.in');assign(outf,'xunhuan_ex18.out'); reset(inf);rewrite(outf); read(inf,m); s: =0; i: =1; whiles<=mdo begin inc(i); s: =s+i*i; end; write(outf,i-1); close(outf); end. 19、读入一句英文语句,以句号为结束,且句中无句号。 统计其中单词个数。 分析: 只要遇到分隔符(即非字母),就可以认为一个单词结束。 但是要考虑 到可能有连续的分隔符,如两个空格及标点符号连在一起。 programxunhuan_ex19; varinf,outf: text; n: integer; st: char; t: boolean; begin assign(inf,'xunhuan_ex19.in');assign(outf,'xunhuan_ex19.out'); reset(inf);rewrite(outf); read(inf,st); n: =0; t: =false; whilest<>'.'do begin ifnot(((st<='Z')and(st>='A'))or((st<='z')and(st>='a')))then begin ifnot(t)theninc(n); t: =true; endelse begin t: =false; end; read(inf,st); end; ifnot(t)theninc(n); write(outf,n); close(outf); end. 20、读入一个不超过9位的正整数,计算各位数字之和。 programxunhuan_ex20; varinf,outf: text; n: longint; s: integer; begin assign(inf,'xunhuan_ex20.in');assign(outf,'xunhuan_ex20.out'); reset(inf);rewrite(outf); read(inf,n); s: =0; whilen<>0do begin s: =s+nmod10; n: =ndiv10; end; write(outf,s); close(outf); end. 21、1*2*3*……*n(n<1000)结果是一个很大的数,求这个数末尾有多少个连续 的零。 基本思路: (1)连乘积的位数太多,不可能全部乘完后再统计零的个数,必须 一边乘,一边统计,统计后立即清除相应的零。 (2)即使清除了末尾的零,但非零的数位仍然太多,会导致变量的 溢出,考虑到前面的数位对末尾零的产生无用,因此,对前面 多余的无用位也清除掉。 又n<1000,最多可以有9个因数2 (29=512,210=1024),因此s最大需要保留59=1953125八位 数。 programxunhuan_ex21; varinf,outf: text; n,m,s,i: integer; begin assign(inf,'xunhuan_ex21.in');assign(outf,'xunhuan_ex21.out'); reset(inf);rewrite(outf); read(inf,n); m: =0;s: =1; fori: =2tondo begin s: =s*i; whilesmod10=0do begin inc(m); s: =sdiv10; end; s: =smod10000; end; write(outf,m); close(outf); end. 22、输入一个大于1的整数,打印出它的素因数分解式。 如输入75,则打印: “75=3*5*5” programxunhuan_ex22; varinf,outf: text; n,m,i: integer; s: longint; begin assign(inf,'xunhuan_ex22.in');assign(outf,'xunhuan_ex22.out'); reset(inf);rewrite(outf); read(inf,n); write(outf,n,'='); i: =2; whilenmodi<>0doinc(i); write(outf,i); n: =ndivi; while(nmodi=0)do begin write(outf,'*',i); n: =ndivi; end; whilen<>1do begin inc(i); whilenmodi<>0doinc(i); whilenmodi=0do begin write(outf,'*',i); n: =ndivi; end; end; close(outf); end. 23、对于所有的数字不完全相同的三位数(不够三位数的前面补零也当成是三位 数)。 我们定出如下计算规则: 用这个三位数的三个数字可组成的最大数减去 可组成的最小数,则得到一个新的三位数;对新的三位数还按照上面的规则继 续算下去,最后会发现,我们陷入一个死循环里,或者说是跌入了一个数的黑 洞里。 用具体例子说明。 比如从三位数123开始,计算如下321-123=198; 981-189=792;972-279=693;963-369=594;954-459=495;954-459=495;….从 其他的任何三位数开始,最终也都会停止在495,我们把495叫做三位数的黑 洞。 读入一个三位数,验证掉入黑洞的过程。 programxunhuan_ex23; varinf,outf: text; n,a,b,c,d,n1,n2,m: integer; s: longint; begin assign(inf,'xunhuan_ex23.in');assign(outf,'xunhuan_ex23.out'); reset(inf);rewrite(outf); read(inf,n); whilen<>495do begin a: =nmod10;b: =ndiv10mod10;c: =ndiv100; ifa begin d: =a;a: =b;b: =d; end; ifa begin d: =a;a: =c;c: =d; end; ifb begin d: =b;b: =c;c: =d; end; n1: =a*100+b*10+c; n2: =c*100+b*10+a; n: =n1-n2; writeln(outf,n1,'-',n2,'=',n); end; close(outf); end. 6.3repeat语句(直到型循环) 一、语法: repeat 语句; 语句; 语句; .;循环体 .; .; until布尔表达式; 二、说明: 1、语义: (1)当执行到repeat语句时,不需做任何判断,只是把repeat作为一个标记, 系统继续向下执行循环体中的语句。 (2)当执行到until时,计算布尔表达式的值,如果布尔表达式的值为true, 则跳出循环,执行下一条语句;如果布尔表达式的值为false,就返回到 repeat处。 2、语法特点: 循环体直接包含多条语句,不需要使用复合语句作为循环体,repeat 和until自动起到了begin-end的效果。 3、repeat循环的循环体由于是“先执行、后判断”,所以,它的循环体至少要被执 行一次。 这一点与其它两种循环方式不同,for循环可以由于初值一开始就超过 终值而使循环体一次都不被执行;while循环可以由于一开始布尔表达式的值就 是false而使循环体也一次都不被执行。 4、注意: while循环和repeat循环的区别: (1)while循环是先判断,在决定是否执行循环体,repeat循环是先执行,后 判断。 (2)while循环中布尔表达式的值为false时,退出循环;repeat循环中布尔表 达式的值为true时退出循环。 (3)while循环的循环体有多条语句时,需要用复合语句;repeat循环不需要。 5、三种循环方式一般可以互相转化: 如: fori: =1to10do循环体; 写成while循环形式: i: =1; whilei<=10do begin 循环体; inc(i); end; 写成repeat循环形式: i: =1; repeat 循环体; inc(i); untili>10; 6、三种循环的实现方式各有不同用途,不同场合下,使用不同的循环方式编程的 方便程度和时间复杂度会有所不同,因此,在编写循环结构程序时,应该仔细 想一想,哪种会更方便些。 6.4算法优劣的评估和程序设计基本方法 一、使用循环结构,必须预先估计程序的时间复杂度。 估计方法如下: (1)只执行一次的语句,操作时间忽略不计。 (2)对循环结构中的所有操作,则必须能少则少,能放在循环外面进行的操 作坚决放在外面;对于多次计算的表达式,坚决只计算一次用变量保存 起来。 循环的初值和终值能少就少,O(循环次数),一般忽略循环内部 的语句数。 (3)循环次数不定时,一般取最大可能的循环次数。 (4)对嵌套的循环,则计为O(外层循环次数*内层循环次数)。 因此,减少 循环的嵌套层数,对程序的优化有极大的效果。 (5)时间复杂度的计算,一般只取最高的一项的数量级,例如: 程序段一;O(n) 程序段二;O(n2) 程序段三;O(n3) 程序段四;O(1000n2) 程序段五;O(10000n) 一般计为: O(n3),n<250时能够接受,超过250非常容易超时。 (6)计算出程序的时间复杂度后,再根据题目所给的数据规模(即n的大小), 算出复杂度值,一般O(1千万)左右是可以接受的。 (7)算法的优劣顺序: O(0)用数学方法直接结果直接输出的算法 O (1)用数学方法推出公式,数据带入公式得结果 O(n)一重循环穷举法 O(nlogn)对树形数据结构的维护和搜索 O(n2)二重循环或对图的数据结构的搜索 O(n3)三重循环 二、程序设计的基本步骤: (1)审题,弄懂题目的全部意思。 (2)建立数学模型。 即用什么样的数学方法能解决题目的问题。 (3)选择恰当的数据结构。 包括选择合适的数据类型、数据组织方式。 (4)设计算法。 (5)对所设计的测算时间复杂度 (6)如果时间复杂度在所给数据规模内能够实现(即1秒能完成),编程实现 算法。 (能的满分) (7)如果时间复杂度在所给的数据规模内无法实现,优化算法,尝试减少循 环层数和循环次数。 (8)算法通过优化能达到要求,编程实现。 (能得满分) (9)算法通过优化不能达到要求,如能更换算法,即想出其它更好的算法, 返回(4)重做。 (10)如更换不了算法,在现有算法内尽可能优化后,编程实现。 (能得部分分,估计方法: 10*现有算法能实现的最大n/题目所给的最大n) 6.5程序的跟踪调试方法 程序的跟踪调试: lazarus不仅提供了run的运行方式(即程序一旦开始,就一 直不停执行,直到程序结束),还提供了单步运行的方式(每次只执行一行)。 配合变量查看器,就可以看到程序每步执行时,各个变量的值的变化情况,以 便查找程序中出现的逻辑错误(预估的变量值与程序中的变量值不吻合时,当 前执行的语句有逻辑错误)。 (1)打开变量查看窗口 菜单法: View→Dubugwindows→Watches→打开变量查看窗口 快捷键: Ctrl+Alt+W→打开变量查看窗口 (2)变量查看窗口: 窗口名: Watchlist Expression列: 待查看的变量列表 Value列: 变量的值 (3)添加待查看的变量: 1)在变量查看窗口中右击鼠标,选择Add 2)弹出如下: WatchProperties窗口 3)在Expression中输入待查看变量的变量名,然后点击OK 4)这时,在变量查看窗口的变量列表中出现变量i,值暂时没有, 当程序运行开始时,就可以看到i的值了。 重复以上四步,可以添加更多的查看变量。 (4)单步运行程序: F8运行: 每按一次F8,程序将只执行一行(注意: 如果一行有多条语句, 则多条语句全部执行;如果一条语句分两行写,则需要按两次才能执行完一条语句)。 (5)如果已发现错误,需要先停止程序的运行,然后改正错误。 菜单: run→stop 快捷键: Ctrl→F2 (6)如果前面的程序段已经检查过并且没有错误,可以把光标定位在需要开 始检查的位置,用F4运行程序(一直运行程序,直到光标所在处),然 后再用F8单步运行。 (7)如果需要检查循环体中的某条语句每次执行后的变量值,还可以在相应 语句前面加“断点”,然后用F9运行,每次运行到断点自动暂停。 加断点方法: 在相应语句前面的灰色区域左击鼠标,加入红色标记即可。 如果该断点不再需要,再次点击标记,标记即可清除。 (8)变量查看器不仅能查看变量的值,还可以查看简单表达式的值。 (9)由于Lazarus的bug,导致了有时程序不能正常停止,此时需要强制停止 1)先尝试run→stop,如果能停止运行,主窗口如下: 2)如果没有能停止下来,主窗口如下: 这时,需要使用任务管理器来强行停止: 第一步: 在windows桌面的任务栏中的空白处,右击鼠标,打开任 务管理器,如图: 第二步: 在任务管理器窗口中选择【进程】标签,并找到gdb.exe进 程,选中并结束进程。 如图: 第三步: 再次用run→stop方法,一般就能结束程序的运行了。 一般情况下,解决一道竞赛题的时间应该分配如下: 1、审题、设计算法、评估算法。 (1/3) 2、编写程序代码。 (1/3) 3、调试程序。 (1/3) 一般竞赛四道题时间分配: 20+40+60+60 6.6练习与作业: 一、找出下面程序中错误: 1、判断n是否是素数: fori: =2totrunc(sqrt(n))do ifnmodi=0thent: =false elset: =true; 2、求最大公约数: i: =2; while(amodi<>0)and(bmodi<>0)doinc(i); 二、写出下面程序的运行结果: 1、programProject1; vari,n,a,b: integer; begin i: =11;n: =0; whilen<=5do begin a: =imod10;b: =idiv10; ifimod(a+b)=0then begin writeln(i); inc(n); end; end; end. 2、programProject1; vari,n,a,b,c: integer; begin i: =1; n: =0; whilen<=200do begin a: =imod10; b: =idiv10mod10; c: =idiv10; ifa=1theninc(n); ifb=1theninc(n); ifc=1theninc(n); inc(i); end; write(i); end. 3、programProject1; vari,j,k,sum1,sum2: integer; begin sum1: =0; sum2: =0; k: =1; whilek<=10do begin if(kmod2=0)thenfori: =1to5dosum1: =sum1+i elseforj: =1to5dosum2: =sum2+i; k: =k+1; end; writeln(suml,sum2); end. 4、programProject1; varn: integer; b,t: Real; begin t: =1;b: =1;n: =2; repeat b: =b*n; t: =t+b; n: =n+1; untiln>8; writeln(t: 3: 0); end. 三、根据流程图,编写程序: 1、计算圆周率: 现代圆周率的计算都是使用计算机完成的。 公式如下: pi/4=1-1/3+1/5-1/7+1/9…… 项数越多,所求出的pi就越精确。 根据下面的流程图,完成一个求精确到0.001 的求pi的程序。 2、输入任意两个不大于32767的整数,输出两数相乘的运算竖式。 (第一题图)(第二题图) 四、程序设计: 1、输入10个数,输出最大和最小的数。 输入: 一行10个数,每两个数之间用一个空格隔开。 输出: 两行。 第一行一个数,表示最大的数;第二行一个数,表示最小的数。 2、读一组非零实数,遇零终止,打印其中正、负数的个数及各自的总和。 输入: 一行若干个非零实数,每两个数之间用一个空格隔开,最后一个数是零。 输出: 两行,第一行第一个是整数,表示正数的个数,第二个数是默认格式的 实数,为所有正数的和;第二行第一个是整数,表示负数的个数,第二 个数是实数,表示负数的和。 每两个数之间用一个空格隔开。 3、Faibonacci数列前几项为: 0,1,1,2,3,5,8,…,其规律是从第三项起, 每项均 等于前两项之和。 求小于整数m的所有项。 输入: 一行一个整数m 输出: 每行一个整数,第一行是Faibonacci数列的第一项;第二行是Faibonacci 数列的第二项;…… 4、一木板高m厘米,有个小虫由地面向上爬,每分钟爬上50厘米,每爬1分钟就要休 息1分钟,在这休息时间内下滑30厘米,当小虫爬到顶部还要休息2分钟,再按原
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Lazarus 讲义 循环 结构