描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787302498070丛书名: 高等学校通识教育系列教材
目录
第1章C#概述
1.1.NET与C#概述
1.1.1.NET概述
1.1.2C#语言的发展
1.1.3C#语言的特点
1.2我的第一个C#程序
1.2.1我的第一个控制台应用程序
1.2.2我的第一个Windows应用程序
1.2.3一个具有输入功能的Win32应用程序
1.2.4我的第一个Web应用程序
1.3C#项目结构与程序特点
1.3.1C#项目结构
1.3.2C#程序的特点
习题
上机实验1
第2章C#程序设计基础
2.1常量与变量
2.1.1常量
2.1.2变量
2.2C#的数据类型
2.2.1简单类型
2.2.2枚举型
2.2.3结构型
2.2.4数据类型转换
2.3运算符与表达式
2.3.1算术运算符与表达式
2.3.2赋值运算符与表达式
2.3.3关系运算符与表达式
2.3.4逻辑运算符与表达式
2.4数组和字符串
2.4.1一维数组
2.4.2多维数组
2.4.3数组型的数组
2.4.4字符串
习题
上机实验2
第3章C#程序的流程控制
3.1C#程序的分支语句
3.1.1if语句
3.1.2多分支if…else if语句
3.1.3switch语句
3.1.4分支语句的嵌套
3.2C#程序的循环语句
3.2.1while语句
3.2.2do…while语句
3.2.3for语句
3.2.4foreach语句
3.2.5循环语句的嵌套
3.3跳转语句
3.3.1break语句
3.3.2continue语句
习题
上机实验3
第4章面向对象程序设计入门
4.1面向对象的基本概念
4.1.1对象
4.1.2事件与方法
4.1.3类与对象
4.1.4抽象、封装、继承与多态
4.2类的定义与使用
4.2.1类的声明和实例化
4.2.2类的可访问性
4.2.3值类型与引用类型
4.3类的成员及其定义
4.3.1常量与字段
4.3.2属性
4.3.3方法
4.3.4构造函数
4.4方法的参数传递
4.4.1按值传参
4.4.2按引用传参
4.4.3输出参数
4.4.4引用类型的参数
4.4.5数组型参数
4.5方法的重载
4.5.1方法的重载
4.5.2构造函数的重载
4.6对象的生命周期
4.6.1对象的生命周期
4.6.2终结器
习题
上机实验4
第5章面向对象的高级程序设计
5.1静态成员与静态类
5.1.1类的静态成员
5.1.2静态构造函数
5.1.3静态类
5.2类的继承性
5.2.1派生类的声明
5.2.2构造函数
5.2.3密封类
5.3类的多态性
5.3.1使用new重新定义类的成员
5.3.2用virtual和override定义类的成员
5.3.3访问基类的成员
5.4抽象类
5.4.1抽象类及其抽象成员
5.4.2重载抽象方法
5.5接口
5.5.1接口的声明
5.5.2接口的实现
5.5.3接口的继承性
5.5.4多重接口实现
5.5.5访问接口的成员
5.5.6抽象类与接口的比较
5.6嵌套类、分部类与命名空间
5.6.1嵌套类
5.6.2分部类
5.6.3命名空间
习题
上机实验5
第6章集合、索引器与泛型
6.1集合
6.1.1集合概述
6.1.2ArrayList
6.1.3哈希表Hashtable
6.1.4栈和队列
6.2索引器
6.2.1索引器的定义
6.2.2索引器的使用
6.2.3索引器的重载
6.2.4接口中的索引器
6.2.5索引器与属性的比较
6.3泛型
6.3.1泛型概述
6.3.2泛型集合
6.3.3自定义泛型
6.3.4泛型的高级应用
习题
上机实验6
第7章程序调试与异常处理
7.1程序错误
7.1.1程序错误分类
7.1.2调试程序错误
7.2程序的异常处理
7.2.1异常的概念
7.2.2异常处理
7.2.3try…catch语句
7.2.4finally语句
7.2.5throw语句与抛出异常
习题
上机实验7
第8章基于事件驱动的程序设计技术
8.1基于事件的编程思想
8.2委托
8.2.1委托的概述
8.2.2委托的声明、实例化与使用
8.2.3委托与匿名函数
8.2.4多路广播与委托的组合
8.3事件
8.3.1事件的声明
8.3.2订阅事件
8.3.3触发事件
8.4基于事件的Windows编程
8.4.1Windows应用程序概述
8.4.2Windows窗体与事件驱动编程
习题
上机实验8
第9章Windows程序的界面设计
9.1窗体与控件概述
9.1.1Windows窗体
9.1.2窗体的控件
9.2按钮与文本显示、编辑控件
9.2.1按钮控件
9.2.2文本显示控件
9.2.3文本编辑控件
9.2.4应用实例——用户登录
9.3列表与选择控件
9.3.1RadioButton控件
9.3.2CheckBox控件
9.3.3ListBox控件
9.3.4ComboBox控件
9.3.5其他常用控件
9.3.6应用实例——添加个人收支明细
9.4图形显示控件
9.4.1PictureBox控件
9.4.2ImageList控件
9.4.3应用实例——关于我们
9.5容器控件
9.5.1GroupBox控件
9.5.2Panel控件
9.5.3TabControl控件
9.5.4应用实例——添加收支项目
9.6对话框
9.6.1对话框概述
9.6.2消息框
9.6.3通用对话框
9.6.4应用实例——简单的文本编辑器
9.7菜单、工具栏和状态栏
9.7.1菜单
9.7.2工具栏
9.7.3状态栏
9.7.4应用实例——个人理财系统的主窗口设计
9.8SDI和MDI应用程序
9.8.1创建SDI应用程序
9.8.2创建MDI应用程序
9.8.3应用实例——个人理财的MDI设计
习题
上机实验9
第10章C#数据库编程技术
10.1数据库与ADO.NET概述
10.1.1数据库概述
10.1.2SQL概述
10.1.3ADO.NET概述
10.1.4ADO.NET访问数据库的一般步骤
10.2Connection与Command对象的使用
10.2.1Connection对象
10.2.2Command对象
10.2.3应用实例——实现用户登录
10.2.4应用实例——实现收支类别的添加
10.3DataReader对象的使用
10.3.1DataReader对象
10.3.2应用实例——实现收支项目的添加
10.3.3应用实例——实现收支明细的添加
10.4DataSet与DataAdaper对象的使用
10.4.1DataSet与DataAdaper对象
10.4.2DataGridView控件
10.4.3应用实例——实现收支明细的查询
习题
上机实验10
第11章文件操作与编程技术
11.1文件的输入/输出
11.1.1文件I/O与流
11.1.2读写文本文件
11.1.3读写二进制文件
11.1.4对象的序列化
11.2文件操作控件
11.2.1SaveFileDialog控件
11.2.2OpenFileDialog控件
11.2.3FolderBrowseDialog控件
11.2.4应用实例——简易的写字板程序
习题
上机实验11
第12章高级数据访问与处理技术
12.1XML编程
12.1.1XML概述
12.1.2XML文档的创建
12.1.3XML文档的查询
12.1.4XML文档的编辑
12.2LINQ编程
12.2.1LINQ概述
12.2.2LINQ的查询子句
12.2.3LINQ to XML的应用
12.2.4LINQ to SQL的应用
习题
上机实验12
第13章面向服务编程技术
13.1面向服务编程基础
13.1.1计算机网络的概述
13.1.2计算机网络的通信协议
13.1.3面向服务编程概述
13.2.NET网络编程基础
13.2.1System.Net概述
13.2.2Socket编程概述
13.2.3TCP应用编程
13.2.4UDP应用编程
13.3基于Web API的面向服务编程
13.3.1ASP.NET Web API概述
13.3.2Web API服务器端编程
13.3.3HttpClient客户端编程
习题
上机实验13
第14章多媒体编程技术
14.1GDI 绘图
14.1.1GDI 概述
14.1.2System.Drawing命名空间
14.1.3创建Graphics对象
14.1.4颜料、钢笔和画笔
14.1.5点、线和图形
14.1.6图像和文本
14.1.7坐标系统及变换
14.2Windows Media Player组件的使用
14.2.1Windows Media Player组件的介绍
14.2.2Windows Media Player组件的使用
习题
上机实验14
参考文献
前言
C#是由微软公司推出的完全面向对象的计算机高级语言。经过近20年的发展,如今它不仅能用于开发传统Windows环境中的应用程序,还可以用来开发原生的Android、iOS、Windows Phone和Mac App应用程序,甚至还能整合Azure或Hadoop技术开发云计算和大数据应用系统。相对于C 来说,C#更容易被理解和接受; 相对于Java来说,C#更好用,开发软件的效率更高。本书自2012年2月出版第1版以来,受到广大师生的欢迎。2014年我们组织修订,推出第2版。如今,3年过去了,微软公司已经推出多个C#新版本,使C#具有大量新特性。为此,我们再次组织编写本教材第3版,针对第2版主要进行以下修订。(1) 在第1章中增加.NET技术体系结构的介绍,使读者对.NET技术有更全面的了解。为了便于读者更早和更快地理解C#程序,把C#程序的特点独立编成1节。(2) 如今海量的文本日志成为构建大数据技术的主要研究内容,特征提取与转换、数据分析与挖掘成为程序设计的重点,为此,第2章加强了字符串的内容,包括文本格式化处理的内容等。(3) 自C# 3.0开始,C#添加很多新特性,例如,引入表达式主体(expressionbodied)来简化对象属性和索引器的定义,引入Lambda表达式简化匿名函数的定义,不仅降低了C#程序的复杂度,还使C#源代码更加优雅。(4) 云计算和大数据技术的基础是面向服务的程序设计思想。要想快速适应云计算和大数据时代的新要求,必须更早地了解或熟悉这种新思想。为此本书第13章剔除原来的一部分内容,增加面向服务的编程技术。本书第3版以Visual Studio .NET 2017和C# 7.0为蓝本,深入介绍C#语言及其应用。全书共分14章,基本上覆盖了C#的主要领域,在讲解C#语法的基础上,不仅阐述面向对象、基于事件驱动和面向服务的3种不同的程序设计思想,还全面展现C#的具体应用技术,包括Windows程序设计、数据库应用编程、文件操作与编程、XML与LINQ高级数据访问、面向服务编程和多媒体处理编程技术等。本书继续保持以下优点: 第一,面向应用型本科院校学生,立足于把C#的语法讲透彻、讲清楚,文字叙述尽量简练; 第二,重点围绕面向对象程序设计思想和可视化的Windows程序设计方法展开教学内容; 第三,书中所有案例均精心设计,不仅代码完整,还贴近学生实际生活; 第四,坚持零起点原则,学生可以在没有C/C 基础的情况下使用本书; 第五,坚持应用为纲,全面展示C#在各应用领域的编程技巧。本书可作为高等院校Visual C# .NET课程的教材或参考资料,也可供软件开发人员参考使用。本书由四川大学锦城学院的罗福强老师主持修订。参与本书编写的还有杨剑、张敏辉、熊永福、陈虹君、李瑶、赵力衡等老师。本书长期以来获得清华大学出版社的各级领导的重视和支持,也获得了作者所在单位领导的大力支持。在此,我们对支持本书编写出版并提供过大量帮助的所有人员表示诚挚的感谢!由于时间仓促,书中难免有不妥之处,我们殷切地期望读者提出宝贵的意见。
编者2018年4月
总体要求 理解分支的概念,掌握if语句和switch语句的使用方法。 掌握条件运算符和条件表达式的使用方法。 理解循环的概念,掌握while、do…while、for、foreach语句的使用方法。 理解分支嵌套、循环嵌套的概念,了解相关应用。 掌握continue和break语句的使用方法。相关知识点 VS2017中创建项目、编辑程序、生成和调试应用程序的方法。 变量的声明和使用。 关系运算符和关系表达式。 逻辑运算符和逻辑表达式。 一维数组和字符串的使用方法。学习重点 if语句和switch语句的使用方法。 while、do…while、for和foreach语句的使用方法。学习难点 分支结构中条件的分析。 循环条件、循环操作的分析。 分支嵌套和循环嵌套。一段C#程序是由若干条C#语句按先后顺序排列而成的。语句的排列顺序体现了程序的执行流程。通常,程序段按语句的先后顺序执行,如果需要改变执行流程,必须使用分支或循环语句。本章将详细介绍有关分支和循环的概念及其实现方法。3.1C#程序的分支语句程序的基本结构有3种: 顺序结构、分支结构和循环结构。顺序结构的执行流程是按程序语句的书写顺序依次执行。但是,大量实际问题通常包含复杂的业务逻辑,有些需要根据条件判断结果选择不同的执行顺序,或者需要重复执行某些操作流程,前者称为分支结构,后者称为循环结构。本节将介绍C#的两个分支语句: if语句和switch语句。3.1.1if语句1. if语句的一般形式
if语句也称为条件语句,或选择语句,用于实现程序的分支结构,根据条件是否成立来控制执行不同的程序段,完成相应的功能。if语句的一般形式如下:
if (表达式)
{
语句块1
}
else
{
语句块2
}
图31if语句
其中,表达式表示条件判定,必须是布尔型的,通常由关系型表达式或逻辑表达式组成。if语句的逻辑意义为: 如果表达式的值为true,则选择执行“语句块1”,否则选择执行“语句块2”,如图31所示。if…else…的结构通常称为双分支结构。实际编程时,可省略else子句,构成单分支结构。当“语句块1”或“语句块2”只有一条语句时,可以省略花括号{},还可以在同一行书写。例如,设x为int型变量,下面的语句就是典型的单分支结构:
if(x%2==0)
Console.Write(“x为偶数”);
它表示: 先将变量x除2求余数,再将余数与0进行比较,如果相等,则显示“x为偶数”。2. 条件运算符和条件表达式在C#中,如果双分支结构比较简单,可使用条件表达式来替代if语句。条件表达式的一般格式如下:
(表达式1)?表达式2:表达式3
其中条件运算符?:是C#语言中仅有的一个三目运算符。条件表达式完成的运算是: (1) 如果表达式1的值为真(true),那么整个表达式的值为表达式2的值; (2) 否则,为表达式3的值。例如,设x,y为int型变量,则下面语句:
int max=(x>y)?x:y;
该语句相当于:
int max;
if(x>y)
max=x;
else
max=y;
图32运行效果
由此可见,使用条件表达式来构造一些逻辑比较简单的双分支结构,要比if语句更加简练。【例31】创建一个Windows应用程序,输入一个整数,判断该数是偶数还是奇数,并显示判断结果,运行效果如图32所示。
(1) 首先在Windows窗体中添加2个Label、1个TextBox和1个Button控件。各控件的主要属性设置见表31。
表31需要修改的属性项
控件属性属 性 设 置Label1Text请输入一个整数: Label2NamelblShowTextBox1NametxtNumButton1NamebtnOkText确定
(2) 然后编写“确定”按钮的Click事件方法,主要代码如下:
using System;
using System.Windows.Forms;
public partial class Test3_1 : Form
{
private void btnOk_Click(object sender, EventArgs e)
{
//提取用户输入并转换为整数
int num = Convert.ToInt32(txtNum.Text);
if (num%2==0)
lblShow.Text = num “是偶数!”;
else
lblShow.Text = num “是奇数!”;
}
}
3.1.2多分支if…else if语句在一个比较复杂的判断逻辑中,条件可能不止一个,这时可以使用多分支的if…else if语句。其语法如下:
if(表达式1) {语句块1;}
else if(表达式2) {语句块2;}
else if(表达式3) {语句块3;}
else if(表达式n) {语句块n;}
else{语句块n 1;}
该语句的功能是: 首先计算表达式1,如果其结果为真(true),则执行语句块1; 否则依次往下计算各表达式的值,直到某个表达式的值为真(true),并且执行相应的语句块。如果所有表达式的值都为假,则执行最后的else子句后的语句块n 1。整个if语句的流程图如图33所示。
图33多分支结构
例如,设x,y为int型变量,则下面语句求出x和y的关系(大于,小于或等于):
string result= “”;
if(x>y)
result= “x比y大”;
else if (xresult= “x比y小”;
else
result= “x和y相等”;
【注意】(1) 整条if语句中只有一个分支能被执行。也就是说,当执行完某个分支后,整条if语句也就执行完毕了。(2) else if子句不能单独使用。(3) 当所有条件都不满足且什么都不用做时,最后的else子句可省略。【例32】创建一个Windows应用程序,实现一个人的体型判断。医学上根据身高和体重,可以计算出“体指数”,从而实现对人肥胖程度的划分: 体指数t=体重w/(身高h)2
其中,w单位是千克,h单位是米,并且有如下判断依据: ① 当t<18时,为偏瘦; ② 当18≤t<25时,为标准; ③ 当25≤t<27时,为偏胖; ④ 当t≥27时,为肥胖。运行效果如图34所示。
图34运行效果
(1) 首先在Windows窗体中添加3个Label、2个TextBox和1个Button控件。各控件的主要属性设置见表32。
表32需要修改的属性项
控件属性属 性 设 置Label1Text体重(kg): Label2Text身高(m): Label3NamelblShowTextBox1NametxtWeightTextBox2NametxtHeightButton1NamebtnOkText确定
(2) 然后编写“确定”按钮的Click事件方法,主要代码如下:
using System;
using System.Windows.Forms;
public partial class Test3_2 : Form
{
private void btnOk_Click(object sender, EventArgs e)
{
double h, w, t;
w = Convert.ToDouble(txtWeight.Text); ////提取用户输入体重并转换为double类型
h = Convert.ToDouble(txtHeight.Text);
t = w / (h * h);
if (t < 18)
lblShow.Text = “您的体型偏瘦,要注意营养!”;
else if (t < 25)
lblShow.Text = “您的体型很标准,要注意保持!”;
else if (t < 27)
lblShow.Text = “您的体型偏胖,要注意多运动!”;
else
lblShow.Text = “您的体型太胖了,要注意锻炼身体!”; }
}
3.1.3switch语句当判断的条件较多,有多个分支时,也可使用switch语句。switch语句主要用于实现多分支结构,其语法更简洁,能处理复杂的条件判断。switch语句的一般格式如下:
switch(表达式)
{
case 常量1:
语句块1;
break;
case 常量2:
语句块2;
break;
…
case 常量n:
语句块n;
break;
default: 语句块n 1;
}
其中,switch中的表达式通常是整型、字符型或字符串表达式,不能是关系表达式或逻辑表达式。case后的常量不允许相同,其类型必须与表达式的值类型一致。switch语句的执行过程为: 首先计算switch语句中表达式的值,再依次与每一个case后的常量比较,当表达式的值与某个常量相等时,则执行该case后的语句块,在执行break语句之后跳出switch结构,继续执行switch之后的语句,如图35所示。如果所有常量都不等于switch中表达式的值,则执行default之后的语句块,其中default子句可以省略,当表达式的值与case后的常量值都不相同时,则退出switch语句,执行该语句后面的语句。
图35switch语句
可见,switch语句中的case只是用来寻找分支的入口。程序在执行时一旦锁定某个分支,就执行该分支中的语句块,直到遇到break语句或到达switch结构的末尾为止。C#不支持从一个case显式贯穿到另一个case,因此在每一个case块的后面都必须有一个break语句, default块的后面也必须有break语句,但当case语句中没有代码时例外,这时可以省略break语句,当表达式的值和一个case后的常量相同时,将直接顺序进入下一个case语句。例如,已知整型量a,b(b≠0),设x为实型量,计算分段函数:
y=a b×x0.5≤x<1.5a-b×x1.5≤x<2.5a×b×x2.5≤x<3.5a/b×x3.5≤x<4.5
使用switch语句求函数值的代码如下:
switch ((int)(x 0.5)) //注意switch中的表达式只能是整型、字符型或字符串表达式
{
case 1: y=a b*x;break;
case 2: y=a-b*x; break;
case 3: y=a*b*x; break;
case 4: y=a/(b*x); break;
default: Console.WriteLine(“x值无效!”);
}
图36运行效果
【例33】创建一个Windows应用程序,将考试的百分制成绩转换为等级: “优秀”“良”“中”“及格”“不及格”,其中成绩大于等于90分的为优秀,80~89分的为良,70~79分的为中,60~69分的为及格,60分以下的为不及格,运行效果如图36所示。
(1) 首先在Windows窗体中添加2个Label、1个TextBox和1个Button控件。各控件的主要属性设置见表33。
表33需要修改的属性项
控件属性属 性 设 置Label1Text成绩: Label2NamelblShowTextBox1NametxtScore
Button1NamebtnOkText确定
(2) 然后编写“确定”按钮的Click事件方法,主要代码如下:
using System;
using System.Windows.Forms;
public partial class Test3_3 : Form
{
private void btnOk_Click(object sender, EventArgs e)
{
double score = Convert.ToDouble(txtScore.Text); //提取用户输入的成绩并转换为浮点数
switch ((int)score / 10) //取出成绩的百位和十位,根据百位和十位确定等级
{
case 10:
case 9:
lblShow.Text = “您的成绩等级为: 优”;
break;
case 8:
lblShow.Text = “您的成绩等级为: 良”;
break;
case 7:
lblShow.Text = “您的成绩等级为: 中”;
break;
case 6:
lblShow.Text = “您的成绩等级为: 及格”;
break;
default:
lblShow.Text = “您的成绩等级为: 不及格”;
break;
}
}
}
}
【注意】因为“case 10: ”后面没有语句,故当表达式: “(int)score / 10”的值为10时,将贯穿到“case 9:”,执行语句“lblShow.Text = “您的成绩等级为: 优”;”。上例也可以用多分支的if…else if语句来实现。如:
if (score >= 90)
lblShow.Text = “您的成绩等级为: 优”;
else if(score>=80)
lblShow.Text = “您的成绩等级为: 良”;
else if(score>=70)
lblShow.Text = “您的成绩等级为: 中”;
else if (score >= 60)
lblShow.Text = “您的成绩等级为: 及格”;
else
lblShow.Text = “您的成绩等级为: 不及格”;
可见,switch语句和if…else if语句有异曲同工的效果,但它们也有不同。 (1) if…else if语句中的每个判定表达式可以是关系表达式,也可以是逻辑表达式,其计算结果是布尔值; 而switch语句中的表达式的计算结果一般是整数或字符串。(2) if…else if更适合于不同取值范围的判定,而switch只适合临界值是否相等的判定。(3) if…else if满足一个表达式时,一旦执行完其后面语句就立即退出,而switch满足一个表达式后时,执行其后面语句直到break才退出。(4) if…else if后的语句超过一句要用{},而switch中的case后不管有多少条语句都可以不要{}。3.1.4分支语句的嵌套无论是if语句,还是switch语句,其中的语句可以是任何合法的C#语句,包括if语句或switch。如果if语句或switch语句中包含了if或switch语句,则称之为嵌套的分支语句。其中,嵌套的if语句也可以用来构建多分支结构的程序,以替代switch语句。对于嵌套的if语句,从上到下,else子句只与最近的尚未配对的if配对。为方便阅读和理解if和else的配对关系,要注意采用缩进格式书写代码或添加花括号{}。例如,
if (x % 2 == 0) //①号if
if (x % 3 == 0) //②号if
Console.WriteLine(“x是能被6整除的偶数”);
else //①号else
Console.WriteLine(“x是不能被6整除的偶数”);
else //②号else
Console.WriteLine(“x是一个奇数”);
其中,①号else子句与最近的②号if配对,而②号else只能与①号if配对。【例34】创建一个Windows应用程序,使用嵌套的分支语句来判断用户输入的字符类型,运行效果如图37所示。
图37运行效果
(1) 首先根据表34在Windows窗体中添加窗体控件。
表34需要添加的控件及其属性设置
控件属性属 性 设 置Label1Text请输入一个字符: Label2NamelblShowTextBox1NametxtChar
Button1NamebtnOkText确定
(2) 然后在源代码视图中编辑如下代码。
using System;
using System.Windows.Forms;
public partial class Test3_4 : Form
{
private void btnOk_Click(object sender, EventArgs e)
{
char c = Convert.ToChar(txtChar.Text); //字符串转换为字符型
if (Char.IsLetter(c)) //判定指定的字符是否是一个字母
{
if (Char.IsLower(c)) //判定指定的字符是否是一个小写字母
{
lblShow.Text = “它是一个小写字母。”;
}
else if (Char.IsUpper(c)) //判定指定的字符是否是一个大写字母
{
lblShow.Text = “它是大写字母。”;
}
else
{
lblShow.Text = “它是中文字符。”;
}
}
else if (char.IsNumber(c)) //判定指定的字符是否是一个数字
{
lblShow.Text = “它是数字。”;
}
else
{
lblShow.Text = “它不是语言文字,也不是数字。”;
}
}
}
该程序首先要求从键盘输入一个字符,然后对其进行判断,如果所输入的字符是文字字符,则进一步判断它是否为小写字母、大写字母或中文字符。如果不是文字字符,则进一步判断它是否为数字字符。注意,该程序的if语句最多为3重嵌套,为了便于理解嵌套关系,同时使用花括号和缩进格式来书写代码。3.2C#程序的循环语句循环结构是程序设计的基本结构之一。其特点是: 在给定条件成立时,反复执行某程序段,直到条件不成立为止。给定的条件称为循环条件,反复执行的程序段称为循环体。C#语言提供了多种循环语句,可以组成各种不同形式的循环结构,包括while语句、do…while语句、for语句和foreach语句。本节将分别作介绍。3.2.1while语句while语句表达的逻辑含义是: 当逻辑条件成立时,重复执行某些语句,直到条件不成立时终止,从而不再循环。因此在循环次数不固定时使用while语句。while语句的一般形式为:
while(表达式)
{
语句块;
}
其中,表达式必须是布尔型表达式,用来检测循环条件是否成立,语句块为循环体。while语句执行过程如图38所示: 首先计算表达式,当表达式的值为true时,执行一次循环体中的语句,
图38while语句
重复上述操作到表达式的值为false时退出循环。如果表达式的值在开始时就为false,那么不执行循环体语句直接退出循环。因此,while语句的特点是: 先判断表达式,后执行语句。
while语句在实际应用中,应该按照这样的思路进行设计: 为了保证循环能正常进行,首先应在while语句之前增加一个控制循环的变量,并为其赋初值(当然该初始值应该符合循环的条件,即代入while语句中的表达式后,表达式的值为true); 然后,在循环体中增加一条改变该变量值的语句,循环体每重复执行一次,其值就增加或减少一次。经过若干次循环后,其值将不符合循环条件,此时循环终止。【例35】求∑100n=1n,即1 2 3 … 100。【分析】该题的求解实际是一个逐步累加的过程,就是做如下操作:
首先令sum=0;
sum=sum 1;
sum=sum 2;
sum=sum 3;
sum=sum 100;
最后的sum即是所求的累加和。从上面的操作中可以看到有相同的操作存在: 增加、赋值……,直到所有的数用完。而循环结构正好适用于这样的重复过程。因此,可以制定这样的算法: (1) 令sum = 0,i = 1;(2) 如果i > 100,转到第6步; (3) 否则,sum = sum i; (4) i = i 1; (5) 重复第2步; (6) 输出sum变量的值,结束。根据上述算法写成的程序如下所示:
using System;
using System.Windows.Forms;
public partial class Test3_5 : Form
{
private void Test3_5_Load(object sender, EventArgs e)
{
int i, sum;
i = 1; //为循环变量赋初值
sum = 0;
while (i <= 100) //循环条件
{ //循环体
sum = sum i;
i ; //改变循环变量的值
}
lblShow.Text = “1到100的自然数之和是” sum; //显示计算结果
}
}
图39运行效果
该程序代码主要包含在窗体的Load事件方法“Test3_5_Load”中。程序先计算1到100的自然数之和,再使用Label控件显示计算结果,运行效果如图39所示。
3.2.2do…while语句do…while语句的特点是先执行循环体,然后判断循环条件是否成立,其一般形式为:
do
{
语句块;
}
while (表达式);
图310do…while语句
其中,语句块为循环体,表达式必须是布尔型表达式,用来检测循环条件是否成立。dowhile语句执行过程如图310所示: 首先执行一次循环体,然后再计算表达式,如果表达式的值为true,则再执行一次循环体,重复上述操作,直到表达式的值为false时退出循环。如果条件在开始时就为false,那么执行一次循环体语句后退出循环。例如:
i = 1; //为循环变量赋初值
sum = 0;
do
{
sum = sum i; //循环体
i ; //改变循环变量的值
} while (i <=100); //循环条件
lblShow.Text = “1到100的自然数之和是” sum; //显示计算结果
使用do…while语句需要注意以下几点。(1) while是先执行后判断,循环至少做1次。(2) 一般情况下,while和do…while均可以替换。但当第一次循环条件不满足的情况下,两者是不等的,不能互换。例如
i = 101;
sum = 0;
while (i <=100)
{
sum = sum i;
i ;
}
循环体一次也不执行,sum为0。而
i = 101;
sum = 0;
do
{
sum = sum i;
i ;
} while (i <= 100);
循环体将执行一次,sum为101。可见,while语句与do…while语句的区别在于: 前者循环体执行的次数可能是0次,而后者循环体执行的次数至少是1次。【例36】创建一个Windows应用程序,统计从键盘输入一行字符中英文字母的个数。【分析】很明显,从一行字符中数出英文字母的个数是一个循环判断的过程。为此,可以设置一个循环控制变量i和记录器变量n。每一次循环先提取文本框中的第i个字符(与此同时变量i加1),再判断该字符是否在A~Z、a~z之间,如果是就执行n 。当i的值等于文本框所输入的字符串长度时,循环结束。(1) 首先根据表35在Windows窗体中添加窗体控件。
表35需要添加的控件及其属性设置
控件属性属 性 设 置Label1Text请输入一行字符: Label2NamelblShowTextBox1NametxtSource
Button1NamebtnOkText确定
(2) 然后在源代码视图中编辑如下代码。
public partial class Test3_6 : Form
{
private void btnOk_Click(object sender, EventArgs e)
{
int n=0, i=0;
do
{
char c=txtSource.Text[i ];
if (c >=’A’ && c <=’Z’ || c >=’a’ && c <=’z’)
n ;
} while (i!=txtSource.Text.Length);
lblShow.Text=String.Format(“在该字符中,英文字母共: {0}个。”, n);
}
}
图311运行效果
该程序运行效果如图311所示。
其中String.Format方法的作用是将相应的变量采用指定格式字符串输出,其中的{0}将用后面的变量值替换,其中的0表示输出变量的序号,序号从0开始,如有多个变量,依次为{0},{1},{2}…3.2.3for语句for语句与while语句、do…while语句一样,可以循环重复执行一个语句或语句块,直到指定的表达式计算为false值。for语句的一般形式为:
for(表达式1;表达式2;表达式3)
{
语句块;
}
图312for语句的执行过程
其中,表达式1为赋值表达式,通常用于初始化循环控制变量; 表达式2为布尔型的表达式,用来检测循环条件是否成立; 表达式3赋值表达式,用来更新循环控制变量的值,以保证循环能正常终止。for语句的执行过程(如图312所示)详细如下。(1) 首先计算表达式1,为循环控制变量赋初值。(2) 然后计算表达式2,检查循环控制条件,若表达式2的值为true,则执行一次循环体语句,若为false,终止循环。(3) 执行完一次循环体语句后,计算表达式3,对控制变量进行增量或减量操作,再重复第(2)步操作。
C#允许省略for语句中的三个表达式,但注意两个分号不要省略,同时保证在程序中有起同样作用的语句。省略后的一般形式如下:
表达式1;
for(;;)
{
if(表达式2==false)
{
break;
}
语句;
表达式3;
}
【例37】一个百万富翁遇到一个陌生人,陌生人找他谈一个换钱的计划,该项计划如下: 我每天给你十万元,而你第一天只需给我一分钱,第二天我仍给你十万元,你给我二分钱,第三天我仍给你十万元,你给我四分钱,……,你每天给我的钱是前一天的两倍,直到满一个月(30天),百万富翁很高兴,欣然接受了这个契约。请编写一个程序计算这一个月中陌生人给了百万富翁多少钱,百万富翁给陌生人多少钱。【分析】设第i天百万富翁给陌生人的钱为ti,则t1=0.01元,由题意可得,ti= ti-1×2。设第i天后百万富翁给陌生人的钱总数为s1i,则s11= t1=0.01,s1i=s1i-1 ti。设第i天后陌生人给百万富翁的钱总数为s2i,则s21= 100000,s2i=s2i-1 100000。显然,这是一个循环过程。
using System;
using System.Windows.Forms;
public partial class Test3_7 : Form
{
private void Test3_7_Load(object sender, EventArgs e)
{
int i;
double t,s1, s2;
s1 = t = 0.01; //百万富翁第一天给陌生人的钱为1分
s2 = 100000; //陌生人第一天给百万富翁的钱为十万元
for (i = 2; i <= 30; i )
{
t = t * 2; //百万富翁第i天给陌生人的钱
s1 = s1 t; //百万富翁第i天后共给陌生人的钱
s2 = s2 100000; //陌生人第i天后共收百万富翁的钱
}
lblShow.Text = String.Format(“百万富翁给陌生人:{0:N2}元。\n”
“陌生人给百万富翁:{1:N2}元。”,s1,s2);
/*说明: 在格式字符”{1:N2}”中,”1″表示索引,
*”N2″表示输出数字的带2位小数,整数每3位用逗号间隔
*如果参数不足2位小数,则自动补充显示0
*/
}
}
图313运行结果
该程序的运行结果如图313所示。
3.2.4foreach语句C#的foreach语句提供了一种简单明了的方法来循环访问数组或集合的元素,又称迭代器。foreach语句的一般形式如下:
foreach(类型 循环变量in表达式)
{
语句块;
}
其中,表达式一般是一个数组名或集合名,循环变量的类型必须与表达式的数据类型一致。foreach语言的执行过程如下: (1) 自动指向数组或集合中的第一个元素。(2) 判断该元素是否存在,如果不存在结束循环。
(3) 把该元素的值赋给循环变量。(4) 执行循环体语句块。(5) 自动指向下一个元素,之后从第(2)开始重复执行。【例38】创建一个Windows程序,实现如下功能。(1) 输入联系人姓名和电话号码并保存到结构体数组中。(2) 使用foreach语句迭代查询指定联系人的电话号码。该程序运行效果如图314所示。
图314运行效果
(1) 首先根据表36内容在Windows窗体中添加窗体控件。
表36需要添加的控件及其属性设置
控件属性属 性 设 置控件属性属 性 设 置Label1Text姓名: TextBox2NametxtTelLabel2Text电话: TextBox3NametxtSearchLabel3Text指定查询条件: Button1NamebtnAddLabel4Text姓名:
Text添加Label5NamelblShowButton2NamebtnSearchTextBox1NametxtName
Text查找
(2) 然后在源代码视图中编辑如下代码:
using System;
using System.Windows.Forms;
public partial class Test3_8 : Form
{
struct Contacter //定义结构体
{
public string name;
public string telphone;
}
Contacter[] persons = new Contacter[10]; //定义结构体数组,用于保存联系人信息
int i=0; //用来记录已添加的联系人的个数
private void btnAdd_Click(object sender, EventArgs e)
{ //获得用户输入并保存到第i个数组元素中
persons[i].name = txtName.Text;
persons[i].telphone = txtTel.Text;
i ;
lblShow.Text = “已成功添加一个联系人!”;
}
private void btnSearch_Click(object sender, EventArgs e)
{
bool isSearched = false; //定义标志变量,用于记录查找是否成功
foreach (Contacter c in persons) //迭代查找指定联系人
{
if (c.name == txtSearch.Text.Trim())
{
isSearched = true; //修改标志变量,表示查找成功
lblShow.Text = “查找成功!此人电话号码为: ” c.telphone;
}
}
if (!isSearched)
lblShow.Text = “查无此人!”;
}
}
【分析】程序首先声明了一个名称为Contacter的结构体,该结构体包含两个成员name和telphone,分别用来记录一个联系人的姓名和电话号码。在程序中,定义了一个结构数组persons用于保存联系人信息,并用i记录当前数组的索引值。用户单击“添加”按钮,则将联系人信息添加到persons[i]中,并显示“已成功添加一个联系人!”,当用户单击“查找”按钮,则使用foreach语句将persons中的每一个联系人取出来,判断该联系人的姓名和在查找文本框中输入的姓名是否一致,如果一致,则显示“查找成功!此人电话号码为: ……”。【注意】foreach语句与for语句的区别。(1) foreach语句用来遍历整个数组。如果只想遍历数组的部分元素(例如,只遍历索引为偶数的元素),那么最好是使用for语句。(2) foreach语句总是从第一个元素遍历到最后一个元素。如果需要反向遍历,那么最好是使用for语句。(3) 如果循环体需要知道元素索引,而不仅仅是元素值,那么必须使用for语句。(4) 如果需要修改数组元素,那么必须使用for语句。这是因为foreach语句的循环变量是一个只读变量。例如,如果在上例的foreach的循环体中加上如下语句:
c.name = “乔峰”;
则在编译时将出现如下错误: “c”是一个“foreach迭代变量”,因此无法修改其成员。3.2.5循环语句的嵌套在一个循环体内又包含另一个循环结构,称为循环嵌套。内层循环体中如果又包含了新循环结构,则称之为多重循环嵌套。C#没有严格规定多重循环的层数,但为了便于理解程序逻辑,建议循环嵌套不要超过3层。C#语言允许各种循环结构任意组合嵌套,一般说来,嵌套循环中涉及几个循环结构就称之为几重循环。下例示意了for和while嵌套组成的二重循环:
for(i=1;i<10;i )
{
while(j<10)
{
Console.WriteLine(“i={0},j={1}”,i,j);
j ;
}
}
【注意】使用循环嵌套时,请注意以下几点。(1) 在使用嵌套时,应使用复合语句(多用花括号)以保证逻辑上的正确性。(2) 内外层的循环变量名应不同,以避免造成混乱。(3) 不允许循环交叉。即内循环必须完全包含于外循环内。(4) 书写时最好养成右缩进的习惯,使得层次清晰,易于检查。【例39】创建一个Windows应用程序,打印如图315所示的九九乘法表。
图315运行效果
【分析】九九乘法表共9行,设行号为i(i=1,2,…,9),设列号为j(j=1,2,…,i),对于i来说,其值每增加1,对应的j将周而复始地从1开始增加,直到等于行号i时结束。显然,如果用2个循环来分别产生行和列,那么产生行的循环必须包含产生列的循环,这是一个嵌套循环。当产生列的循环结束时,可使用“\n”实现换行显示。主要源代码如下:
using System;
using System.Windows.Forms;
public partial class Test3_8 : Form
{
private void Test3_8_Load(object sender, EventArgs e)
{
lblShow.Text = “九九乘法表: \n”;
for(int i = 1; i<=9;i )
{
for (int j = 1; j <= i; j )
{
lblShow.Text = String.Format(“{0}×{1}={2,-2:D}”, i, j, i * j);
/*说明: 在格式字符”{2,-2:D}”中,第一个”2″表示索引,
“-2: D”表示输出十进制数字,左对齐同时占2个字符位置,
如果参数不足2位,则自动补充显示空格
*/
}
lblShow.Text = “\n”;
}
}
}
3.3跳 转 语 句3.2节讨论的循环语句,是以某个布尔型表达式的结果作为循环条件,当表达式的值为false时,就结束循环。但有时希望在循环的中途直接控制流程转移。C#提供了两个跳转语句: break、continue,本节将详细介绍它们的使用方法。3.3.1break语句break语句既可用于switch语句,也可用于循环语句。break语句用于switch语句时,表示跳转出switch语句; 用于循环语句时表示提前终止循环。在循环结构中,break语句可与if语句配合使用,通常先用if语句判断条件是否成立,如果成立,则用break来终止循环,跳转出循环结构。【例310】创建一下Windows程序,先输入一个整数,判断该数是否是整数。【分析】质数是除了1和本身外没有其他因子的数,例如3、17、41等。根据定义,要确定一个数m是否为质数,就可以通过测试m有没有因子来确定。如果有,则不是质数; 反之则是。可以让m一个个地去除以2到m之间的所有整数,只要其中一个能被整除,那么m肯定不是质数; 如果所有的都不能被整除,则m一定是质数。算法如下: (1) 给定数m,令n=m」(向下取整); (2) 令i=2; (3) 令r = m % i; (4) 如果r = 0,则表明m不是质数,转到第8步; (5) 否则,令i ; (6) 如果i≤n,那么转向第3步; (7) 否则,m一定是质数; (8) 结束。操作过程如下: (1) 首先根据表37在Windows窗体中添加窗体控件。
表37需要添加的控件及其属性设置
控件属性属 性 设 置Label1Text整数: Label2TextlblShowTextBox1NametxtNum
Button1NamebtnOkText确定
(2) 然后在源代码视图中编辑如下代码。
using System;
using System.Windows.Forms;
public partial class Test3_10 : Form
{
private void btnOk_Click(object sender, EventArgs e)
{
int num = Convert.ToInt32(txtNum.Text);//把输入的文本转换成对应的整数
int n = (int)Math.Sqrt(num); //Math.Sqrt()方法求指定数字的平方根
int i;
for (i = 2; i <= n; i )
{
if (num % i == 0)
break; //不是质数,跳出循环体
}
if (i <= n) //如果i<=n,一定是在循环体内遇到break退出的,说明num不是质数
lblShow.Text = num “不是质数!”;
else
lblShow.Text = num “是质数!”;
}
}
图316运行效果
该程序的运行效果如图316所示。
3.3.2continue语句continue语句只能用于循环结构,与break语句不同的是,continue语句不是用来终止并跳出循环结构的,而是忽略continue后面的语句,直接进入本循环结构的下一次循环操作。在while和do while循环结构中,continue立即转去检测循环控制表达式,以判定是否继续进行循环,在for语句中,则立即转向计算表达式3,以改变循环控制变量,再判定表达式2,以确定是否继续循环。图317展示了break和continue在for循环结构中的区别。
图317break和continue在for语句中的区别
【例311】创建一个Windows应用程序,过滤连续重复输入的字符。(1) 首先根据表38在Windows窗体中添加窗体控件。
表38需要添加的控件及其属性设置
控件属性属 性 设 置
Label1Text字符串(相同字符将被过滤)Label2TextlblShowTextBox1NametxtSourceButton1NamebtnOkText过滤
(2) 然后在源代码视图中编辑如下代码:
using System;
using System.Windows.Forms;
public partial class Test3_11 : Form
{
private void btnOk_Click(object sender, EventArgs e)
{
char ch_old, ch_new;
ch_old = ‘ ‘;
lblShow.Text = “过滤之后的结果如下: \n\n”;
for (int i = 1; i < txtSource.Text.Length; i )
{
ch_new = (char)txtSource.Text[i];
if (ch_new == ch_old) continue; //前后两个字符相同,忽略后面的字符
lblShow.Text = ch_new.ToString();
ch_old = ch_new;
}
}
}
程序使用ch_new获取输入的每一个字符,用ch_old记录该字符之前的字符,如果两者相等,则用continue结束本次循环,继续下一次的循环。如果不相同,则将字符ch_new添加到lblShow.Text中,同时,让ch_old=ch_new,继续下一次的循环。该程序运行效果如图318所示。
图318运行效果
习题1. 简述if…else…语句的逻辑意义。2. 请列举switch语句的特点。3. 在使用嵌套的if语句时,else子句与if配对遵循什么原则?4. 比较while语句和do…while语句的异同。5. 请描述for语句的基本格式,并简述其执行流程。6. 比较for语句和foreach语句的异同。7. 指出以下循环体的执行次数。
for(int i = 1; i<=n; i )
{
for(int j = 1; j <= m; j )
{
… //循环体
}
}
8. 比较break语句和continue语句的区别。9. 设计一个Windows应用程序,实现如下功能: 输入考试成绩,判断并显示优、良、中、及格或不及格的等级。10. 有一函数:
y=1-2x(0≤x<10)
x(10≤x<20)
1 2x(20≤x<30)
设计一个Windows应用程序,输入x,输出y值。11. 设计一个Windows应用程序,显示所有水仙花数。所谓水仙花数是指一个3位数,其各位数字的立方和等于该数本身,例如,153就是一个水仙花数,因为153=13 53 33。12. 设计一个Windows应用程序,计算以下分数序列前20项之和:
21,32,53,85,138,2113,…
13. 设计一个Windows应用程序,使用for语句输出杨辉三角的前十行,形式如下: 11112113311464115101051……14. 设计一个Windows应用程序,将1~1000中能被3但不能被5整除的数输出。15. 分析下列程序代码,请写出该程序运行时的输出结果。
using System;
public class Program
{
static void Main(string[] args)
{
for(int i = 1; i<20;i )
{
if(i%2==0 || i%3==0)
Console.WriteLine(i.ToString() ” “);
}
}
}
上机实验3一、 实验目的
1. 理解分支和循环的逻辑意义。2. 掌握C#的if、switch分支语句的使用方法。3. 掌握C#的while、do…while、for、foreach等循环语句的使用方法。二、 实验要求1. 熟悉VS2017的基本操作方法。2. 认真阅读本章相关内容,尤其是案例。3. 实验前进行程序设计,完成源程序的编写任务。4. 反复操作,直到不需要参考教材也能熟练操作为止。三、 实验内容1. 修改上机实验2的第3个实验任务,将输入的n个数字,通过for语句排序并输出。注意,不允许使用Array.Sort()方法排序。2. 设计一个Windows应用程序,实现如下功能。(1) 输入学生姓名和考试成绩并保存到结构体数组中。(2) 使用foreach语句求最高分并输出对应的姓名。3. 设计一个Windows应用程序,输入一行字符,检索是否存在重复的二字词汇(由两个字符组成的字符),输出重复的次数,效果如图319所示。
图319运行效果
核心代码如下:
private void btnSearch_Click(object sender, EventArgs e)
{
int n = 0; //记录重复出现的词汇个数
string[] words = new string[10]; //保存重复出现的词汇
int[] times = new int[10]; //记录每一个词汇的重复出现次数
//寻找第n个出现重复的词汇
for (int i = 0; i < txtSource.Text.Length – 2; i )
{
bool isSame = false; //记录是否发生重复
string source = txtSource.Text.Substring(i, 2); //提取二字源词
int j = i 2;
while (j < txtSource.Text.Length – 2)
{
string target = txtSource.Text.Substring(j, 2); //提取二字目标词
if (source == target)
{
times[n] ; //重复次数增加1
//如果是新出现的重复词汇,则保存
if (Array.IndexOf(words, target) ==-1)
{
isSame = true;
words[n] = target;
}
}
j ;
}
if (isSame) n ; //重复出现的词汇个数加1
}
lblShow.Text = String.Format(“一共有{0}个重复的词汇!\n\n其中,”, n);
for (int i = 0; i < 10; i )
{
if(!String.IsNullOrEmpty(words[i]))
lblShow.Text = String.Format(“”{0}”重复{1}次?”, words[i], times[i] 1);
}
}
四、 实验总结写出实验报告,内容包括实验内容、任务分析、算法设计、源程序、实验体会等,并记录实验过程中的疑难点。
评论
还没有评论。