第 7讲 综合结构程序设计
请大家及时到我的个人主页 http://cs.cqupt.edu.cn/xiejb
或公共邮箱 http://stu.cqupt.edu.cn中查看作业回复及下载课件自学
因课堂时间有限,不能把所有例题都讲到,请大家 课下一定多看相关例题
2
如何读程序?
写程序:任务(自然语言)?C语言程序
读程序,?
如何读?
先用 大脑 按照程序执行顺序读,给出程序的功能和程序的输出结果
再到计算机上运行该程序,看结果是否与分析结果一样
相当于阅读理解
3
作业答案
例题 4-29:
输入一串字符,以 ESC结束输入,输出这一串字符,并统计该串字符中有多少行
(每回车一次计作一行)。
例题 4-30
输入一串字符,以回车结束输入,除字符串中的 ‘ ESC’外全部输出。
break和 continue的含义
4
多个循环控制变量的三种情况 -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语句是嵌套关系。
外层循环控制变量不变的时候,
内层循环控制变量按顺序自加
5
多个循环控制变量的三种情况 -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次
两个循环控制变量共同自加
6
多个循环控制变量的三种情况 -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次
两个循环控制变量各自分别控制各自的循环语句的执行次数,互不干涉。
7
例 4- 27
for (i=1; i<2; i++)
for (j=1; j<2; j++)
for (j=1; j<2; j++)
printf(" %d,%d,%d\n",i,j,k);
结果为?;;
加个分号会怎样?
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1
2 0 0
2 0 1
2 1 0
2 1 1
再加个分号又会怎样?
2 2 0
2 2 1;
再加个分号呢?
2 2 2
!!加分号与不加分号不同。
8
记住:编程的步骤!!!
分析问题
逐步求精地写算法(请记住 P77页图 4- 2)
写程序 (请严格按照附录 C的语法格式书写 )
调试程序
9
作业讲评
判断 0-100之间有多少个完数。
完数:
所有因子的和等于它本身
例如,1+ 2+ 3= 6
整体思路??
for(i=1;i<=100;i++)
{如果 i是完数,输出,i是完数,,并将计数器加 1
}
输出完数的个数。
10
Y
N
i<=100?
输出 counter
counter=0,i=1
如果 i是完数,输出,i是完数,,
并将计数器加 1
i++
判断 i与 sum是否相等,是的话输出 i,同时 counter加 1;i++
求 i的因子之和 sum
YN
sum=0,j=1
判断 j是否为 i的因子,
是的话累加,j++
j<=i?
分析过程

逐步求精
11
写程序:逐步求精

for(i=1;i<=100;i++)
{
如果 i是完数,输出 i,并将计数器加 1
}
输出完数的个数。
先求 i的所有因子之和 sum。
如果 sum和与 i相等,则 i是完数,输出 i,计数器加 1
for(j=1;j<I:j++)
{判断每一个 j是否为 I的因子,是的话累加求和
}
如果求和的结果与 I相等,则 j是完数,计数器加 1
,sum=0;j<i:j++)
{if(i%j==0)
sum+=j;
}
if(i==sum)
{ 输出 i是完数,计数器加 1
}
12
程序
#include<stdio.h>
void main()
{int i,counter=0,sum;
for(i=1;i<=100;i++)
{ for(j=1,sum=0;j<=i/2;j++) /*循环求 m的因子之和 */
{if(0 == i%j)
sum+=j;
}
if(sum==i) /*判断 m是否为完数 */
{ printf("%d is a wanshu\n",i);
counter++;
}
}
printf("There are %d wanshu(s) between 1 and
100\n",counter);
}
13
记住:编程的步骤!!!
分析问题
逐步求精地写算法(请记住 P77页图 4- 2)
写程序 (请严格按照附录 C的语法格式书写 )
调试程序
14
#include<stdio.h>
int wanshu(int m); /*函数声明 */
int wanshu(int m)/*函数功能:判断 m是否为完数,是返回 1,否则,返回 0*/
{int i,sum=0;
for(i=1;i<=m/2;i++) /*循环判断 i是否为 m的因子 */
{if(m%i==0)
sum+=i;
}
if(sum==m) /*判断 m是否为完数 */
return 1;
else
return 0;
}
void main()
{int i,counter=0;
for(i=1;i<=100;i++)
{if(wanshu(i))
{printf("%d is a wanshu\n",i);
counter++;
}
}
printf("There are %d wanshu(s) between 1 and 100\n",counter);
}
写成多函数程序
15
#include<stdio.h>
void wanshu(int m); /*函数声明 */
void wanshu(int m)/*函数功能:判断 m是否为完数,然后输出 */
{int i,sum=0;
for(i=1;i<=m/2;i++) /*循环判断 i是否为 m的因子 */
{if(m%i==0)
sum+=i;
}
if(sum==m) /*判断 m是否为完数 */
printf("%d is a wanshu\n",i);
else
printf("%d is not a wanshu\n",i);
}
另一种写法
如何在主函数中调用?
void main()
{int i,counter=0;
for(i=1;i<=100;i++)
{wanshu(i);
}
}
如何统计完数的个数?或者如何,记住,
有多少个完数?
printf("There are %d wanshu(s) between 1 and 100\n",counter);
int counter=0;
{ counter++;}
全局变量的,记忆,作用 !
虽然达到此题要求,但 独立性和完整性都被破坏了。不是一个很好的,分段方式,
16
P116例 4- 33
判断 m是否为素(质)数
算法:
输入 m
判断
循环判断每一个比 sqrt(m)小的数是否能整除 m,如果能够整除(找到一个因子),不再继续循环了,说明
m不是素数,
输出判断结果
循环开始 i=2
循环体:判断 m%i==0成不成立,若成立则结束循环,否则继续循环
循环条件,i<=sqrt(m)?有两个循环结束条件,怎样判断是满足哪个条件结束的呢?
17
#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);
}
P116例 4- 33程序
18
例 4-33:方法 2
另外一个思路:
循环条件,i<=sqrt(m)而且 没找到 因子
循环开始,假设 没找到,i=2
循环体:判断 m%i==0成不成立,若成立表示找到,做,找到,标记
输出时:若,找到,,则不是素数,否则,是素数
找到没找到如何表示?
19
#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");
}
例 4-33:方法 2
循环只有一个出口。
设置标志变量是最好的方法
20
思考题,
如何将求素数的功能分离出来,写到独立的函数中去。
如何调用上述函数,判断 2-100之间哪些是素数?
21
#include <math.h>
#include <stdio.h>
int Prime(int m)/*判断 m是否为素数,是返回 1,否返回 0*/
{ int i,find = 0,k = sqrt(m);
for (i=2; i<=k && !find; i++)
{ if (m % i == 0)
find = 1;
}
return find;
}
void main()
{ int m,;
for (m=2; i<=100; m++)
{ if (Prime(m))
printf(“No!%d is not a prime!\n“,m);
else
printf("Yes! %d is a prime!\n“,m);
}
}
22
例:辗转相除法求最大公约数
辗转相除法
算法
输入两个数 a,b
求它们的最大公约数
循环开始:
循环体,c=a%b;a=b,b=c;
循环条件,c!=0
输出
23
程序
#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);
}
将求最大公约数另外写成一个函数呢?
24
#include <stdio.h>
int Gcd(int,int); /*函数声明 */
int Gcd(int a,int b)/*函数功能:求两数的最大公约数 */
{ int c;
do{
c=a%b;
a=b;
b=c;
}while(c!=0);
return a;
}
void main()
{ int a,b,c;
printf("please enter two integers:");
scanf("%d%d",&a,&b);
printf("the greatest common divisor is %d\n",Gcd(a,b));
}
25
例:猜数游戏
先由计算机,想,一个数请人猜,如果人猜对了,则计算机给出提示:
,Right!”,否则提示:,Wrong!”,并告诉人所猜的数是大还是小。
26
库函数 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;
27
#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
只猜一次,要猜多次,直到猜对呢?
哪些要循环呢?
循环条件是什么?
28
#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次机会猜数,怎么解决?
29
#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
30
库函数 srand()
每次运行程序时机器所,想,的数都是一样的,
这是什么原因呢?
函数 rand()产生的只是 伪随机数
随机函数 srand
为函数 rand()设置随机数 种子 来实现对函数 rand所产生的伪随机数的,随机化,
通过键入随机数种子,产生 [0,100]之间 的随机数
scanf("%u",&seed);
srand(seed);
magic = rand() % 100 + 1;
31
#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
32
库函数 time()
如何自动产生种子?
使用计算机读取其时钟值并把该值自动设置为随机数种子,产生 [0,100]之间 的随机数
函数 time()返回以秒计算的当前时间值,
该值被转换为无符号整数并用作随机数发生器的种子
#include <time.h>
srand(time(NULL));
magic = rand() % 100 + 1;
33
#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
34
本讲小结
掌握综合结构的程序设计
能够读懂程序功能,并能分析出其运行结果
下节课讲第五章,请提前预习
35
作业:
读程序练习:例题 4- 36 4- 38(不用交,但下节课抽查)
写程序:一个三位数,如果它的每个数位上的立方和等于这个数,则这个数是一个水仙花数(例如,153= 13+ 53+ 33,找出所有的水仙花数。
自学该讲中未讲过的例题。
提高题(可不做):编写一个程序,模拟小数速算考试。要求:出 50道题,算式中的数据和运算符随机给出,得数要小于 20,学生答完题,判断对错,并给出最终的总分。计算出考试的总时间。