4 循环结构程序设计
请大家及时到我的个人主页
http://cs.cqupt.edu.cn/xiejb下载资料自学
某学生的心得:虽然在编程过程中很繁琐,但还是有顺序可循,我现在算是总结出来了,先写流程图,再写程序,
在调试的过程中要先注意一些细节问题。例如分号是否缺少,break后要加分号,同时判断是否有少或者有多,我现在就是小心的看程序,积累经验和知识。
2
例 1:读程序,蓝色字体的语义?
#include <stdio.h>
void main() /*程序功能:小写字母转换成大写字母 */
{
char lower,upper;
printf(“please input an lowercase:”);
scanf(“%c”,&lower);
getchar();
while( !(lower>='a'&&lower<='z') )
{
printf("the character you input is not a lowercase,please re-input:\n");
lower=getchar();
}
upper=lower-32;
printf(“lower:%c?upper:%c\n",lower,upper);
}
/* 输入数据的合法性检查 */
3
涉及的语法知识
循环结构
While语句的格式
while( P )
{
A
}/*语义:当条件 p满足的时候,执行 A*/
C语言提供了三个处理循环结构的语句:
for
while
do-while
4
例 2
=1+2+… +100
粗略算法:
输入 n
计算过程
输出结果 p
1 0 0
1i
i计算
分析:从 1开始加,每次加 i,加完后 i加 1,共加 100次
即 i=1,sum=0,sum=sum+i,i=i+!,i<=100?
从哪开始?哪些语句循环 100次呢?什么时候结束呢?
循环三要素:
初值
循环体
循环条件
5
算法
6
方法一程序
#include <stdio.h>
main()
{ int i,sum = 0;
for (i=1; i<=100; i++)/*先判断后执行,循环 100次 */
{
sum = sum + i; /*作累加运算 */
}
printf(" 1+… +100= %d\n",sum);
}
循环循环控制变量 i起到控制循环次数的作用。
++(自加 1运算符 )
--(自减 1运算符 )
7
方法二程序
#include <stdio.h>
main()
{ int i = 1,sum=0;
while (i <= 100) /*先判断后执行,循环 n次 */
{ sum = sum+i; /*作累加运算 */
i++; /*累加次数计数器加 1*/
}
printf(" 1+… +100 = %d\n",sum);
}
8
方法三程序
#include <stdio.h>
main()
{
int i = 1,sum=0;
do
{
sum = sum+i; /*作累加运算 */
i++; /*累加次数计数器加 1*/
}while (i <= 100); /*先执行后判断,循环 n次 */
printf("1+… +100 = %d\n",n,p);
}
9
涉及的语法知识
-循环语句 1,while
while (表达式 )
{
循环体语句
} A
F
T
P
10
涉及的语法知识
-循环语句 2,do-while
do
{
循环体语句
}while (表达式 );
A
P
T
11
涉及的语法知识
-循环语句 3,for 语句
for(表达式 1 ; 表达式 2 ; 表达式 3)
{
循环体语句
}
AP
T
循环变量增加步长循环变量赋初值
F
12
循环结构程序设计注意事项
三条语句几乎等价,编程时可用任意一条语句
刚才例题中的重点语句是
i=1; sum=0 (循环开始之前的 初始值 )
sum=sum+i; i++ (循环内容,即 循环体 )
i<=100 (循环条件 )
因此,写循环时上述三点万不可缺。只是对应不同的循环语句,所放的位置不同
13
下边两个程序的区别?
int sum=0;
int i=1;
do
{ sum=sum+i;
i++;
}
while (i<=100);
int sum=0;
int i=1;
do
{ i++;
sum=sum+i;
}
while (i<=100);
定义变量
sum时不赋初值会怎样?
14
例 2又可写成
#include <stdio.h>
main()
{ int i,j,sum = 0;
for(i=1,j=100; i<=50; i++,j--)
{
sum=sum+i+j;
}
printf("1+… +100 = %d\n",sum);
}
两个 循环控制变量 i,j
用逗号分开
逗号运算符
在这加分号会怎样?
加 ;不会出现 error,是因为编译会将 ;这个 空语句 当成循环体,{}里的内容不再循环执行。;
15
课堂练习 1
求 n!
输入 n
计算 n!
输出结果开始开始
fac=fac*n;
i++i<=n
T
i=1,fac=1
F
要学会逐步求精地写算法
16
程序
#include <stdio.h>
void main()
{
int i,n;
double fac;
printf(“please input n:”);
scanf(“%d”,&n);
for(i=1,fac=1;i<=n;i++)
{
fac*=i;
}
printf(“%d!=%lf\n”,n,fac);
}
17
例 3:求 1!+2!+… +n!
算法:
输入
计算
输出
循环开始,i=1;sum=0;
循环条件,i<=n
循环体:计算 i!,然后,sum+=i!
18
例 3程序一
#include <stdio.h>
main()
{int i,n; double term,sum;
printf(“please input n:”);
scanf(“%d”,&n);
for(i=1,sum=0;i<=n;i++)
{ for(j=1,term=1;j<=i;j++)
{term*=j;}
sum=sum+term;
}
/* 求第 i项:从头求起,i!=1*2*… *i */
printf(“sum=%lf\n”,sum);
}
循环嵌套
执行顺序?
19
例 3程序二
#include <stdio.h>
main()
{int i,n; double term,sum;
printf(“please input n:”);
scanf(“%d”,&n);
for(i=1,term=1,sum=0;i<=n;i++)
{ term*=i;
sum=sum+term;
}
/*求第 i项:借助于前项,i!=(i-1)!*i */
printf(“sum=%lf\n”,sum);
}
后项还可以借助前项求,这样提高效率。
这种方法又称为递推法!
20
典型循环题 1
累加求和的关键:寻找累加项的构成 规律
前后项之间 无关
1*2*3 + 3*4*5 +… + 99*100*101
term = i * (i+1) * (i+2); i = 1,3,…,99
前 100项之积
term = n * n / ((n-1) * (n+1)); n = 2,4,… 100
1 - 1/2 + 1/3 - 1/4 + … + 1/99 - 1/100
+ … 直到最后一项的绝对值小于 10-4为止
term = sign / n;
分子 sign = -sign; 初值为 1
分母 n = n + 1; 初值为 1
...7656543432122
21
典型循环题 2
前后项之间 有关
1!+2!+...+n!
term = term * i; i = 1,2,… 10,term初值为 1
a + aa + aaa + aaaa + aaaaa +...,例 a=2,
2 + 22 + 222 + 2222 +...,
term = term * 10 + a; i = 1,2,… n,term初值为 0
term = term / n; term初值为 1.0
n = n + 1,n初值为 1
sin(x) ≈ x - x3/3! + x5/5! - x7/7! + x9/9! -

term = - term * x * x / ((n+1) * (n+2)); term初值为
x
n = n + 2,n初值为 1
!
1.,.
!3
1
!2
1
!1
11
ne
22
小结 1
掌握简单循环结构的程序设计,尤其是累加、累乘的问题。
能够读懂程序功能,并能分析出其运行结果
应掌握 的语法内容
循环结构的三种语句格式和语义
理解循环语句的执行过程
++ --,三种运算符的用法
23
Tips:编程的步骤!!!
分析问题
逐步求精地写算法 (仿照练习 2,至少写出两个层次的算法 )
写程序 (请严格按照附录 C的语法格式书写 )
调试程序
24
作业 1
编程实现:从键盘上输入全班 n个同学的成绩,求平均成绩。
上机观察题:将例 2中的 100改为 10,
上机单步执行,观察程序的执行过程,
以及每个变量的值的变化。
25
作业 1答案 1
#include <stdio.h>
void main( )
{
int i,n;
int sum=0,score;
float average=0.0;
printf("\n n=?");
scanf("%d",&n);
for(i=1;i<=n;i++)
{ printf("\n please input the score of the %d student\n",i);
scanf("%f",&score); /* 输入学生成绩 */
if((score<0.0 || score>100.0))
{--i; continue;} /* 判断成绩的合法性 */
sum += score; /* 求成绩之和 */
}
average = (float)sum/n; /* 求平均成绩,在循环结束后 */
printf("\n average =%f",average);
}
这里没有分号,加了分号,循环体就是空语句,{}里的内容不再循环执行。
26
作业 1答案 2
#include <stdio.h>
void main( )
{
int i,n;
float sum=0,score,average=0.0;
printf("\n n=?");
scanf("%d",&n);
for(i=1;i<=n;i++)
{ do
{ printf("\n please input the score of the %d student\n",i);
scanf("%f",&score); /* 输入学生成绩 */
}while(!(score<0.0 || score>100.0)); /* 判断成绩的合法性 */
sum += score; /* 求成绩之和 */
}
average = sum/n; /* 求平均成绩 */
printf("\n average =%f",average);
}
27
例 4:打印输出九九乘法表
#include <stdio.h>
main()
{ int i,j,m;
for (i=1; i<=9; i++)
printf(“%4d”,m);
printf("\n");
for (i=1; i<=9; i++)
printf(" -");
printf(“\n”); /*以上打印表头 */
for (i=1; i<=9; i++) /*i可表示第一个乘数从 1到 9*/
{
for (j=1; j<=9; j++) /*j可表示第二个乘数从 1到 9*/
{ m=i*j;
printf("%4d",m);
}
printf("\n");
}
}
/*互不相关的循环可以使用相同的循环变量 */
/*相关的循环(例如嵌套)一定不能使用相同的循环变量 */
28
多个循环控制变量的三种情况 -1
for (i=1; i<=9; i++)
for (j=1; j<=9; j++)
printf(" i=%1d j=%1d\n",i,j);
i=1 j=1
j=2
j=3
...
i=1 j=9
i=2 j=1
j=2
j=3
...
i=2 j=9
...
i=9 j=1
j=2
j=3
...
i=9 j=9
输出语句执行了 9* 9= 81次。
两个 for语句是嵌套关系。
外层循环控制变量不变的时候,
内层循环控制变量按顺序自加
内层循环控制变量能用 i
吗?
不能,如果在层循环中改变了 i的值,
它对外层的控制也就不会正常从 1到 9。
29
多个循环控制变量的三种情况 -2
for (i=1,j=1; i<=9; i++,j++)
printf(" i=%1d j=%1d\n",i,j);
i=1 j=1
i=2 j=2
...
i=9 j=9
输出语句执行了 9次
两个循环控制变量共同自加
30
多个循环控制变量的三种情况 -3
for (i=1; i<=9; i++)
printf(" i=%2d\n",i);
for (j=1; j<=9; j++)
printf(" i=%2d j=%2d\n",i,j);
i=1
i=2
i=3
...
i=9
i=10 j=1
i=10 j=2
i=10 j=3
...
i=10 j=9
每个输出语句各执行了 9次,
共 9+ 9= 81次
两个循环控制变量各自分别控制各自的循环语句的执行次数,互不干涉。
下边的循环控制变量能用
i吗?
能,因为这两个循环是先后完成,用 i
不会影响两个循环的循环次数
31
例 5:上机验证
for (i=1; i<=2; i++)
for (j=1; j<=2; j++)
for (k=1; k<=2; k++)
printf(" %d,%d,%d\n",i,j,k);
结果为?;;
加个分号会怎样?
1 1 1
1 1 2
1 2 1
1 2 2
2 1 1
2 1 2
2 2 1
2 2 2
3 2 1
3 1 2
3 2 1
3 2 2
再加个分号又会怎样?
3 3 1
3 3 2;
再加个分号呢?
3 3 3?!!加分号与不加分号不同,循环体发生了变化。
请上机观察各种写法的执行顺序和输出结果。
32
练习 2:读程序功能
#include<stdio.h>
main()
{int i,sum=0;
for(i=1; ; i++)
{if (i>100) break;
sum+=i;
}
printf(“sum=%d”,sum);
}
结束当前所在循环,
转到循环花括号结束后的语句。
有 嵌套的时候要注意 结束的是哪一层的循环。
33
练习 3:读程序功能
#include<stdio.h>
main()
{int i,sum=0;
for(i=1; i<=100; i++)
{if (i%2) continue;
sum+=i;
}
printf(“sum=%d”,sum);
}
结束本次循环中
continue后边的语句,继续下一次循环。
注意转向。
程序功能:求 1-100内偶数的和,也可以写成:
#include<stdio.h>
main()
{int i,sum=0;
for(i=2; i<=100; i=i+2)
sum+=i;
printf(“sum=%d”,sum);
}
34
break和 continue
注意二者在 语义上 的区别
另外一个转向语句 goto,不建议使用,
请大家自学!
35
例 6 百钱买鸡问题


)(C hi c k s /H e n sC oc k s
)(C hi c k sH e n sC oc k s
210 03*3*5
110 0
公元五世纪末,我国古代数学家张丘建在,算经,中提出了如下问题:鸡翁一值钱五,鸡母一值钱三,鸡雏三值钱一。凡百钱买百鸡,问鸡翁、母、雏各几何?
#include <stdio.h>
main()
{ int Cocks,Hens,Chicks;
printf(“Cocks \t Hens \t Chicks\n");
for (Cocks =0; Cocks <=20; Cocks ++)
for (Hens =0; Hens <=33; Hens ++)
{ Chicks = 100 – Cocks - Hens;
if (5* Cocks +3* Hens + Chicks /3.0 == 100)
printf(“\n%d\t%d\t%d\n",Cocks,Hens,Chicks);
}
}
运行结果
Cocks Hens Chicks
0 25 75
4 18 78
8 11 81
12 4 84
36
小结 2:多重循环结构程序设计
一般情况下:
如果循环次数已知,用 for
如果循环次数未知,用 while
如果循环体至少要执行一次,用 do-while
!!!关键
单重循环:归纳出每次循环要做的共同工作 (规律 ),即是循环体。
循环嵌套,(例:九九乘法表) 根据关系分析清楚哪是外层,哪是内层,一层一层写算法,
一层一层写程序
37
小结 2
掌握多重循环 (循环嵌套 )的程序设计方法,先逐层 (由外层到内层 )写算法,再逐层地 (由外到内 )写循环语句,注意多层的循环控制变量不能用相同的。
掌握 break和 continue的用法和区别
灵活应用循环语句。
38
作业 2
编程实现:输出 0-100的平方根表 (输出保留两位小数 )。
上机观察题:上机观察练习 3中程序的执行过程,将 continue改为 break以后再观察一下。
39
两个常用算法
穷举法:
按顺序列举出所有可能的解,然后依次验证这些是不是真正的解。例如:百钱买百鸡问题。
迭代法 (递推法 )
迭代就是用不断变量的新值替代其旧值。例如,一笔存款每年自动转存,就形成利滚利的情况,本金每年不同,不断迭代。递推是由一个变量的值推出另外的变量的值。它们没有本质的不同,例如新的存款就是由旧的存款推算出来的。
一般可以得到迭代公式,其中指明了新值 an+1与旧值 an的关系,或一个变量 a与另外一个变量 b的关系。
例如,i!=(i-1)!*i;就表明了这两种关系。
40
例 7
判断 m是否为素(质)数
算法:
输入 m
判断
循环判断每一个比 sqrt(m)小的数是否能整除 m,如果能够整除(找到一个因子),不再继续循环了,说明
m不是素数,
输出判断结果
循环开始 i=2
循环体:判断 m%i==0成不成立,若成立则结束循环,否则继续循环
循环条件,i<=sqrt(m)?有两个循环结束条件,怎样判断是满足哪个条件结束的呢?
41
#include <stdio.h>
#include <math.h>
void main()
{ int m,i,k;
do
{ printf("Input a positive integer m>2,");
scanf("%d",&m);
}while(m<=2); /* 保证输入大于 2的整数 */
k=sqrt(m);
for(i=2;i<=k;i++)
{
if(m % i ==0)
break; /* 能被一个数整除时退出 */
}
if(i>=k+1)
printf("%d is a prime.\n",m); /* 无整除数就是素数 */
else
printf("%d is not a prime.\n",m);
}
例 7程序
42
例 7:方法 2
另外一个思路:
循环条件,i<=sqrt(m)而且 没找到 因子
循环开始,假设 没找到,i=2
循环体:判断 m%i==0成不成立,若成立表示找到,做,找到,标记
输出时:若,找到,,则不是素数,否则,是素数
找到没找到如何表示?
43
#include <math.h>
void main()
{ int m,i,k,find = 0; /*标志变量 find置为 1*/
printf("Please enter a number (>=2),");
scanf("%d",&m);
k = sqrt(m);
for (i=2; i<=k && !find; i++)
{ if (m % i == 0)
find = 1;
}
if (find)
printf("No!\n");
else
printf("Yes!\n");
}
例 7:方法 2
循环只有一个出口。
设置标志变量是最好的方法
44
也可以写成:
#include <math.h>
#include <stdio.h>
void main()
{ int m,i,k;
printf("Please enter a number:");
scanf("%d",&m);
k = sqrt(m);
for (i=2; i<=k; i++)
{ if (m%i == 0)
{ printf("No!\n");
goto end; /*另外一个程序转向语句,goto,end是语句标号 */
}
}
printf("Yes!\n");
end,; /*将该行语句 (空语句 )标记为 end,end是语句标号的名字 */
}
45
其它典型习题:应用穷举法
1,搬砖问题,36块砖,36人搬,男搬 4、女搬 3,两个小儿抬一砖,要求一次全搬完,问男、女、小儿须若干?
2,五家共井问题:我国古代数学巨著,九章算数,卷第八 ·第十三题为,五家共井,甲二绠(汲水用的井绳)
不足,如(接上)乙一绠;乙三绠不足,如丙一绠;
丙四绠不足,如丁一绠;丁五绠不足,如戊一绠;戊六绠不足,如甲一绠。如各得所不足一绠,皆逮
( dia,及)。问井深,绠长各几何。答曰:井深七丈二尺一寸,甲绠长二丈六尺五寸,乙绠长一丈九尺一寸,丙绠长一丈四尺八寸,丁绠长一丈三尺九寸,戊绠长七尺六寸。,这是世界上最古老的不定方程问题。
请用程序求解。
46
其它典型习题:应用穷举法
3,父子俩的年龄:父亲今年 30岁,儿子今年 6岁,问多少年后父亲的年龄始儿子年龄的 2倍。
4,换硬币:把一元人民币换成 5分,2分,1分的硬币,有多少种换法?
5,要登上 n阶楼梯,每一步允许跨 1阶或 2阶。共有多少种登楼梯方法?
6,打印出 500之内所有能被 7或 9整除的数。
7,一根 29cm长的尺子,只允许在它上面刻 7个刻度。若要用它能良出 1~ 29cm的各种整长度,刻度应如何选择?
8,一个 4位数,当它的逆向排列时得到的 4位数是它自身的倍数。请用 C语言程序,找出这一条件的 4位数来。
9,某人的年龄的 3次方是四位数,4次方是六位数,并且这两个数中没有重复的数字。请用 C语言程序,求出该人的年龄
47
例 8,计算 Fibonacci数列的第 n项
Fibonacci是中世纪意大利的一位极有才华的数学家 。 他的代表作是 1202年出版的,算盘的书,。 在这本书中,Fibonacci提出一个问题:
假定一对新出生的兔子一个月后成熟,并且再过一个月开始生出一对小兔子 。 按此规律,在没有兔子死亡的情形下,一对初生的兔子,到一年头上,可以繁殖成多少对兔子?
显然,各月的兔子数组成数列:
1,1,2,3,5,8,13,21,34,55,89,…
Fthis = Flast + Fbeforelast
48
程序
#include <stdio.h>
void main()
{ int i,Fthis=1,Flast=1,Fbeforelast;
for(i=3;i<=12;i++)
{
Fthis=Flast+Fbeforelast;
Fbeforelast=Flast;
Flast=Fthis;/*为下次计算做准备 !两个语句的顺序能颠倒吗?请上机验证,并观察结果 */
}
printf("The number of rabbit,%d\n",Fthis);
}
49
例 9:求两数的最大公约数
辗转相除法
算法
输入两个数 a,b
求它们的最大公约数
循环开始:
循环体,c=a%b;a=b,b=c;
循环条件,c!=0
输出
50
例 9程序
#include <stdio.h>
void main()
{ int a,b,c;
printf("Please enter two integers:");
scanf("%d%d",&a,&b);
do{
c=a%b;
a=b;
b=c;
}while(c!=0);
printf("The greatest common divisor is %d\n",a);
}
51
例 10 二分法求方程的根
二分法:根据已知条件将对解的搜索范围缩小到原来的二分之一。
迭代法:根据迭代公式 (步骤 )依次求近似解,直至满足要求为止。
52
(a)f(h)与 f(a)同号时; (b)f(h)与 f(a)异号时
Y
X
a h
b
f( a )
f( b )
f( h )
0
Y
X
a
h b
f( a )
f( b )
f( h )
0
( a ) ( b )
53
其它迭代法习题
1,牛的繁殖问题,有位科学家曾出了这样一道数学题:有一头母牛,它每年年初要生一头小母牛;每头小母牛从第四个年头起,每年年初也要生一头小母牛。按此规律,若无牛死亡,
第 20年头上共有多少头母牛?
2,把下列数列延长到第 50项,
1,2,5,10,21,42,85,170,341,682,
3,一个球从 100米高度自由落下后,反弹回原来高度的一半。按此规律,到第 10次落地时,
行程共有多少米?然后将反弹起多高?
54
4,编写一个 C程序,利用如下的格里高利公式求
π的值。直到最后一项的值小于 10-5为止。
5,编写一个 C程序,计算 y的值,n由键盘输入。
6,编写一个 C程序,把下列数列延长到第 50项:
1,2,5,10,21,42,85,170,341,
682,…
7,切饼问题。一张大饼放在板上,如果不许将饼移动,问切 n刀时,最多可以切成几块。
55
例 11:猜数游戏
先由计算机,想,一个数请人猜,如果人猜对了,则计算机给出提示:
,Right!”,否则提示:,Wrong!”,并告诉人所猜的数是大还是小。
56
库函数 rand()
怎样模拟计算机“想”一个数呢?
随机函数 rand()
#include <stdlib.h>
产生 [0,RAND_MAX] 之间的随机数
RAND_MAX在 stdlib.h中定义,TC中是 32767
magic = rand();
产生 [0,b-1] 之间的随机数
magic = rand()%b;
产生 [a,a+b-1] 之间的随机数
magic = rand()%b + a;
57
#include <stdlib.h>
#include <stdio.h>
main()
{ int magic; /*计算机 "想 "的数 */
int guess; /*人猜的数 */
magic = rand()%100 + 1; /*“想,一个 [1,100]之间的数 magic*/
printf("Please guess a magic number:");
scanf("%d",&guess); /*猜数 */
if (guess > magic) /*判断 */
{
printf("Wrong! Too high!\n");
}
else if (guess < magic)
{
printf("Wrong! Too low!\n");
}
else
{
printf("Right! \n");
printf("The number is:%d \n",magic);
}
}
猜数游戏 -1
只猜一次,要猜多次,直到猜对呢?
哪些要循环呢?
循环条件是什么?
58
#include <stdlib.h>
#include <stdio.h>
main()
{ int magic,guess,counter = 0 ; /*记录人猜次数 */
int magic = rand() % 100 + 1;
do{
printf("Please guess a magic number:");
scanf("%d",&guess); /*猜数 */
counter ++; /*计数器变量 count加 1*/
if (guess > magic) /*判断 */
printf("Wrong! Too high!\n");
else if (guess < magic)
printf("Wrong! Too low!\n");
else
printf("Right! \n");
} while (guess != magic);
printf(" you guess %d times!\n",counter);
}
猜数游戏 -2
?用 while行不行?
?最多给他 10次机会猜数,怎么解决?
59
#include <stdlib.h>
#include <stdio.h>
main( )
{ int magic,guess,counter = 0;
magic = rand() % 100 + 1;
do{
printf("Please guess a magic number:");
scanf("%d",&guess); /*猜数 */
counter ++; /*计数器变量 count加 1*/
if (guess > magic) /*判断 */
printf("Wrong! Too high!\n");
else if (guess < magic)
printf("Wrong! Too low!\n");
else
printf("Right!\n");
}while (guess != magic && counter<10);
if (counter==10) /*10次仍没猜对,提示最终结果 */
printf(" the integer is %d,you guess 10 times! But you are
fail!\n",magic );
else
printf("congratulations! you just guess %d times!\n",
magic,counter);
}
猜数游戏 -3
60
库函数 srand()
每次运行程序时机器所,想,的数都是一样的,
这是什么原因呢?
函数 rand()产生的只是 伪随机数
随机函数 srand
为函数 rand()设置随机数 种子 来实现对函数 rand所产生的伪随机数的,随机化,
通过键入随机数种子,产生 [0,100]之间 的随机数
scanf("%u",&seed);
srand(seed);
magic = rand() % 100 + 1;
61
#include <stdlib.h>
#include <stdio.h>
main()
{ int magic,guess,counter = 0;
printf(“please input a seed:”);
scanf(“%u”,&seed); /*输入种子 */
srand(seed); /*设置种子 */
magic = rand() % 100 + 1; /*产生随机数 */
do{ printf("Please guess a magic number:");
scanf("%d",&guess); /*猜数 */
counter ++; /*计数器变量 count加 1*/
if (guess > magic) /*判断 */
printf("Wrong! Too high!\n");
else if (guess < magic)
printf("Wrong! Too low!\n");
else
printf("Right!\n");
}while (guess != magic && counter<10);
if (counter==10) /*10次仍没猜对,提示最终结果 */
printf(" the integer is %d,you guess 10 times! But you are
fail!\n",magic );
else
printf("congratulations! you just guess %d times!\n",
magic,counter);
}
猜数游戏 -4
62
库函数 time()
如何自动产生种子?
使用计算机读取其时钟值并把该值自动设置为随机数种子,产生 [0,100]之间 的随机数
函数 time()返回以秒计算的当前时间值,
该值被转换为无符号整数并用作随机数发生器的种子
#include <time.h>
srand(time(NULL));
magic = rand() % 100 + 1;
63
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
main()
{ int magic,guess,counter = 0;
srand(time(NULL)); /*根据系统当前时刻设置种子 */
magic = rand() % 100 + 1;
do{ printf("Please guess a magic number:");
scanf("%d",&guess); /*猜数 */
counter ++; /*计数器变量 count加 1*/
if (guess > magic) /*判断 */
printf("Wrong! Too high!\n");
else if (guess < magic)
printf("Wrong! Too low!\n");
else
printf("Right!\n");
}while (guess != magic && counter<10);
if (counter==10) /*10次仍没猜对,提示最终结果 */
printf(" the integer is %d,you guess 10 times! But you are
fail!\n",magic );
else
printf("congratulations! you just guess %d times!\n",
magic,counter);
}
猜数游戏 -5
64
小结 3
理解穷举法和迭代法
掌握综合结构的程序设计
能够读懂程序功能,并能分析出其运行结果
65
作业 3:
编程:一个三位数,如果它的每个数位上的立方和等于这个数,则这个数是一个水仙花数(例如,153= 13+ 53+ 33,找出所有的水仙花数。
编程:一个球从 100米高度自由落下后,反弹回原来高度的一半。按此规律,到第 10
次落地时,行程共有多少米?然后将反弹起多高?
66
选做题
编程模拟小学学生的速算考试。要求
随机给出 50道题,每题 2分。算式中的数据和运算符随机给出,数据必须是 0-100之间的整数,运算符只能是 +,-,*,/,得数必须是 0-100之间的整数
学生答完题,判断对错。
计算出总成绩和考试使用的总时间。
提示:
要用到 srand(),rand(),time()函数
循环体:出题、修正试题以满足条件、得到正确答案,请学生答题,批改,成绩累加
67
选做题提示
算法:
1,计算开始时间 (用 time()函数 )
2,循环:
1,出题并给出答案 (用 srand()函数设置种子,用 rand()
得到一个算式,如果算式不符合要求要修改算式 ),
并计算出题目的正确答案。
2,学生答题 (由用户输入 )
3,批改并计入总分
3,计算结束时间 (用 time()函数 )
4,输出总分和总时间
注:所用到的库函数的用法请参考 例 11
68
总结
能够读懂程序功能,并能分析出其运行结果
灵活编写循环结构和综合结构的程序。
理解和掌握两个常用算法,递推法和列举法
应掌握 的语法内容
For,while,do-while语句的用法和语义,理解语句的执行顺序和过程
break和 continue的用法和区别
++ --,三种运算符的运算规则
69
补充:程序测试 —边值分析法
所谓边界条件,是指输入等价类和输出等价类边缘上的数据。运用边值分析法并不那么容易,应特别注意它与等价分类的差别:
70
程序测试 ——边值分析法
(1) 边值分析不是从等价类中随便选一个例子作为代表,而是着眼于使该等价类的边界情况成为测试的主要目标来选择例子。
(a)如果某个输入条件说明了值的范围,则可选择一些恰好取得边界值的例子,另外再给出一些恰好越过边界值属于无效等价类的例子。
(b)如果一个输入条件指出了输入数据的个数,则可取最小个数、最大个数、比最小个数少 1、比最大个数多 1,来分别设计测试用例。
如例 2.3中,要求输入边数 n=3,则可取 3,2,4作为测试用例。
(c)若输入是有序集(如按成绩排出的名次),则应把注意力放在第一和最后一个元素上。
71
程序测试 ——边值分析法
(2) 边值分析不仅要注意输入条件,还要注意输出情况,按输出等价类设计测试用例。
(a)对每个输出条件,如果指出了输出值的范围或输出数据的个数,
则应按与设计输入等价类的方法,为它们设计测试用例。
(b)若输出是个有序集,则应把测试注意力放在第一和最后一个元素上。
72
循环结构的边值分析法测试
循环结构可以看作是一种特殊的判定结构。一般说来,仅考虑循环结构的设定是否正确,可以采用边值分析法。下面以计数循环结构( for循环结构)为例进行讨论。
( 1)初始边值条件
( 2)终止边值条件
( 3)特殊循环次数
1,单计数循环结构的边值分析法测试
73
循环结构的边值分析法测试嵌套循环可以看作循环的组合。但为了减少测试用例的组合数,可以用以下策略:
· 除指定层的循环要遍历单循环的全部情况外,其它各层取典型循环次数,
再把各层分别作为指定层,重复上述过程;
· 对全部各层循环同时取最小循环次数;
· 对全部循环同时取最大循环次数;
· 取指定层的循环,遍历单循环的全部情况,其它各层循环均取最大循环次数;再把各层分别作为指定层,重复上述过程。
2,嵌套循环的边值分析法测试
74