第3章 选择结构与循环结构 王德俊 上海交通大学继续教育学院
第3章 选择结构与循环结构 3.1 一个简单的选择结构程序 3.2 if语句——二分支选择语句 3.3 switch语句——多分支选择语句 3.4 一个简单的循环结构程序 3.5 while语句和do…while语句 3.6 for语句和foreach语句 3.7 跳转语句
循环结构程序设计 循环语句用于实现语句块的重复执行 C#中提供了四种不同的循环机制: while 循环 do…while循环 for循环 foreach循环
3.4 一个简单的循环结构程序 ——等差数列求和 3.4.1 创建C#控制台应用程序 【例3.6】 构造一个C#控制台应用程序,使之能够计算下列等差数列的前n项之和,n从键盘输入: 1, 3, 5, 7, 9, …
3.4 一个简单的循环结构程序 ——等差数列求和 3.4.1 创建C#控制台应用程序(续) //创建控制台应用程序ArithProg: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ArithProg { class Program static void Main(string[] args)
循环控制变量 循环条件表达式 while语句 3.4 一个简单的循环结构程序 ——等差数列求和 3.4.2 循环结构解析 3.4 一个简单的循环结构程序 ——等差数列求和 3.4.2 循环结构解析 Console.Write("n = "); int n = int.Parse(Console.ReadLine()); int i = 1; //循环控制变量 int sum = 0; //累加器 while (i <= n) { sum = sum + (2 * i - 1); i++; } Console.Write("1+3+5+...+{0}={1}",2*n-1,sum); Console.ReadLine(); } //Main结束 } //Program结束 } // ArithProg结束 循环控制变量 循环条件表达式 while语句
3.5 while语句和do…while语句 3.5.1 while语句 3.5.2 do…while语句
while语句每次在循环的顶部检测循环是否继续,当循环的条 件为假时,退出循环 3.5 while语句和do…while语句 3.5.1 while语句 while语句用于不知道循环次数的情况 while语句每次在循环的顶部检测循环是否继续,当循环的条 件为假时,退出循环
while循环语句的格式为: 3.5.1 while语句 while (布尔条件表达式) {语句序列; } 3.5 while语句和do…while语句 3.5.1 while语句 while循环语句的格式为: while (布尔条件表达式) {语句序列; } 布尔条件表达式是每次循环开始前进行判断的条件 当条件表达式的值为true时,执行循环 否则,退出循环
① 布尔条件表达式是一个具有bool值的条件表达式,为循环的条件 ② 作为循环体的语句序列可以是简单语句、复合语句和其他结构语句 ③ while循环的执行过程:首先计算条件表达式的值,如果为真(true), 则执行后面的循环体,执行完后,再开始一个新的循环;如果为假 (false),则终止循环,执行循环体后面的语句 ④ 可以在循环体中的任何位置放置break语句来强制终止while循环——随 时跳出while循环 break语句通常包含于if语句中 ⑤ 可以在循环体中的任何位置放置continue语句,在整个循环体没有执行 完就重新判断条件,以决定是否开始新的循环 continue语句通常包含于if语句中
【例3.7】 用while语句对下列无穷级数求和: 3.5 while语句和do…while语句 3.5.1 while语句(续) 【例3.7】 用while语句对下列无穷级数求和: 分析: (1)该级数可以写成: ,显然各项的分母构成了一个等差数列,因此可以用循环语句来控制; (2)设定循环终止条件:计算机程序不可能真正求一个无穷级数的和,而只能求其前面有限项的和。这样,循环的终止条件可以设为求前面n项的和,或当某一项的值小于给定的阀值。这里取后者。
累加器 循环控制变量(各项分母) while语句 累加器 3.5.1 while语句(续) 3.5 while语句和do…while语句 3.5.1 while语句(续) static void Main(string[] args) { double t = 2; int i = 1; double sum = 0; while (t > 0.000001) t = 1.0 / i; sum = sum + t; i++; } Console.Write("1+1/2+1/3+...+1/{0}={1}", i-1, sum); Console.ReadLine(); 累加器 循环控制变量(各项分母) while语句 累加器
while循环的测试条件在每一次循环开始时判断 do…while循环的测试条件在每一次循环体结束时进行判断
do {语句序列; } while (布尔条件表达式) do…while语句的一般格式为: 该循环的循环体至少执行一次
① 布尔条件表达式是一个具有bool值的条件表达式,为循环的条件 ② 循环体的语句序列可以是一条语句,也可以是多条语句 ③ 循环的执行过程:首先执行循环体,然后计算条件表达式的值,如果条件为真(true),则开始一个新的循环;如果条件为假(false),则终止循环,执行后面的语句 ④ 可以在循环体中的任何位置放置break语句来强制终止do…while循环——随时跳出循环 break语句通常包含于if语句中 ⑤ 可以在循环体中的任何位置放置continue语句,在整个循环体没有执行完就重新判断条件,以决定是否开始新的循环 continue语句通常包含于if语句中
【例3.8】 用do…while语句计算1~100之间所有整数的和。 3.5 while语句和do…while语句 3.5.2 do…while语句 【例3.8】 用do…while语句计算1~100之间所有整数的和。 static void Main(string[] args) { int n = 100; int i = 1; int sum = 0; do sum = sum + i; i++; } while (i <= n); Console.Write("1+2+3+...+{0}={1}", n, sum); Console.ReadLine(); } do…while语句
循环的嵌套 当一个循环(称为“外循环”)的循环语句序列内包含另一 个循环(称为“内循环”),称为循环的嵌套,这种语句结 构称为多重循环结构 三种循环(while循环、do…while循环、for循环)可以互相嵌套 多重循环可能导致程序的执行速度有所降低
P56 四、上机题1(Add_N!) [上机题1] 编写一个C#窗体应用程序,对于输入的正整数n,计 算1!+2!+3!+…+n!的值并输出 分析: 本例是求n个自然数的阶乘之和,分为两步实现: 首先计算自然数的阶乘 然后将阶乘累加
private void button1_Click(object sender, System private void button1_Click(object sender, System.EventArgs e) { int sum,sum1,i,j; sum1=0; i=1; int n=int.Parse(textBox1.Text); while(i<=n) //计算1!+2!+…+i! { sum=1; j=1; while(j<=i) //计算i! { sum=sum*j; j=j+1; } //计算i!结束 sum1=sum1+sum; i=i+1; } //计算1!+2!+…+i! 结束 textBox2.Text=sum1.ToString(); } 该程序中,注意每次阶乘计算前sum的值应重新赋值为1,以便下次实现i的阶乘计算时从1乘到i
其实,本题也可不用双重循环,程序的执行效率会更高 private void button1_Click(object sender, System.EventArgs e) { int sum,sum1,i,j; sum1=0; i=1; int n=int.Parse(textBox1.Text); while (i<=n) //计算1!+2!+…+i! sum=sum*i; //计算i! sum1=sum1+sum; i=i+1; } //计算1!+2!+…+i! 结束 textBox2.Text=sum1.ToString(); } 在某些情况下,将多重循环修改为单循环,可以提高程序的效率,解决的方法往往是采用类似本例的递推方法
3.6 for语句和foreach语句 3.6.1 for语句 3.6.2 foreach语句
for循环常常用于已知循环次数的情况 使用该循环时,测试是否满足某个条件 3.6.1 for语句 如果满足条件,则进入下一次循环 3.6 for语句和foreach语句 3.6.1 for语句 for循环常常用于已知循环次数的情况 使用该循环时,测试是否满足某个条件 如果满足条件,则进入下一次循环 否则,退出该循环
for循环语句格式为: 3.6 for语句和foreach语句 3.6.1 for语句(续) for (表达式1; 表达式2; 表达式3) {循环语句序列; } 表达式1用于参与循环条件变量的初始化,该表达式仅执行一次; 表达式2为条件判断表达式,即每次循环体开始之前,判断该表达式 是否成立,如果成立,进入下一次循环,否则,循环结束; 表达式3用于参与循环条件变量的运算,一般为递增或递减的循环计 数器 循环语句序列用于描述重复执行的语句,当语句序列中仅含有一条 语句时,花括号可以省略
流程图 表达式1、表达式2、表达式3是可选的,但应该注意死循环的发生 可以在循环体中的任何位置放置break语句来强制终止for循环——随时跳出for循环 break语句通常包含于if语句中 可以在循环体中的任何位置放置continue语句,在整个循环体没有执行完就重新开始新的循环 continue语句通常包含于if语句中
【例3.9】 从键盘输入由若干字符构成的一个字符串,用for 语句统计字符串中大写英文字母、小写英文字母、数字字 符和其他字符的个数。 3.6 for语句和foreach语句 3.6.1 for语句(续) 【例3.9】 从键盘输入由若干字符构成的一个字符串,用for 语句统计字符串中大写英文字母、小写英文字母、数字字 符和其他字符的个数。 分析:大写英文字母和小写英文字母的Unicode码值分别分布 在65~90和97~122,数字字符的分布在48~57。于是,结合 if,我们就可以用for语句统计各类字符的个数。
3.6 for语句和foreach语句 3.6.1 for语句(续) static void Main(string[] args) { int lowerNum = 0; //小写字母个数 int upperNum = 0; //大写字母个数 int numeralNum = 0; //数字个数 int otherNum = 0; //其他字符个数 string line = Console.ReadLine(); char[] chars = line.ToCharArray(); int lineLen = chars.Length; //获取字符数组chars的长度
循环条件表达式 循环控制变量 for 语句 3.6 for语句和foreach语句 3.6.1 for语句(续) for (int i=0; i<lineLen; i++) { int unic= (int)chars[i]; //获取字符的ASCII码值 if (unic >= 65 && unic <= 90) upperNum++; //统计大写字母 else if (unic >= 97 && unic <= 122) lowerNum++; //统计大写字母 else if (unic >= 48 && unic <= 57) numeralNum++; //统计数字字符 else otherNum++; //统计其他字符 } Console.WriteLine("大写字母个数:{0}", upperNum); Console.WriteLine("小写字母个数:{0}", lowerNum); Console.WriteLine("数字字符个数:{0}", numeralNum); Console.WriteLine("其他字符个数:{0}", otherNum); Console.ReadLine(); } //end main
对于集合类型中的元素,有时候不在乎元素的下标,或者 根本就没有下标时,foreach语句来处理这所有元素就非常 方便。 3.6 for语句和foreach语句 3.6.2 foreach语句 对于集合类型中的元素,有时候不在乎元素的下标,或者 根本就没有下标时,foreach语句来处理这所有元素就非常 方便。 foreach语句的语法格式如下: foreach (数据类型 变量 in 集合表达式) { 语句序列; }
取出集合表达式中的每一个元素并保存到变量中,每保存一 次变量后执行一次循环体,集合表达式中有多少个元素就有 多少次变量保存和循环体执行操作。 3.6 for语句和foreach语句 3.6.2 foreach语句(续) 取出集合表达式中的每一个元素并保存到变量中,每保存一 次变量后执行一次循环体,集合表达式中有多少个元素就有 多少次变量保存和循环体执行操作。 不能更改变量的值,只能引用。 集合表达式的类型必须为集合类型 对于依次获取数组中各元素值的操作,使用这种循环语句很 方便
依次获取整型数组A中各元素值的操作,使用foreach循环语句很方便,如下段程序用于依次获取数组中的数据并判断输出其中的奇数: 3.6 for语句和foreach语句 3.6.2 foreach语句(续) 依次获取整型数组A中各元素值的操作,使用foreach循环语句很方便,如下段程序用于依次获取数组中的数据并判断输出其中的奇数: int [ ]A=new int[10]{2,7,12,35,43,11,24,268,67,88}; // 创建数组 lblInfo.Text="数组中的奇数为:"+'\n'; foreach(int i in A) // 输出数组各元素值 { if (i%2==1) lblInfo.Text=lblInfo.Text+i+" "; }
【例3.10】 将学生的记录信息(包括学号和姓名)保存到 Hashtable类的实例中,然后用foreach语句筛选学号为奇数的 学生。 3.6 for语句和foreach语句 3.6.2 foreach语句(续) 【例3.10】 将学生的记录信息(包括学号和姓名)保存到 Hashtable类的实例中,然后用foreach语句筛选学号为奇数的 学生。 分析:Hashtable是命名空间System.Collections中的一个容器, 它类似于数组(属于一种集合类型),但比数组功能强大得 多。它支持任何类型的key/value键值对,可以对其进行元素 添加和删除、数据清空等操作。
HashTable 类表示键/值对的集合,这些键/值对根据键的哈希代 码进行组织。 每个元素都是一个存储在 DictionaryEntry对象中的键/值对。键不 能为 null 引用,但值可以。 建议在这里停留一下,查MSDN中关于HashTable的用法,参照里面给的例子程序再考虑本程序的设计
3.6 for语句和foreach语句 3.6.2 foreach语句(续) using System.Collections; //必须引入System.Collections命名空间,才能使用Hashtable类 static void Main(string[] args) { Hashtable ht = new Hashtable(); //创建一个Hashtable实例 ht.Add(201001, "张赵刚"); //在哈希表实例中添加学生记录 ht.Add(201002, "李斯"); ht.Add(201003, "王智高"); ht.Add(201004, "蒙恬"); ht.Add(201005, "赵高"); Console.WriteLine("学号为奇数的学生:"); Console.WriteLine("------------------------"); Console.WriteLine("学号 姓名"); foreach (DictionaryEntry stuid in ht) if(((int)stuid.Key+1)%2==0) Console.WriteLine(stuid.Key.ToString() + " " + stuid.Value); } Console.ReadLine(); foreach语句
本讲小结 while语句和do…while语句 for语句和foreach语句