• 沒有找到結果。

第 4 章 循环结构

N/A
N/A
Protected

Academic year: 2021

Share "第 4 章 循环结构"

Copied!
40
0
0

加載中.... (立即查看全文)

全文

(1)

第 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。

(2)

图 4.1 知识能力结构图 循环结构的

概念

循环体

循环条件

循环语句选择

while 语句

循环语句

do-while 语句

break 语句 continue 语句

典型算法 (循环嵌套)

典型问题的 算法框架

能正确分析实际问题

能根据实际情况合理使用

能根据实际情况熟练编写程序 for 语句

(3)

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

4

4.1.1 4.1.2 while

π 4=1−1

3+1 5−1

7+…

4-1 π

10

4

4.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;

(4)

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 3

for

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++; /*

*/

}

(5)

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

(6)

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 ++;

}

(7)

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

(8)

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: 9

No!

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!

(9)

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;

}

(10)

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

(11)

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

(12)

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

(13)

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

(14)

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);

}

(15)

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

• 

• 

• 

(16)

(保留 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 和猜测的

(17)

最大次数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;

(18)

}

源程序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;

}

(19)

练习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)

(20)

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;

(21)

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.求奇数和。输入一批正整数(以零或负数为结束标志),求其中的奇数和。试编写相应

(22)

程序。

解答:

# 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

2

2! + x

3

3! + x

4

4! + ...

提醒:教材上此题的计算公式见下式,且计算结果要求保留2 位小数。下次印刷时将修改 一致。

s = x + x

2

2! + x

3

3! + x

4

4! + ...

解答:

# 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) {

(23)

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;

(24)

}

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);

(25)

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;

}

(26)

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;

(27)

}

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)

(28)

{

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;

(29)

}

解答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;

}

(30)

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);

(31)

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”。下次印 刷时将修改一致。

參考文獻

相關文件

Young people like to play computer

理解句子的 意思 理解句子前 後銜接關係.. 理解段落 理解句子的

間接問句:Do you know your favorite color can also tell people what kind of person you are.. 句中有兩個間接問句:第一個間接問句 your favorite color can also tell people

本課程共分為兩階段。第一階段由基本網頁概念介 紹開始,帶領學員循序漸進使用 FrontPage 2003 建 立個人網頁;第二階段著墨在 Flash

本課程共分為兩階段。第一階段由基本網頁概念介 紹開始,帶領學員循序漸進使用 FrontPage 2003 建 立個人網頁;第二階段著墨在

則是第四句。但取一閻浮對一切忉利是第二句。其第三句易故文無。義必合有。是則

p 先导化合物的优化( Lead Optimization)的 目的是针对先导化合物存在的一些缺陷,进

通过 HSK(二级)的考生可以用汉语就熟悉的日常话题进行简单而直接的 交流,达到初级汉语优等水平。..