1、第 4 单元 循环结构程序设计,信息学奥赛(C+),第 1 课 while 语句,学习目标 1. 理解循环结构的含义。 2. 熟练掌握 while 语句的格式和功能。 3. 初步应用 while 语句解决一些实际问题。,循环结构,在程序设计中,经常需要反复执行某一条语句或一个语句块,这种结构称为“循环结构”或者“重复结构”。其实,计算机最擅长的就是重复做一件事情,所以循环结构在程序设计中应用非常广泛。 在 C+ 中,循环结构有三种实现语句:while 语句、do-while 语句和 for 语句。,1. while 语句的含义,其含义为:先计算表达式(一般称为循环条件)的值,当表达式的值为真(
2、循环条件成立)时,去执行一次循环体。和 if 语句不同的是,执行完一次循环体后,while 语句又回到开始处,继续计算和判断表达式的真假,决定是否再次执行循环体。也就是“当表达式成立时,不断重复执行循环体”,所以又称为“当型循环”。,while 语句的格式如下: while(表达式)循环体 ,2.while 语句的应用举例,【问题分析】 设 sum 存放答案,初始化为 0。再设 i 为循环控制变量,初始化为 1。当循环条件(i=100)成立时,反复执行以下循环体: (1) 将 i 累加到和 sum 中; (2) 将 i 取值为下一个数,即 i+。 最后,输出 ans 的值。,例1、求 1+2+
3、3+100 的值。,/p4-1-1 #include using namespace std; int main()int i = 1,sum = 0;while(i = 100) sum += i+;cout sum endl;return 0; ,例2、阅读程序,写出程序的运行结果。,/p4-1-2 #include using namespace std; int main()int i = 100,x = 0,y = 0;while(i 0)i-;x = i % 8;if(x = 1) y+;cout y endl;return 0; ,【问题分析】 一般采用列表观察、找规律的方法,阅
4、读和理解程序。对于本题而言,循环条件为“i 0”,用到 i、x 和 y 这 3 个变量,列表如表 4.1-1。,通过找规律发现,每次 i 是 8*x+1 时,y 的值会加1,也就是97、89、81、9、1,一 共99/8+1=13。所以,程序最后输出 y 的值为 13。,例3、统计正数,【问题描述】 输入若干整数,以 0 结尾,统计其中有多少个正整数。 【输入格式】 一行若干整数,最后一个为 0。 【输出格式】 一行一个整数,表示输入的数据中正整数的个数。 【样例输入】 3 6 -3 2 0 【样例输出】 3,【问题分析】 对于本题来说,首先要输入一个整数,当它不为 0 时,需要反复执行: (
5、1) 判断该数是否为正数,如果是,则答案累加 1; (2) 输入下一个数,再返回去判断是否为 0。,/p4-1-3 #include using namespace std; int main()int x,s = 0;cin x;while(x != 0)/ 也可以简写成 while(x)if(x 0) s+;cin x;cout s endl;return 0; ,例4、投资收益,【问题描述】 小华在去年赚了一大笔钱。他想把这些钱用于投资,并对自己能得到多少收益感到好奇。 已知投资的年利率为 r(020 之间的整数),小华现有 m 元钱。他想知道投资多少年后,他的钱将会超过 y 元。 【输
6、入格式】 一行三个整数 r、m 和 y,相邻两个整数之间用一个空格隔开。m 为 1001000000 之间的整数。 【输出格式】 一行一个整数,即要投资的年数。保证答案的范围在 1400 之间。 【样例输入】 5 5000 6077 【样例输出】 4,【样例说明】 第一年后:1.05 * 5000 = 5250; 第二年后:1.05 * 5250 = 5512.5; 第三年后:1.05 * 5512.5 = 5788.125; 第四年后:1.05 * 5788.125 = 6077.53125。,【问题分析】 小华手里有 m 元钱,目标是超过 y 元钱,k 表示答案(初始化为 0)。所以,当条
7、件“m = y”成立时,要反复执行: (1) 修改 m 的值,即 m = m *(1 + r%); (2) 修改 k 的值,即 k+。 循环结束后,k 的值即为所求的答案。,/p4-1-4 #include using namespace std; int main()double r,m,y;int k = 0;cin r m y;while(m = y)m = m * (1 + r / 100);k = k + 1;cout k endl;return 0;,实践巩固,第 2 课 do-while 语句,学习目标 1. 熟练掌握 do-while 语句的格式和功能。 2. 体会 do-wh
8、ile 语句与 while 语句的区别。 3. 熟练运用 do-while 语句解决一些实际问题。,do-while 语句,do-while 语句是 C+ 中用于解决至少执行一次重复操作(循环体)的循环语句。,1. do-while 语句的含义,do-while 语句的格式如下: do循环体 while(表达式);,其含义为:先执行一次循环体,然后判断表达式是否成立,如果成立,则返回继续执行循环体,直到表达式不成立,才退出循环。一般称之为“直到型循环”。,例1、用 do-while 语句实现输出一行 10 个“”。,/p4-2-1 #include using namespace std; i
9、nt main()int i = 1;doprintf( “ ” );i+;while(i = 10);return 0; ,例2、统计正数,【问题描述】 用 do-while 语句实现:输入若干整数,以 0 结尾,统计其中有多少个正整数。 【输入格式】 一行若干整数,最后一个为 0。 【输出格式】 一行一个整数,表示输入的数据中正整数的个数。 【样例输入】 3 6 -3 2 0 【样例输出】 3,/p4-2-2 #include using namespace std; int main()int x,s = 0;docin x;if(x 0) s+;while(x != 0);cout s
10、 endl;return 0; ,例3、投资收益,【问题描述】 小华在去年赚了一大笔钱!他想把这些钱用于投资,并对自己能得到多少收益感到好奇。 已知投资的年利率为 r(020 之间的整数),小华现有 m 元钱。他想知道投资多少年后,他的钱将会超过 y 元。要求用 do-while 语句实现。 【输入格式】 一行三个整数r、m和y,相邻两个整数之间用一个空格隔开。m为1001000000之间的整数。 【输出格式】 一行一个整数,即要投资的年数。保证答案的范围在 1400 之间。,【样例输入】 5 5000 6077 【样例输出】 4,/p4-2-3 #include using namespac
11、e std; int main()double r,m,y;int k = 0;cin r m y;dom = m * (1 + r / 100);k = k + 1;while(m = y)cout k endl;return 0; ,例4、数字和,【问题描述】 输入一个正整数,输出它的各位数字之和。 【输入格式】 一行一个正整数,int 范围以内。 【输出格式】 一行一个正整数,表示答案。 【样例输入】 258 【样例输出】 15,【问题分析】 求一个正整数的各位数字之和,需要“分解”出它的每一位数字,每次进行累加。定义累加器 s,初始化为 0。对于正整数 n,分解的过程就是从低位到高位,
12、不断求余累加(s += n % 10)和整除(n = n / 10),直到 n 等于 0。,/p4-2-4 #include using namespace std; int main()int n,s = 0;scanf( “ %d ” , ,实践巩固,第 3 课 for 语句,学习目标 1. 熟练掌握 for 语句的格式、功能和应用场合。 2. 学会用 for 语句改写 while 和 do-while 语句。 3. 熟练应用 for 语句解决一些实际问题。,for 语句,如果重复执行的操作(循环体)次数是固定的、已知的,则一般使用 for 语句。,for 语句的格式如下: for( 表达
13、式 1; 表达式 2; 表达式 3)循环体 ,例1、用 for 语句实现:输出一行 10 个“”。,/p4-3-1a #include using namespace std; int main()for(int i = 1; i = 10; i+)printf( “ ” );printf( “ n ” );return 0; ,for 语句写法灵活,上述程序也可以写成:,/p4-3-1b #include using namespace std; int main()int i = 1;for(; i = 10; i+) printf( “ ” );printf( “ n ” );retur
14、n 0; ,还可以写成:,/p4-3-1c #include using namespace std; int main()int i = 1;for(; i = 10; )printf( “ n ” );i+;printf( “ n ” );return 0; ,例2、斐波那契数列,【问题描述】 斐波那契数列是指这样的数列:第一个数和第二个数都为 1,接下来每个数都等于前面两个数之和。编程输入一个正整数 k,输出斐波那契数列第 k 个数。 【输入格式】 一行一个正整数 k,1k46。 【输出格式】 一行一个正整数,表示斐波那契数列第 k 个数的大小。 【样例输入】 19 【样例输出】 418
15、1 【问题分析】,/p4-3-2 #include using namespace std; int main()int k;cin k;int k1 = 1,k2 = 1,k3 = 1;for(int i = 3; i = k; i+)k3 = k1 + k2;k1 = k2; / 迭代法k2 = k3;cout k3 endl;return 0; ,例3、求平均年龄,【问题描述】 给出一个班级里每名学生的年龄(正整数),求所有学生的平均年龄,保留到小数点后两位。 【输入格式】 一行一个正整数 n,表示学生的人数,1n100。 后面 n 行,每行一个正整数,表示学生的年龄,15年龄25。 【
16、输出格式】 一行一个浮点数,保留到小数点后两位。 【样例输入】 2 18 17 【样例输出】 17.50,/p4-3-3 #include using namespace std; int main()int n;float s;scanf( “ %d ” , ,例4、整数的个数,【问题描述】 给定 k 个正整数,每个数都是大于或等于 1,且小于或等于 10。编程统计其中 1、5 和 10 出现的次数。 【输入格式】 第一行一个正整数 k; 第二行包含 k 个正整数,每两个正整数之间用一个空格隔开。 【输出格式】 第一行为 1 出现的次数,第二行为 5 出现的次数,第三行为 10 出现的次数。
17、 【样例输入】 5 1 5 8 10 5 【样例输出】 1 2 1,/p4-3-4 #include using namespace std; int main()int n;int s1 = 0,s2 = 0,s3 = 0;scanf (“%d“, ,实践巩固,第 4 课 循环嵌套,学习目标 1. 理解循环嵌套的含义。 2. 熟练应用循环语句及其嵌套解决一些实际问题。,循环结构的嵌套,循环结构与分支结构的嵌套类似,也可以在一个循环语句的循环体里出现另一个循环语句,不管是 while 语句、do-while 语句还是 for 语句。这样的循环结构称为“循环嵌套”。,例1、输出矩形,【问题描述】
18、 输入 n 和 m,输出一个 n 行 m 列的“*”矩形图案。 【输入格式】 一行两个正整数 n 和 m,中间用一个空格隔开,1n、m100。 【输出格式】 输出一个 n 行 m 列的“*”矩形图案。 【样例输入】 3 4 【样例输出】 * * *,/p4-4-1 #include using namespace std; int main()int n,m;scanf (“%d %d“, ,【问题分析】 要输出 n 行,所以可以编写一个外层循环,穷举行。然后,在循环体里,还要输出 m 个“*”,所以再嵌套一个内层循环,穷举每一行的“*”个数。,例2、数字三角形,【问题描述】 输入一个正整数
19、n,输出 n 行的数字三角形。其中,第 1 行为数字 1,第 2 行为数字 23,第 3行为数字 456,第 4 行为数字 7890,第 5 行为数字 12345, 【输入格式】 一行一个正整数 n,1n100。 【输出格式】 n 行的数字三角形。 【样例输入】 4 【样例输出】 1 23 456 7890,/p4-4-2 #include using namespace std; int main()int n,t = 1;scanf (“%d“, ,例3、与 7 无关的数,【问题描述】 一个正整数,如果它能被 7 整除,或者它的某一位上的数字为 7,则称其为“与 7 相关”的数。 现在,请
20、编程求出所有小于或等于 n 的“与 7 无关”的正整数个数。 【输入格式】 一行一个正整数 n,n106。 【输出格式】 一行一个整数,表示答案。 【样例输入】 21 【样例输出】 17,/p4-4-3 #include using namespace std; int main()int n,ans = 0;cin n;for(int i = 1; i = n; i+)int flag1 = 1, flag2 = 1;if(i % 7 = 0) flag1 = 0;int x = i;while(x ,实践巩固,第 5 课 break 和 continue 语句,学习目标 1. 理解 bre
21、ak 语句和 continue 语句的作用。 2. 学会使用 break 语句和 continue 语句。,break 和 continue 语句,在循环结构中,有时需要提前跳出循环体,或者忽略本次循环的后续语句而去执行下一次循环。为此,C+ 提供了 break 语句和 continue 语句。,1. break 语句,在循环体中遇到 break 语句,就会立刻跳出循环体,执行循环结构后面的语句。,例 1、与 7 无关的数。 【问题描述】 一个正整数,如果它能被 7 整除,或者它的某一位上的数字为 7,则称其为“与 7 相关”的数。现在,请编程求出所有小于或等于 n 的“与 7 无关”的正整数
22、个数。 【输入格式】 一行一个正整数 n,n106 。 【输出格式】 一行一个整数,表示答案。 【样例输入】 21 【样例输出】 17,【问题分析】 判断 x 中是否有数字 7 的时候,一旦出现“x % 10 = 7”,则说明 x 是与 7 相关的数,就可以用 break 语句立刻退出当前的 while 循环,这样可以提高程序的效率。,/p4-5-1 #include using namespace std; int main()int n,ans = 0;cin n;for(int i = 1; i = n; i+)int flag1 = 1,flag2 = 1;if(i % 7 = 0)
23、flag1 = 0;int x = i;while(x)if(x % 10 = 7) flag2 = 0; break;x = x / 10;if(flag1 ,2. continue 语句,在循环体中遇到 continue 语句,就会忽略本次循环的后续语句而去执行下一次循环。,例 2、与 7 无关的数。 【问题描述】 一个正整数,如果它能被 7 整除,或者它的某一位上的数字为 7,则称其为“与 7 相关”的数。 请编程求出所有小于或等于 n 的“与 7 无关”的正整数个数。 【输入格式】 一行一个正整数 n,n106 。 【输出格式】 一行一个整数,表示答案。,【问题分析】 当 i 是 7
24、的倍数,即“i % 7 = 0”时,说明 i 已经是与 7 相关的数了,此时,就不再需要判断 i的某一位是否是 7 了。所以,可以用 continue 忽略本次循环的后续语句,而去执行下一次循环,判断下一个数了。这样做同样可以提高程序的效率。,【样例输入】 21 【样例输出】 17,/p4-5-2 #include using namespace std; int main()int n,ans = 0;cin n;for(int i = 1; i = n; i+)int flag = 1;if(i % 7 = 0) continue;int x = i;while(x)if(x % 10 =
25、 7) flag = 0; break;x = x / 10;if(flag) ans+;cout ans endl;return 0; ,3. break 语句和 continue 语句的应用举例,例3、素数的判定 【问题描述】 输入一个正整数,判断其是否为素数。如果是,则输出“prime”;否则,输出“not prime”。 【输入格式】 一行一个正整数 n,2n107 。 【输出格式】 一行一个字符串。 【样例输入】 8 【样例输出】 not prime,/p4-5-3 #include #include using namespace std; int main()int x;cin
26、x;for(int i = 2; i = sqrt(x); i+)/ 或者 i*i =xif(x % i = 0)cout “ not “ ;break; cout “ prime ” endl;return 0; ,例4、素数的统计,【问题描述】 输入两个正整数 m 和 n,判断 m 和 n 之间(含 m 和 n)一共有多少个素数。 【输入格式】 一行两个正整数 m 和 n,2mn104 。 【输出格式】 一行一个整数,表示素数的个数。 【样例输入】 5 10 【样例输出】 2,/p4-5-4 #include include using namespace std; int main()i
27、nt m,n,i,j,ans = 0;cin m n;for(i = m; i = n; i+)for(j = 2; j sqrt(i); j+)if(i % j = 0) break;if(j sqrt(i) continue;ans+;cout ans endl;return 0; ,实践巩固,第 6 课 程序的调试与跟踪,学习目标 熟练掌握程序的调试与跟踪。,程序的调试与跟踪,在编写程序的过程中,错误是在所难免的。一般来说,程序代码越长、算法和数据结构越复杂,出错的概率越高。因此,调试就成了极其重要的一个环节。学会程序的调试与跟踪,可以快速、准确地发现并改正错误。,1. 静态查错,程序写
28、好后,首先要从头至尾通读程序,检查是否存在下面几个问题:语句的顺序、思路、逻辑是否有误;语法是否有误,如关键字是否录入错误、变量是否没有定义就使用、变量的大小写问题、用错标点符号等。其它错误如下: (1) 变量未赋初值 (2) 中间运算结果越界 (3) if-else 语句混乱 (4) 实数比较出错,2. 通过添加输出语句调试程序,/p4-6-1 #include using namespace std; int main()int x;cin x;for(int i = 2; i x; i+)if(x % i = 0) cout x “ “ i endl; / 用于查看 x 和 i 的值co
29、ut “ not “ ;break; cout “ prime ” endl;return 0; ,3. 借助 IDE 的调试工具实施单步跟踪,通过“单步执行”观察跟踪某个变量的值的变化。,实践巩固,第 7 课 循环结构应用举例,学习目标 1. 总结与反思建立循环结构的知识体系。 2. 实践巩固,熟练应用循环结构解决一些实际问题。,例1、金币问题,具体问题见教材128页。,【问题分析】 设共有 N 天,当前为第 i 天,则当 i N 时,可以统计之后连续 K 天所得的金币,在统计过程中,如果 iN,则退出统计。 参考程序见教材129页。,例2、比例简化,具体问题见教材129页。,【问题分析】 由于 L100,可以穷举 A和 B,然后判断 A和 B是否互质。如果互质,那么判断“A/B-A / B”的值是否更小,如果满足,则更新最小值 mindiff 和答案 resa 和 resb。 参考程序见教材130页。,实践巩固,知识回顾Knowledge Review,