第 4 章 循环结构
4.1 教学要点
本章通过典型程序解析,介绍循环结构程序设计的基本思想和实现方法,以及典型算法,
使学生理解 C 语言所提供的三种循环语句即 for、while 和 do-while 语句的执行机制,并能 综合运用编写循环结构类的程序。
4.1 节通过引例“用格里高利公式求
π
的近似值”和示例“统计学生成绩”,针对没有显性给出循环次数的情况(分别对比例2-8 和例 3-3),介绍如何确定循环条件,并引入 while 语句。教师在讲授时,应重点说明根据具体问题,确定循环条件和循环体的基本思路,并针
对3 种常见的循环控制方式(计数控制、计算值控制和输入值控制),选择合适的循环语句
实现。还要介绍while 语句的执行流程和使用方法,通过与 for 语句的比较,加深对循环语
句的理解,使学生能使用for/while 语句进行循环程序设计。
4.2 节通过案例“统计一个整数的位数”,详细介绍 do-while 语句的执行流程以及使用
方法,教师在讲授时,应详细介绍 do-while 语句的执行流程、循环条件以及循环体,并通
过与for、while 语句的比较,加深理解 do-while 语句,使学生不仅能使用 do-while 语句进行 循环程序的设计,并且能合理选择循环语句。
4.3 节通过案例“判断素数”,详细介绍循环结构中 break 和 continue 语句的功能以及执 行流程,教师在讲授时,应详细介绍判断素数的算法以及break 和 continue 语句的执行流程,
使学生能在循环结构中正确使用break 和 continue 语句。
4.4 节通过案例“求 1!+2!+3!+…+100!”,详细介绍嵌套循环的程序设计方法,教师在讲 授时,应详细嵌套循环的执行流程(过程),使学生能正确使用嵌套循环进行程序设计。
4.5 节综合介绍循环结构的程序设计,涉及到多个典型的算法,教师在讲授时,重点应 放在问题的分析、算法分析以及选择合理的循环语句上。使学生充分理解程序设计的思想与 方法。
讲授学时:4 学时,实验学时同讲授学时。
本章的知识能力结构图见图4.1。
图 4.1 知识能力结构图 循环结构的
概念
循环体
循环条件
循环语句选择
while 语句
循环语句
do-while 语句
break 语句 continue 语句
典型算法 (循环嵌套)
典型问题的 算法框架
能正确分析实际问题
能根据实际情况合理使用
能根据实际情况熟练编写程序 for 语句
4.2 讲稿
1 本章分 4 节。
2 提出本章的学习要点。
3 借助引例提出要解决的问题,并比较与例
2-8 的异同,简要分析,提供思路,聚焦在 如何确定循环条件。
可运行例4-1 程序,让学生感受场景。
本节介绍为解决这个问题所编写的程序和 涉及到的语言知识。
4 对比分析例2-8 源程序,共同点在于循环体
不变,差异在于本例并没有显性给出循环 次数,但给出了循环的结束条件。通过具 体分析示例的处理流程,提出问题:
(1)循环条件是什么?
(2)如何确保循环的初始条件为真?使循
环能正常启动?
(3)程序如何实现?
提醒:学习就是在已有的基础上(循环体 不变),从已知到未知(循环条件变化),
不断探索深化的过程,要扎实走好每一步。
4.1 π while
4.2 do-while
4.3 break continue
4.4 1! + 2! + … + 100!
4.5
!
!
!
while do-while
!
while do-while
!
break
!
4.1 π
4-1 π
10
44.1.1 4.1.2 while
π 4=1−1
3+1 5−1
7+…
4-1 π
10
44.1.1 π
π 4=1−1
3+1 5−1
7+…
2-8 1-1/3+1/5-… n
flag = 1;
denominator = 1;
sum = 0 ;
for (i = 1; i <= n; i++) { item = flag * 1.0 / denominator;
sum = sum + item ; flag = -flag;
denominator = denominator + 2;
}
|item| < 0.0001
|item| >= 0.0001 fabs(item) >= 0.0001 while (fabs(item) >= 0.0001)
item = 1;
5 展示、运行例4-1 程序,并解读程序:
(1)程序运行过程:当 item 的值尚未足够 小的时候,计算 item,并累加至 pi,周而 复始,直到循环条件为假,即|item|已足够 小,不再满足其值>=0.0001。
提醒:循环结束时,最后一次累加至 pi 的
item 之值恰好小于 0.0001,满足题目要求。
(2)简要介绍 while 语句的执行流程。
(3)说明变量初值、循环条件、循环体、
循环体语句先后顺序等之间的逻辑关系。
设问,以加深对循环条件的理解:
(1)若 item 初值为 0,运行结果?
(2)若循环条件由>=改成<,运行结果?
解答:循环初始条件为假,一次也不执行。
6 从例4-1 分析得知,累加求π的循环次数事
先不确定,需要在循环累加的过程中反复
测试 item 值来决定是否继续循环,即“当
条件成立时要做循环”,从而引出 while 语 句。
说明:
(1)while 语句的一般形式;
(2)while 语句的执行流程,强调先判断 条件;
(3)while 语句与 for 语句流程的比较。
7 继续对比while 语句与 for 语句,重点说明
两者可互换。应针对具体问题,选择合适 的循环语句实现。
8 继续讨论while 语句与 for 语句,举例说明
两者可互换,建议让学生练习。
强调 while 语句的循环体内必须有能改变
循环条件的语句(如i++),以避免死循环。
# include <math.h>
int main (void)
{ int denominator, flag;
double item, pi;
flag = 1; denominator = 1; item = 1.0; pi = 0;
while (fabs (item) >= 0.0001) { item = flag * 1.0 / denominator;
pi = pi + item;
flag = -flag;
denominator = denominator + 2;
} pi = pi * 4;
printf ("pi = %f\n", pi);
return 0;
}
4-1 π
pi = 3.141613 item = 0.0 ?
fabs (item) < 0.0001?
4.1.2 while
while (
while
while for
while
1
while (
2) {for 3
}
for (
1 2 3for
while
while for
sum = 0;
for (i = 1; i <= 10; i++){
sum = sum + i;
} sum = 0;
i = 1; /* */
while (i <= 10){ /*
*/sum = sum + i;
i++; /*
*/}
9 例4-2 介绍如何根据输入值确定循环条件。
可通过运行例 4-2 程序,让学生感受场景
(程序运行停不下来,无法结束)。
对比分析例3-3 源程序,共同点在于循环体
基本不变,差异在于,本例同样没有显性
给出循环次数(与例 4-1 相似),问题也同
样聚焦在如何确定循环条件。
10 通过用一个特殊的值作为正常输入数据的
结束标志,解决系列输入数据何时结束的 问题,这也是解决此类问题的常用方法。
即给出循环的结束条件,进而确定循环条 件。
再次提醒:
如果题目描述的是循环的结束条件,必须
将其转换为循环条件。这是 C 语言中循环
语句的语法要求。
11 具体分析示例的处理流程,在例3-3 源程序
上修改,边修改边运行,渐进式提出问题:
(1)循环条件是什么?已解决
(2)如何确保循环的初始条件为真?使循
环能正常启动?正常运转?
如果参照例4-1,while 前 grade 赋值 1(>=0 皆可),循环正常启动,但伪数据也累加至 total。原因在于输入的数据先参加运算,再 判断其值是否满足循环条件。例如:
输入 90 50 -2,total 值:138(90+50-2)
输入 -1,total 值:-1
解答:将 while 循环体的输入语句移到最
后,并在while 前输入第 1 个数。
(3)如何求平均值?增加变量 num 计数
12 展示、运行程序,分析程序结构。
设问:
(1)为什么 while 循环前要先输入第一个 数据?
(2)循环体中语句的先后顺序可以任意调
整吗?
(3)循环结束后,为什么要用 if 语句判断?
3-3 n n
total = 0;
count = 0;
for (i = 1; i <= n; i++){
scanf ("%lf", &grade);
total = total + grade;
if (grade < 60){
count++;}
}
-
!
"
"
grade < 0 grade >= 0
-
total = 0;
count = 0;
for (i = 1; i <= n; i++){
scanf ("%lf", &grade);
total = total + grade;
if (grade < 60){
count++;}
}
total = 0;
count = 0;
while (grade >= 0) {
total = total + grade;
if (grade < 60){
count++; } }
scanf ("%lf", &grade);
scanf ("%lf", &grade);
num = 0;
num ++;
scanf ("%lf", &grade);
4-2 -
include <stdio.h>
int main (void)
{ int count, num; double grade, total;
num = 0; total = 0; count=0;
printf ("Enter grades: \n");
scanf ("%lf", &grade); /*
while (grade >= 0) { /*
total = total + grade;
num++;
if (grade < 60){
count++; } scanf ("%lf", &grade);
} if(num != 0) {
printf("Grade average is %.2f\n", total/num);
printf("Number of failures is %d\n", count);
} else{
printf("Grade average is 0\n");}
return 0;
}
Enter grades: 67 88 73 54 82 -1 Grade average is 72.80 Number of failures is 1
13 小结 3 种常见的循环控制方式,即计数控 制、计算值控制和输入值控制。
循环程序设计:
(1)具体问题具体分析;
(2)确定循环体、循环条件;
(3)选择合适的循环语句。
14 借助引例提出要解决的问题,简要分析,
提供思路,即统计整数的位数,需要一位 位地数,这是循环问题,应聚焦于实现的 算法。
可运行例4-3 程序,让学生感受场景。
本节介绍为解决这个问题所编写的程序和 涉及到的语言知识。
15 以495 为例,一位一位地数,共重复 3 次:
(1)数出 1 个数;
(2)划掉数好的这个数;
(3)如果没有数完,继续(1)和(2)。
16 从示例495 的数数过程,依次归纳出:
循环结束条件;(循环的次数与输入数据相
关,事先无法确定)
循环条件;
循环体;
最终得到统计位数的算法。
设问:
输入0,输出结果?
解答:
输出0,应输出 1。故引入 do-while。
-
!
2.4
sum = 0;
for (i = 1; i <= n; i++){
sum = sum + i;
}
!
4-1
item = 1.0;
while (fabs (item) >= 0.0001) {
item = flag * 1.0 / denominator;
} ……
!
4-2
scanf ("%lf", &grade);
while (grade >= 0) {
……
scanf ("%lf", &grade);}
4.2
4-3
4.2.1
4.2.2 do - while
4-3
495!
1 5 495%10
! 49 495
5 49 495 / 10 = 49
!
2 9 49%10
! 4 495
9 4 49 / 10 = 4
!
3 4 4%10
! 0 495
4 0 4 / 10 = 0
! 3 3
4.2.1 -
-
495 % 10 = 5 495 / 10 = 49 49 % 10 = 9 49 / 10 = 4
4 % 10 = 4 4 / 10 = 0 digit = numbr % 10 number = number / 10
number = 0
!
number = 0
!
number != 0
!
"
digit = number %10
"
number = number / 10
"
count ++
number = 0?
count = 0;
do{
digit = number % 10 number = number / 10;
count ++;
} while (number != 0);
count = 0;
while (number != 0){
digit = number %10 number = number / 10;
count ++;
}
17 展示、运行例4-3 程序,并解读程序:
(1)程序运行过程:从右向左,每划去一
个数字(number= number/10),计数器 count 增1,直到所有数字全部被划去 number==0, 此时count 的值就是该整数的位数。
(2)简要介绍 do-while 语句的执行流程。
(3)对负数的处理:-99 与 99 的位数是一 样的,故将负数改为正数(number=-number)
设问,本例如何用while 语句实现?以加深 对do-while/while 的理解。
解答:对0 单独处理。
18 从例 4-3 分析得知,先划去一个数字并计
数,再判断是否所有数字全部被划去了。
即“先执行循环体,再判断条件,当条件 成 立 时 继 续 执 行 循 环 体 ”, 从 而 引 出 do-while 语句。
说明:
(1)do-while 语句的一般形式;
(2)do-while 语句的执行流程,强调先循 环后判断条件。
19 对比do-while 语句与 while 语句,说明:
(1)执行流程的不同;
(2)结合例 4-3,分析循环体的执行次数:
当循环的初始条件为假时,do-while 执行 1 次,while 执行 0 次;
(3)两者可互换。
应针对具体问题,选择合适的循环语句实 现。
20 借助引例提出要解决的问题,简要分析,
提供思路,即如果只能被 1 和自身整除,
则为素数;否则不是素数,这就需要在取 值范围内检测能否整除,这是循环问题,
应聚焦于实现的算法。
可运行例4-4 程序,让学生感受场景。
本节介绍为解决这个问题所编写的程序和 涉及到的语言知识。
int main (void) { int count, number;
printf ("Enter a number: ");
scanf ("%d", &number) ; if (number < 0){
number = -number;
} count = 0;
do {
number = number / 10;
count ++;
} while (number != 0);
printf ("It contains %d digits.\n", count);
return 0;
}
4-3
Enter a number: 12534 It contains 5 digits.
Enter a number: -99 It contains 2 digits.
Enter a number: 0 It contains 1 digits.
count = 0;
while (number != 0) { number = number / 10;
count ++;
}
if (number == 0){
count = 1;}
4.2.2 do - while
do { } while (
do-while
!
while:
!
do-while
while do-while
do-while while
4.3
4-4 m
1
1 2
4.3.1
4.3.2 break continue
21 算法解析:
设i 的取值范围为[2~m-1],则:
(1)若 m 是素数,则该范围内的每一个数
都必须被测试且满足m%i!=0,即循环测试
每一个数,直到所有的数都被测试且不能 整除;
(2)一旦遇到能被该范围内的某一个数整
除,即m%i==0,则该数一定不是素数,此
时其余的数不必再继续检测,应中止循环,
此时使用break 语句提前中止循环。
If 语句用于区分循环是正常结束(所有的数
都被测试且不能整除),故m 是素数;还是
遇到能整除的数,用break 提前中止循环,
故m 不是素数。
22 展示、运行例4-4 程序,并解读程序:
(1)循环条件:i <= m/2 且 m%i != 0
(2)循环结束条件:i > m/2 或者 m%i == 0 i > m/2:说明 for 循环正常结束;
m%i==0:说明 break 强行终止了循环
(3)for 循环结束后必须判断是怎么结束
的,即是正常结束还是强行终止,以此来 判断是否是素数。
23 介绍break 语句的执行流程。重点说明:
(1)如何理解共同表示循环条件?
exp 为真 且 expb 为假;
(2)如何理解循环结束条件?
exp 为假 或 expb 为真;
(3)如何区分循环的结束条件?
用if 语句。
特别提醒:
while 表达式 exp:表示循环条件 if 表达式 expb:表示循环结束条件
24 常见错误解析,建议学生练习。
4.3.1
1 m i [2, m-1]
!
m
i m%i m
!
i m%i m
m %2 %3 %4 %5 %(m-1)
|| 0 0
&& 0 0
m m/2
i [2 m-1] [2 m/2] [2 m ]
for (i = 2; i <= m/2; i++) if (m % i == 0) break;
if (i > m/2) printf ("yes\n") else printf ("no\n");
int main (void) { int i, m;
printf ("Enter a number: ");
scanf ("%d", &m);
for (i = 2; i <= m/2; i++){
if (m % i == 0){
break; } }
if (i > m/2 && m != 1){ /* 1 */
printf ("%d is a prime number! \n", m); } else{
printf ("No!\n"); } }
4-4 1-
Enter a number: 9No!
Enter a number: 11 11 is a prime number!
?
?
Enter a number: 1 No!
Enter a number: 2 2 is a prime number!
4.3.2 break
while ( exp ){
1 if ( expb ){
break;
} 2 }
exp
1
expb 2 for (i = 2; i <= m/2; i++){
if (m % i == 0) { break; } }
if (i > m/2 ) { printf ("Yes!"); } else { printf ("No!\n"); }
•
•
exp expb
-
for (i = 2; i <= m/2; i++) { if (m % i == 0){
printf ("No!\n");}
else{
printf ("Yes! \n");}
}
for (i = 2; i <= m/2; i++){
if (m % i == 0) { break;}
}
if (i > m/2 ) {printf ("Yes!");}
else { printf ("No!\n"); }
for (i = 2; i <= m/2; i++){if (m%i == 0){
printf ("No!\n");
break;
} }
printf ("Yes!");
Enter a number: 9 No!
Enter a number: 9 No!
Yes!
Enter a number: 9 Yes!
No!
Yes!
25 介绍continue 语句的执行流程。
提醒:
当expb 为真时,跳过 continue 后面的语句,
即提前结束本次循环,重新开始下一次循 环。
26 举例说明break 与 continue 语句的不同,建
议单步运行程序。
27 举例说明 continue 语句的功能,建议单步
运行程序。
设问:
如果将continue 语句换成 break 语句,程序 的运行结果是什么?
解答:没有输出。
28 改写例3-1 的猜数游戏,增加没猜中可反复
猜数的功能,最多猜7 次。解读程序:
(1)定义变量 flag 表示猜数状态,1 表示
猜中;0 表示尚未猜中,不做结论。即:
flag=1:yournumber == mynuber,终止循环 flag=0:yournumber != mynuber,继续循环
(2)将 flag 的初值置 0。考虑到猜中则终 止循环,没猜中则继续循环,flag 初值应选 择能使循环继续的值0。
(3)循环条件:count<=7 且 flag==0;
(4)循环结束条件:count>7 或者 flag==1。
count>7:此时 flag==0,说明始终没猜中,
for 循环正常结束,结束后显示信息;
flag==1:猜中,显示信息,break 终止循环。
continue
while (exp){
1 if (expb) { continue;
} 2 }
exp
expb
continue
break continue
include <stdio.h>
int main (void) { char c;
int i;
for (i = 0; i < 10; i++) { c = getchar ();
if (c == '\n') break;
putchar (c);
} }
abc efgh 123 abc
abcefgh1 continue;
break continue
100~200 3
for (i = 100; i <= 200; i++) { if ( i % 3 != 0 ) continue;
printf ("%d ", i);
}
for (i = 100; i <= 200; i++) if (i % 3 == 0) printf ("%d ", i);
4-5-1
# include <stdio.h>
int main (void)
{ int count = 0, flag, mynumber, yournumber;
mynumber = 38; /* /
flag = 0; /* flag: 0 1 /
for (count = 1; count <= 7; count++) {
printf ("Enter your number: "); scanf ("%d", &yournumber);
if (yournumber == mynumber) { printf ("Lucky You!\n");
flag = 1;
break; /* / }
else
if (yournumber > mynumber ) printf ("Too big\n");
else printf ("Too small\n");
}
if (flag == 0) printf ("Game Over!\n");
return 0;
}
29 例4-4 求素数的另一种实现,使用 flag 表示 判断素数的状态。解读程序:
(1)变量 flag 表示判断素数的状态,0 表
示不是素数;1 表示尚未遇到能整除该数的
数,假设其为素数,不做结论。即:
flag=0:m%i == 0,终止循环 flag=1:m%i != 0,继续循环
(2)将 flag 的初值置 1。考虑到不是素数 则终止循环,否则继续循环,flag 初值应选
择能使循环继续的值1,即假设其为素数。
(3)循环条件:i <= m/2 且 flag==1。
(4)循环结束条件:i > m/2 或者 flag==0。
i>m/2:此时 flag==1,说明始终没遇到能整 除该数的数,for 循环正常结束,m 是素数;
flag==0:遇到能整除该数的数,m 不是素 数,break 强行终止了循环。
30 继续讨论猜数游戏。
介绍由计算机随机产生一个 1~100 之间的
被猜数的方法。
本节小结:
(1)算法:判断素数,猜数
(2)变量 flag 的引入,表示循环继续与否 的状态,如是否猜中、是否为素数的状态;
(3)多出口循环的设计方法:
共同表示循环条件:循环语句+break 区分循环的结束条件:if
31 引导学生分析题目:这是一个累加求和的
问题。
先给出解决此类问题的一般框架结构,从 而给出两种不同的编程方法:函数、循环 嵌套。
32 展示、运行例4-6 程序,用定义和调用 fact()
函数方法实现。
解读程序,特别说明累加求和循环体内内 的第 i 项数据由 fact()函数计算,其中 for 变量i 即作为 for 循环的控制变量又同时参
与循环体内的计算,即作为 fact 函数的参
数。
考 虑 : 是 否 可 以 不 调 用 函 数 的 方 法 实 现 呢?
int main (void) { int i, m;
printf ("Enter a number: ");
scanf ("%d", &m);
for (i = 2; i <= m/2; i++){
if (m % i == 0) { break;
} }
if (i > m/2 && m != 1) { printf ("Yes\n"); } else{
printf ("No\n"); } }
4-4 2-
int main (void){ int i, flag = 1, m;
printf ("Enter a number: ");
scanf ("%d", &m);
if (m == 1) flag = 0;
for (i = 2; i <= m/2; i++) { if (m % i == 0){
flag = 0;
break;
} }
if (flag == 1){
printf ("Yes\n"); } else{
printf ("No\n"); } }
4-5-2
# include <stdlib.h>
# include <time.h>
int main (void)
{ int count = 0, flag = 0, mynumber, yournumber;
srand (time(0));
mynumber = rand () % 100 + 1; /* 1~100 /
while (count < 7){
printf ("Enter your number: "); scanf ("%d", &yournumber);
count++;
if (yournumber == mynumber) { printf ("Lucky You!\n"); flag = 1; break;
} else
if (yournumber > mynumber ) printf ("Too big\n");
else printf ("Too small\n");
}
if (flag == 0) printf ("Game Over!\n");
return 0;
}
4.4 1 2 100
sum = 0;
for (i = 1; i <= 100; i++){
item = i !
sum = sum + item;
}
4.4.1
fact(i) i 4.4.2
i
include <stdio.h>
double fact (int n);
int main (void) { int i;
double sum;
sum = 0;
for ( i = 1; i <= 100; i++ ){
sum = sum + fact (i);
}
printf ("1! + 2! + 3! + … + 100! = %e\n", sum);
return 0;
}double fact (int n)
{ int i;
double result = 1;
for ( i = 1; i <= n; i++){
result = result * i ; }
return result ; }
4.4.1
1! + 2! + …. + 100!
1! + 2! + … + 100! = 9.426900e+157
33 前一种方法是用函数来计算第i 项的值,然
后进行累加,另一方面我们已经知道求 i
的阶乘也可用for 循环实现,故提出了循环
的嵌套。
34 展示、运行例4-7 程序,用嵌套循环方法实
现。
解读程序,特别说明累加求和循环体内内 的第 i 项数据 item 由内部循环计算,即内 循环专门计算i 的阶乘值。
35 重点说明一下几点:
循环的控制变量不同;
内、外层循环的变量初始值不同,特别时 内层循环的初始化语句所放的位置,放置 地方不同将对程序功能产生极大的影响;2 个程序段的区别;
36 分析嵌套循环的执行过程。
分析计算下列各语句的执行次数:
item=1; //100 次
item=item*j; //1+2+3+…+100 次 sum=sum+item; //100 次
4.4.2
sum = 0;
for ( i = 1; i <= 100; i++ ){
item = i !
sum = sum + item;
} sum = 0;
for ( i = 1; i <= 100; i++ ) {
item = 1;for (j = 1; j <= i; j++){
item = item * j;
}
sum = sum + item;
}
include <stdio.h>
int main(void) { int i, j;
double item, sum; /* item sum = 0;
for ( i = 1; i <= 100; i++ ) { item = 1; /*
for ( j = 1; j <= i; j++ ){ /* item = i! */
item = item * j;
}
sum = sum + item;
printf ("1! + 2! + 3! + … + 100! = %e\n", sum);
4-7
-
sum = 0;
for ( i = 1; i <= 100; i++ ) {
item = 1;
for (j = 1; j <= i; j++){
item = item * j;
}
sum = sum + item;
}
1! 2! 100!
item = 1;sum = 0;
for( i = 1; i <= 100; i++ ){
for (j = 1; j <= i; j++){
item = item * j;
}
sum = sum + item;
}
1! 1! 2! 1! 2! 100!
sum = 0;
for(i = 1; i <= 100; i++) { item = 1;
for (j = 1; j <= i; j++) item = item * j;
sum = sum + item;
}
i
j
i j
37 以ppt 中程序段为例,深入说明二重循环的 执行过程,必要时可单步执行。
说明对于每一个i 值,内层循环控制变量都
必须从 1 开始执行,并分析循环体的执行
次数。
38 本节介绍循环结构程序设计思想、方法及
算法。
实现要点:
哪些操作需反复执行?即循环体;
什么情况下重复执行?即循环条件;
有哪些常见的循环控制方式?
适合使用什么循环语句?
用什么方法实现?即算法;
39 小结常见的循环控制方式及对应的例题
40 至此已介绍三种不同的循环语句,即for、
while、do-while,说明一般情况下三种循环 语句的选择方法,但需强调这不是规则,
通常意义下三种循环语句可通用。
i = 1 j = 1 1 1 1
j = 1 2 1 2
i = 2
j = 2 2 2 3
j = 1 100 1 4951
j = 2 100 2 4952
i = 100
j = 100 100 100 5050
for (i = 1; i <= 100; i++)
for (j = 1; j <= i; j++) printf ("%d %d\n", i, j );
-
4.5
!
"
"
!
"
"
+ ……
!
for while do-while
! 2.4 , 4-6, 4-7, 4-11, 4-12
sum = 0;
for (i = 1; i <= n; i++){
sum = sum + fact (i);
}
! 4-1, 4-3, 4-9
item = 1.0;
while (fabs (item) >= 0.0001) { item = flag * 1.0 / denominator;
} ……
! 4-2, 4-8
scanf ("%lf", &grade);
while (grade >= 0) { ……scanf ("%lf", &grade);
}
! + 4-4, 4-5, 4-10
!
"
for
"
while do-while
if
for
else /*
if (
while
else /*
do-while
41 例4-8 重点要解决的是:在若干个数据中求 最大(小)值的问题。分数据个数已定、
数据个数不定两种情形。
ppt 首先给出的是数据个数确定的情形,故 可采取用for 循环实现。
需重点说明求最大值max 的方法,变量 max 的作用是始终存放当前的最大值。
类推到求最小值。
42 本ppt 给出的是数据个数不确定的情形,用
输入一个特殊值作为结束标志,故可采取 用while 循环实现。
循环前先读入一个数据,作为当前的最大 值 max 的初值,并作为 while 循环判断的 依据,一旦输入一个负数,循环结束。
引导学生考虑前 2 个程序是否有缺限?可
运行测试。
43 介绍第3 种方法,用 do-while 循环实现。
运行程序,并进行解读。
考虑:当输入数据时第一个就输入-1,程序
运行结果是什么?为什么?
44 例4-9 重点要解决的是:对一个数据进行逐
位分拆的问题。也可分为逆序和正序分拆 两种情形。
本例已逆向分拆为例。
需说明:
逆向分拆的方法;
循环条件是什么? 循环体是什么?
程 序 结 构 怎 么 搭 ? 用 while 循 环 还 是 do-while 循环?有和区别?
include <stdio.h>
int main(void) { int i, mark, max, n;
printf ("Enter n: "); scanf ("%d", &n);
printf ("Enter %d marks: ", n);
scanf ("%d", &mark); /*
max = mark; /*
for (i = 1; i < n; i++ ){
scanf ("%d", &mark);
if (max < mark) max = mark;
}
printf ("Max = %d\n", max);
return 0;
}
4-8 for)
mark max max mark Enter n: 5
Enter 5 maks:67 88 73 54 82 Max = 88
Enter n: 0
include <stdio.h>
int main (void) { int mark, max;
printf (“Enter marks:");
scanf ("%d", &mark); /*
max = mark; /*
while (mark >= 0){
if (max < mark) max = mark ; scanf ("%d", &mark );
}
printf ("Max = %d\n", max);
return 0;
}
4 8 while)
Enter marks:67 88 73 54 82 -1 Max = 88
Enter marks:-1
include <stdio.h>
int main (void) { int mark, max;
max = -1; /* max printf ( "Enter marks: " );
do {
scanf ( "%d", &mark );
if ( max < mark ) max = mark;
} while ( mark >= 0 );
printf ( "Max = %d\n ", max);
}
4 8 do-while)
Enter marks: 67 88 73 54 82 -1 Max = 88
Enter marks: -1
4 9
) 12345 5 4 3 2 1
12345 % 10 =5 12345 / 10 = 1234 1234 % 10 = 4 1234 / 10 = 123
123 % 10 = 3 123 / 10 = 12 12 % 10 = 2 12 / 10 = 1
1 % 10 = 1 1 / 10 = 0 x%10 x=x/10 x==0
scanf ( "%d", &x );
while ( x != 0 ){
digit = x %10;
x = x/10 ;
printf ( "%d ", digit );
}
do-while
45 例 4-10 需要解决的是:用嵌套循环方式找 出某个范围内的所有素数以及如何实现每 行几个的问题。
先实现找出所有的素数,不考虑分组输出,
可逐步细化介绍此程序段。
46 展示、运行程序,说明一下几个问题:
内外层循环的变量初始值;
外层循环的循环体是什么?
内层循环的循环体是什么?
变量count 的作用是什么?
如何实现每行输出10 个?
注意:每行输出几个是初学者容易出错的 地方。
47 例 4-11 用斐波那契数列为例,说明数列问
题如何推算?
引导学生分析问题,归纳出需要重复执行 的是什么?重复执行的条件是什么?怎么 搭程序框架?
这是经典的算法例子。
48 例 4-12 以搬转头为例,说明穷举法的算法
方法。
引导学生分析问题,男人、女人和小孩的
人数取值范围均在 0~45 之间,只要能满
足总人数为 45 人且所搬的砖为 45 块就是 一种搬法,显然要对男人、女人和小孩三 个人数的各种可能一一测试,来找出满足 条件的人员组合,可采用三重循环。
这也是经典的算法例子。
4 10 100
for (m = 2; m <= 100; m++) if (m printf( "%d", m);
n = sqrt(m);
for (i = 2; i <= n; i++) if (m % i == 0) break;
if(i > n) printf ("yes\n") else printf ("no\n”);
for (m = 2; m <= 100; m++){
n = sqrt(m);
for (i = 2; i <= n; i++) if (m % i == 0) break;
if (i > n) printf ("%d", m) }
include <stdio.h>
10
#include <math.h>
int main(void) { int count, i, m, n;
count = 0;
for (m = 2; m <= 100; m++){
n = sqrt(m);
for (i = 2; i <= n; i++) if (m % i == 0) break;
if (i > n){ /* m printf ("%6d", m);
count++; /* 10 / if (count %10 == 0) printf (“\n”);
} } }
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
4-11 Fibonacci 1,1,2,3,5,8,13,…
1 1 2 3 5 8 13, ……
x1 x2 x x1 x2 x
x1 x2 = 1;
x = x1 + x2;
x1 = x2;
x2 x;
x1 = 1;
x2 = 1;
printf ( "%6d%6d", x1, x2 ); /*
for ( i = 1; i <= 8; i++ ){ /* 8 x = x1 + x2; /*
printf( "%6d", x );
x1 = x2; /* x1 x2 */
x2 = x;
}
4-12
for ( men = 0; men <= 45; men++ ) for ( women = 0; women <= 45; women++ ) for ( child = 0; child <= 45; child++ )
if ((men+women+child==45) && (men*3+women*2+child*0.5==45)) printf("men=%d women=%d child=%d\n", men, women, child);
}
49 引导学生考虑:上述三重循环的循环体(if 语句)共执行了多少次?是否可减少循环 次数?
说明如何把三重循环改成二重循环?并比 较循环体的执行次数,分析减少的方法。
50 归纳总结本章的各个重要知识点。
4.3 练习与习题参考答案
4.3.1 练习参考答案
练习4-1 在例 4-1 程序中,如果对 item 赋初值 0,运行结果是什么?为什么?如果将精度改 为10–3,运行结果有变化吗?为什么?
解答:
如果对item 赋初值 0,则程序运行结果是 pi=0,因为 item 为 0 时不满足 while 循环的 执行条件,即不执行循环,故pi 值为 0。如果将精度改为 10-3,运行结果会有变化,因为精 度改变意味着while 循环的条件改变,精度变大使得 while 循环次数减少,必然影响到 pi 的 值。
练习4-2 运行例 4-2 程序时,如果将最后一个输入数据改为-2,运行结果有变化吗?如果第 一个输入数据是 -1,运行结果是什么?为什么?
解答:
如果将最后一个输入数据改为-2,运行结果没有变化,因为最后一个负数是一结束标志,
不进行统计,故任意一个负数都可以。如果第一个输入数据是-1,运行结果是:Grade average is 0,因为第一个输入就是-1,则 while 循环条件不成立,不执行循环体。
练习 4-3 序列求和(1-1/4+1/7-1/10+1/13-1/16+……):输入一个正实数 eps,计算序 列1-1/4+1/7-1/10+1/13-1/16+……的值, 直到最后一项的绝对值不大于给定精度 eps
4-12
for (men = 0; men <= 15; men++)
for (women = 0; women <= 22; women++){
child = 45 – women – men;
if (men * 3 + women * 2 + child * 0.5 == 45)
printf("men=%d women=%d child=%d\n", men, women, child);
}
for (men = 0; men <= 45; men++) for (women = 0; women <= 45; women++) for (child = 0; child <= 45; child++)
if ((men+women+child==45) && (men*3+women*2+child*0.5==45)) printf("men=%d women=%d child=%d\n", men, women, child);
}
!
"
while do-while for
!
break continue
!
!
!
"
π
fibonacci
"
/
ddd
• while do-while
• break continue
•
•
•
(保留 6 位小数)。试编写相应程序。
提醒:教材上此题对最后一项取值的描述为“精确到最后一项的绝对值小于 eps”。下次印 刷时将修改一致。
解答:
# include <stdio.h>
# include <math.h>
int main (void) {
int flag;
double denominator, eps, item, sum;
flag = 1; denominator = 1 ; item = 1.0; sum = 0;
scanf("%lf", &eps);
while (fabs (item) > eps) { sum = sum + item;
flag = -flag;
denominator = denominator + 3;
item = flag * 1.0 / denominator;
}
sum = sum + item;
printf ("sum = %.6f\n", sum);
return 0;
}
练习4-4 如果将例 4-3 程序中的 do-while 语句改为下列 while 语句,会影响程序的功能吗?
为什么?再增加一条什么语句,就可以实现同样的功能?
while (number != 0){
number = number / 10;
count ++;
} 解答:
会有影响,因为当输入数据number 为 0 时,上述 while 循环将不执行,count 值仍为 0,
故输出为0,不符合题目要求。可增加一条 if 语句来解决上面的问题,在 while 循环前加上 语句“if ( number == 0) count = 1; ”。
练习4-5 例 4-4 程序中的第 9~15 行可以用下列 for 语句替代吗?为什么?
for (i = 2; i <= m/2; i++)
if (m%i == 0) printf ("No!\n");
else printf ("%d is prime number!\n", m);
解答:
不能代替,因为只用一个数来除不足以判断该数是否是素数。
练习4-6 猜数字游戏:先输入 2 个不超过 100 的正整数,分别是被猜数 mynumber 和猜测的
最大次数n,再输入你所猜的数 yournumber,与被猜数 mynumber 进行比较,若相等,显示
猜中;若不等,显示与被猜数的大小关系,最多允许猜 n 次。如果 1 次就猜出该数,提示
“Bingo!”;如果 3 次以内猜到该数,则提示“Lucky You!”;如果超过 3 次但不超过 n 次猜 到该数,则提示“Good Guess!”;如果超过 n 次都没有猜到,则提示“Game Over”。如果在
到达 n 次之前,用户输入了一个负数,也输出“Game Over”,并结束程序。试编写相应程
序。
解答:
源程序1
# include <stdio.h>
int main (void) {
int count = 0, flag = 0, mynumber, n, yournumber;
scanf ("%d%d", &mynumber, &n);
if (n > 100 || mynumber > 100) printf ("Invalid number!\n");
else{
while (count < n) {
scanf ("%d", &yournumber);
count ++;
if (yournumber < 0) { break;
}
if (yournumber == mynumber) { flag = 1;
break;
}else if (yournumber > mynumber ) { printf ("Too big\n");
}else {
printf ("Too small\n");
} }
if (flag == 0) {
printf ("Game Over\n");
}else if (count == 1) { printf ("Bingo!\n");
}else if (count <= 3) { printf ("Lucky You!\n");
}else {
printf ("Good Guess!\n");
} } return 0;
}
源程序2
# include <stdio.h>
int main (void) {
int count = 0, flag = 0, mynumber, n, yournumber;
scanf ("%d%d", &mynumber, &n);
if (n > 100 || mynumber > 100) printf ("Invalid number!\n");
else{
scanf ("%d", &yournumber);
while (yournumber >= 0) { count ++;
if (count > n) { break;
}
if (yournumber == mynumber) { flag = 1;
break;
}
else if (yournumber > mynumber ){
printf ("Too big\n");
} else{
printf ("Too small\n");
}
scanf ("%d", &yournumber);
}
if (flag == 0) {
printf ("Game Over\n");
}else if (count == 1) { printf ("Bingo!\n");
}else if (count <= 3) { printf ("Lucky You!\n");
}else {
printf ("Good Guess!\n");
} } return 0;
}
练习4-7 求 e 的值:输入 1 个正整数 n,计算下式求出 e 的值(保留 8 位小数),要求使用 嵌套循环。
! 1
! 3 1
! 2 1
! 1 1 1
e = + + + + + n
解答:
# include <stdio.h>
int main(void) {
int i, j, n;
double e, product;
scanf("%d", &n);
e = 1;
for (i = 1; i <= n ; i++){
product = 1;
for (j = 1; j <= i; j++) product = product * j;
e = e + 1.0 / product;
}
printf ("%.8f\n", e);
return 0;
}
练习4-8 运行例 4-8 的源程序 1 时,如果先输入 0,即输入数据个数 n = 0,表示不再输入任
何成绩,运行结果是什么?如何修改程序以应对这种情况?
解答:
当输入数据个数n=0 时,由于在 for 循环外首先得输入一个成绩,故程序仍将等待输
入第一个人的成绩,这与输入个数n=0 矛盾,可修改如下:
# include <stdio.h>
int main (void) {
int i, mark, max, n;
printf ("Enter n: ");
scanf ("%d", &n);
if (n > 0) {
printf ("Enter %d marks: ", n);
scanf ("%d", &mark); /* 读入第一个成绩 */
max = mark; /* 假设第一个成绩是最高分 */
for (i = 1; i < n; i++ ){
scanf ("%d", &mark);
if (max < mark)
max = mark;
}
printf ("Max = %d\n", max);
}
return 0;
}
练习4-9 运行例 4-8 的源程序 2 时,如果输入的第一个数就是负数,表示不再输入任何成绩,
运行结果是什么?如何修改程序以应对这种情况?
解答:
当输入的第一个数就是负数时,将不执行while 循环,程序运行结果就是输出所输入的
负数。修改思路同上题。
练习4-10 找出最小值:输入一个正整数 n, 再输入 n 个整数,找出其中的最小值。试编写相 应程序。
解答:
# include <stdio.h>
int main (void) {
int i, min, n, x;
scanf ("%d", &n);
scanf ("%d", &x);
min = x;
for (i = 1; i < n; i++){
scanf ("%d", &x);
if (min > x) min = x;
}
printf ("min = %d\n", min);
return 0;
}
练习4-11 统计素数并求和:输入 2 个正整数 m 和 n(1<=m<=n<=500),统计并输出 m 和 n
之间素数的个数以及这些素数的和。素数就是只能被 1 和自身整除的正整数,1 不是素数,
2 是素数。试编写相应程序。
解答:
# include <stdio.h>
# include <math.h>
int main (void) {
int count = 0, flag, i, j, k, m, n, sum = 0;
scanf ("%d%d", &m, &n);
if (m >= 1 && n <= 500 && m <= n){
for (k = m; k <= n; k++){
if (k == 1) { flag = 0;
}else { flag = 1;
}
j = sqrt (k);
for (i = 2; i <= j; i++){
if (k % i == 0){
flag = 0;
break;
} }
if (flag == 1){
count++;
sum = sum + k;
} }
}
printf("%d %d\n", count, sum);
return 0;
}
4.3.2 习题参考答案
一.选择题
1 2 3 4 5 6 7 8 A C D A B B C A
二.填空题 1.13 2.**
3.t*10 4.12
5.(1) k=6,m=2 (2) k=6,m=9 (3) k=3,m=6 6.62ufd!
三.程序设计题
1.求奇数和。输入一批正整数(以零或负数为结束标志),求其中的奇数和。试编写相应
程序。
解答:
# include <stdio.h>
int main (void) {
int sum, x;
sum = 0;
scanf ("%d", &x);
while (x > 0){
if (x % 2 != 0){
sum = sum + x;
}
scanf ("%d", &x);
}
printf ("%d\n", sum);
return 0;
}
2.展开式求和。输入一个实数 x,计算并输出下式的值,直到最后一项的绝对值小于 0.00001
(保留 4 位小数)。要求定义和调用函数 fact(n)计算 n 的阶乘,可以调用 pow()函数求幂。
试编写相应程序。
s =1+ x + x
22! + x
33! + x
44! + ...
提醒:教材上此题的计算公式见下式,且计算结果要求保留2 位小数。下次印刷时将修改 一致。
s = x + x
22! + x
33! + x
44! + ...
解答:
# include <stdio.h>
# include <math.h>
int main (void) {
int i;
double item, s, x;
double fact (int n);
scanf("%le", &x);
s = 1;
item = x;
i = 1;
while (fabs (item) >= 0.00001) {
item = pow (x, i) / fact(i);
s = s+ item;
i++;
}
printf ("%.4f\n", s);
return 0;
}
double fact (int n) {
int i;
double result = 1;
for(i = 1; i <= n; i++){
result = result * i;
}
return result;
}
3.求序列前 n 项和(2/1+3/2+5/3+8/5+...)。输入一个正整数 n,输出 2/1+3/2+5/3+8/5 +…
的前n 项之和,保留 2 位小数。该序列从第 2 项起,每一项的分子是前一项分子与分母的
和,分母是前一项的分子。试编写相应程序。
解答:
# include <stdio.h>
int main (void) {
int i, n;
double denominator, numerator, sum, temp;
scanf ("%d", &n);
numerator = 2;
denominator = 1;
sum = 0;
for (i = 1; i <= n; i++){
sum = sum + numerator / denominator;
temp = numerator;
numerator = numerator + denominator;
denominator = temp;
}
printf ("%.2f\n", sum);
return 0;
}
4.求序列前 n 项和(a+aa+aaa+aa…a)。输入两个正整数 a 和 n,求 a+aa+aaa+aa…a(n 个a)之和。例如,输入 2 和 3,输出 246(2 + 22 + 222)。试编写相应程序。
解答:
# include <stdio.h>
int main (void) {
int a, i, n, sn, tn;
scanf("%d%d", &a, &n);
tn = 0;
sn = 0;
for (i = 1; i <= n; i++){
tn = tn * 10 + a;
sn = sn + tn;
}
printf ("s = %d\n", sn);
return 0;
}
5.换硬币。将一笔零钱(大于 8 分,小于 1 元, 精确到分)换成 5 分、2 分和 1 分的硬币,
每种硬币至少有一枚。输入金额,问有几种换法?针对每一种换法,输出各种面额硬币的数 量和硬币的总数量。试编写相应程序。
解答:
# include <stdio.h>
int main(void) {
int count, fen1, fen2, fen5, x;
scanf("%d", &x);
count = 0;
for (fen5 = (x -3) / 5; fen5 > 0; fen5--){
for (fen2 = (x - fen5 * 5 - 1) / 2; fen2 > 0; fen2--){
fen1 = x - 5 * fen5 - 2 * fen2;
if (fen1 > 0){
count++;
printf("fen5:%d, fen2:%d, fen1:%d, total:%d\n",fen5,fen2,fen1,fen1+fen2+fen5);
} } }
printf("count = %d\n", count);
return 0;
}
6.输出水仙花数。输入一个正整数 n(3<=n<=7),输出所有的 n 位水仙花数。水仙花数
是指一个n 位正整数,它的各位数字的 n 次幂之和等于它本身。例如 153 的各位数字的立
方和是13+53+33=153。试编写相应程序。
提示:定义函数ipow(x, n)计算 x 的 n 次幂,返回值为整型。
解答:
# include <stdio.h>
int ipow (int x, int n) {
int i, p = 1;
for (i = 1; i <= n; i++) { p = p * x;
}
return p;
}
int main (void) {
int a, b, digit, i, n, number, s;
scanf ("%d", &n);
a = ipow (10, n-1);
b = a*10;
for (i = a; i < b; i++) { s = 0;
number = i;
while (number != 0){
digit = number % 10;
number = number / 10;
s = s + ipow (digit, n);
}
if (i == s){
printf ("%d\n", s);
} }
return 0;
}
7.求最大公约数和最小公倍数。输入两个正整数 m 和 n(m<=1000,n<=1000),求其最 大公约数和最小公倍数。试编写相应程序。
解答:
# include <stdio.h>
int main (void) {
int j, k, m, n; /* j 表示最小公倍数,k 表示最大公约数 */
scanf ("%d%d", &m, &n);
j = m;
while (j % n != 0){
j = j + m;
}
k = (m * n) / j;
printf ("%d %d\n", k, j);
return 0;
}
8.高空坠球。皮球从 height(米)高度自由落下,触地后反弹到原高度的一半,再落下,
再反弹,……,如此反复。问皮球在第 n 次落地时,在空中一共经过多少距离?第 n 次
反弹的高度是多少?输出保留1 位小数。试编写相应程序。
解答:
# include <stdio.h>
int main (void) {
double h, distance;
int height, i, n;
scanf ("%d%d", &height, &n);
if (height == 0 || n == 0) { printf ("0.0 0.0\n");
} else {
distance = height;
h = 0.5 * height;
for (i = 1; i < n; i++) {
distance = distance + 2 * h;
h = 0.5 * h;
}
printf ("%.1f %.1f\n", distance, h);
} return 0;
}
9.打印菱形“星号*”图案。输入一个正整数 n(n 为奇数),打印一个高度为 n 的"*"菱
形图案。例如,当n 为 7 时,打印出以下图案。试编写相应程序。
* * * *
* * * * *
* * * * * * *
* * * * * * * *
* 解答:
源程序1
# include <stdio.h>
int main (void) {
int i, j, n;
scanf ("%d", &n);
for (i = 1; i <= n/2 + 1; i++){
for (j = 2 *(n/2 + 1 - i); j > 0; j--){
printf (" ");
}
for (j = 1; j <= 2 * i - 1; j++){
printf ("* ");
}
printf ("\n");
}
for (i = 1; i <= n/2; i++){
for (j = 1; j <= 2 * i; j++){
printf (" ");
}
for (j = 1; j <= 2 * (n/2 + 1 - i) - 1; j++){
printf ("* ");
}
printf ("\n");
}
return 0;
}
源程序2
# include <stdio.h>
int main (void)
{
int i, j, n;
scanf ("%d", &n);
for (i = 1; i <= n/2 + 1; i++){
for (j = 2 *(n/2 + 1 - i); j > 0; j--){
printf (" ");
}
for (j = 1; j <= 2 * i - 1; j++){
printf ("* ");
}
printf ("\n");
}
for (i = n/2; i >= 1; i--){
for (j = 2 *(n/2 + 1 - i); j > 0; j--){
printf (" ");
}
for (j = 1; j <= 2 * i - 1; j++){
printf ("* ");
}
printf ("\n");
}
return 0;
}
10.猴子吃桃问题。一只猴子第一天摘下若干个桃子,当即吃了一半,还不过瘾,又多 吃了一个;第二天早上又将剩下的桃子吃掉一半,又多吃了一个。以后每天早上都吃了前一
天剩下的一半加一个。到第 n 天早上想再吃时,见只剩下一个桃子了。问:第一天共摘了
多少个桃子?试编写相应程序。(提示:采取逆向思维的方法,从后往前推断。)
解答1:假设第 1 天摘的桃子个数是偶数,PTA 上的题目以此为前提。
# include <stdio.h>
int main (void) {
int i, n, peach;
scanf ("%d", &n);
peach = 1;
for (i = 1; i < n; i++){
peach = 2 * (peach + 1);
}
printf ("%d\n", peach);
return 0;
}
解答2:假设第 1 天摘的桃子个数是奇数。
# include <stdio.h>
int main (void) {
int i, n, peach;
scanf ("%d", &n);
peach = 1;
for (i = 1; i < n; i++){
peach = 2 * peach + 1;
}
printf ("%d\n", peach);
return 0;
}
11.兔子繁衍问题。一对兔子,从出生后第 3 个月起每个月都生一对兔子。小兔子长到 第 3 个月后每个月又生一对兔子。假如兔子都不死,请问第 1 个月出生的一对兔子,至少需 要繁衍到第几个月时兔子总数才可以达到 n 对?输入一个不超过 10000 的正整数 n,输出兔 子总数达到 n 最少需要的月数。试编写相应程序。
解答:分析:
月month
1 2 3 4 5
1 月龄兔子对数 n1 1 0 1 1 2
2 月龄兔子对数 n2 0 1 0 1 1
>=3 月龄兔子对数 n3
0 0 1 1 2
兔子总数n 1 1 2 3 5
源程序:
# include <stdio.h>
int main (void) {
int n, n1, n2, n3, month;
scanf("%d", &n);
month = 1;
n1 = 1;
n2 = n3 = 0;
while ((n1+n2+n3) < n) { month ++;
n3 = n3 + n2;
n2 = n1;
n1 = n3;
}
printf ("%d\n", month);
return 0;
}
4.4 实验指导教材参考答案
4.4.1 基本循环语句的使用
一 、 调 试 示 例
最大公约数和最小公倍数:输入两个正整数 m 和 n,输出它们的最大公约数和最小公倍 数。
解答:参见习题程序设计第7 题。
二 、 基 础 编 程 题
(1)求奇数和:读入一批正整数(以零或负数为结束标志),求其中的奇数和。请使用 while
语句实现循环。
解答:参见习题程序设计第1 题。
(2)求最小值:输入一个正整数 n, 再输入 n 个整数,输出最小值。
解答:参见练习4-10。
(3)求整数的位数以及各位数字之和:输入一个整数,求它的位数以及各位数字之和。例 如,123 的位数是 3,各位数字之和是 6。
解答:
# include <stdio.h>
int main (void) {
int count, number, sum;
scanf ("%d", & number);
if (number < 0) { number = - number;
}
count = 0;
sum = 0;
while (number != 0){
sum = sum + number % 10;
number = number / 10;
count ++;
}
printf ("%d %d\n", count, sum);
return 0;
}
(4)韩信点兵:在中国数学史上,广泛流传着一个“韩信点兵”的故事:韩信是汉高祖刘 邦手下的大将,他英勇善战,智谋超群,为汉朝建立了卓越的功劳。据说韩信的数学水平也 非常高超,他在点兵的时候,为了知道有多少兵,同时又能保住军事机密,便让士兵排队报 数:
按从1 至 5 报数,记下最末一个士兵报的数为 1;
再按从1 至 6 报数,记下最末一个士兵报的数为 5;
再按从1 至 7 报数,记下最末一个士兵报的数为 4;
最后按从1 至 11 报数,最末一个士兵报的数为 10;
你知道韩信至少有多少兵?
解答:
# include <stdio.h>
int main (void) {
int n;
n = 0;
while (n % 5 != 1 || n % 6 != 5 || n % 7 != 4 || n % 11 != 10){
n++;
}
printf ("%d\n", n);
return 0;
}
(5)求序列前 N 项和:输入一个正整数 n,输出 2/1 + 3/2 + 5/3 + 8/5 + …的前 n 项之和(该
序列从第二项起,每一项的分子是前一项分子与分母的和,分母是前一项的分子),保留 2
位小数。
解答:参见习题程序设计第3 题。
(6)求 a+aa+aaa+aa…a:输入两个正整数 a 和 n,求 a + aa + aaa + aa…a(n 个 a)之和。试 编写相应程序。
解答:参见习题程序设计第4 题。
三 、 改 错 题
序列求和:输入一个正实数eps,计算并输出下式的值,直到最后一项的绝对值不大于
于eps(保留 6 位小数)。请使用 do-while 语句实现循环。(源程序 error04_2.cpp)
1 1 1 1 1
1 ...
4 7 10 13 16
s = − + −
+ − +提醒:教材上此题对最后一项取值的描述为“精确到最后一项的绝对值小于 eps”。下次印 刷时将修改一致。