搜索
您的当前位置:首页正文

《C++程序设计》完整教案

来源:意榕旅游网
《C++程序设计》教案

蔡勇智 讲师

授课时间:2010年3月 ——2010年 7月 课程性质:专业必修课 课程类别:讲授课+实训课 授课对象:08级电子商务专业 课 时 数:周4

教学目的:通过本课程的学习,使学生理解面向对象程序设计思想,掌握面向对象程序设计的基本概念和技术。使学生深刻理解面向对象技术所带来的观念改革,掌握一种面向对象程序设计语言和面向对象设计的思维方式、规则与基本方法,了解面向对象程序设计技术的发展趋势。通过面向对象思维的训练,使学生逐渐掌握现代编程能力,为今后的软件开发和各种信息处理打下良好的基础。 教学方法:

本课程以以下两种教学方法为主:

1.理论课堂教学使用多媒体辅助教学手段,并采用可视化的编程工具用于课程学习和编程。

2.实验教学结合理论教学实际情况,布置合适比例的概念理解题和综合设计题,使学生在掌握面向对象概念、巩固知识的同时,提高综合设计和处理实际问题的能力。

第1章 C++概述 3

第一节 面向对象程序设计 ..................................................................................................... 3 第二节 C++的发展 ................................................................................................................. 4 第三节 c++程序的基本结构 .................................................................................................. 4 第四节 Visual C++ 6.0集成开发环境 ................................................................................... 6 第2章 C++程序设计基础 ........................................................................................................... 7

第一节 词法符号 ..................................................................................................................... 8 第二节 基本数据类型 ............................................................................................................. 9 第三节 常量与变量 ................................................................................................................. 9 第四节 运算符和表达式 ..................................................................................................... 11 第五节 控制语句 ................................................................................................................. 17 第3章 函数 ................................................................................................................................. 26

第一节 函数的定义和声明 ................................................................................................... 26 第二节 函数调用 ................................................................................................................. 28 第三节 变量的作用域 ......................................................................................................... 30 第四节 内联函数 ................................................................................................................... 31 第五节 函数重载 ................................................................................................................... 32 第六节 带默认参数值的函数 ............................................................................................. 32 第七节 C++的系统函数...................................................................................................... 33 第4章 数组 ................................................................................................................................. 34

第一节 一维数组的定义和数组元素的引用 ..................................................................... 34 第二节 二维数组的定义和数组元素的引用 ..................................................................... 37 第三节 字符数组的定义及初始化 ..................................................................................... 38 第5章 结构体和共用体 ............................................................................................................. 41

第一节 结构体 ..................................................................................................................... 41 第二节 共用体 ..................................................................................................................... 45 第6章 指针和引用 ............................................................................................................. 47 第一节 指针 ......................................................................................................................... 47 第二节 引用 ......................................................................................................................... 58

1

教学内容:

第一章 面向对象程序设计概述 第二章 C++程序设计基础 第三章 函数 第四章 数组

第五章 结构体与共用体 第六章 指针与引用

教学重难点:重难点在于采用面向对象的观点分析问题、解决问题,以及培养学生结合实际应用,采用面向对象的思想设计有效的算法和可视化编程实现能力。

考核方式:平时考勤、作业占30%,期末考试占70%。 使用教材:《C++程序设计》邓振杰 主编

2

第1章 C++概述

本章课时:

4课时

本章重点: c++的基本结构 C++的上机实现 本章难点: C++的上机实现 教学内容及教学目标:

了解:

1.传统程序设计与面向对象程序设计的区别 2.C++的发展

3.面向对象程序设计语言 理解:

1.面向对象程序设计的特点 2.熟悉VC++6.0集成开发环境 掌握:

1.C++的特点

2.C++程序结构和书写规则

第一节 面向对象程序设计

基本概念: 1. 对象

在面向对象程序设计中,对象是由对象名、一组属性数据和一组操作封装在一起构成的实体。其中属性数据是对象固有特征的描述,操作是对这些属性数据施加的动态行为,是一系列的实现步骤,通常称之为方法。 2. 类

在面向对象程序设计中,类是具有相同属性数据和操作的对象的集合,它是对一类对象的抽象描述。类是创建对象的模板,它包含着所创建对象的状态描述和方法的定义,一般是先声明类,再由类创建其对象。按照这个模板创建的一个个具体的实例,就是对象。 3. 属性

对象中的数据称为对象的属性,而类中的特性称为类的属性,不同的类和对象具有不同的属性。 4. 消息

在面向对象程序设计中,当要求一个对象做某一操作时,就向该对象发出请求,通常称为“消息”。当对象接收到消息时,就调用有关方法,执行相应操作。这种对象与对象之间通过消息进行相互联系的机制,就叫做消息传递机制,通过消息传递可实现对象的交互。 5. 方法

3

方法就是对象所能执行的操作。方法包括接口和方法体两部分。方法的接口就是消息的模式,它告诉用户如何调用该方法;方法体则是实现操作的一系列步骤,也就是一段程序代码。

传统程序设计及其局限性:

1. 传统程序设计开发软件的生产效率低下

2. 传统程序设计难以应付庞大的信息量和多样的信息类型 3. 传统程序设计难以适应各种新环境 面向对象程序设计的特点: 1.封装性

封装是一种数据隐藏技术,在面向对象程序设计中可以把数据和与数据有关的操作集中在一起形成类,将类的一部分属性和操作隐藏起来,不让用户访问,另一部分作为类的外部接口,用户可以访问。 2. 继承性

在面向对象程序设计中,继承是指新建的类从已有的类那里获得已有的属性和操作。已有的类称为基类或父类,继承基类而产生的新建类称为基类的子类或派生类。 3. 多态性

多态性是指相同的函数名可以有多个不同的函数体,即一个函数名可以对应多个不同的实现部分。在调用同一函数时,由于环境的不同,可能引发不同的行为,导致不同的动作,这种功能称为多态。它使得类中具有相似功能的不同函数可以使用同一个函数名。

第二节 C++的发展

1980年,美国AT&T公司贝尔实验室的Bjarne Stioustrup博士为了仿真课题研究,编写了称为“带类的C”语言版本。1983年7月用C++将该语言名字定下来,并对外公开发表。 Microsoft公司于20世纪80年代中期在Microsoft C 6.0的基础上开发了Microsoft C/C++ 7.0,同时引进了Microsoft Foundation Class(MFC)1.0版本,完善了源代码。后来Microsoft公司推出了Microsoft C/C++ 8.0,即Visual C++ 1.0版本,之后又推出了 Visual C++ 2.0和Visual C++ 4.0版本。

伴随Windows 98操作系统的发布,Microsoft公司又隆重推出了Visual C++ 6.0 C++的特点:

C++全面兼容C语言,许多C语言代码不经修改就可以在C++中使用。 用C++编写的程序可读性更好,代码结构更为合理。 生成代码质量高,运行效率仅比汇编语言慢10%~20%。 从开发时间、费用到形成软件的可重用性、可扩充性、可维护性和可靠性等方面有很大提高,使得大中型软件开发变得容易很多。

支持面向对象程序设计,可方便地构造出模拟现实问题的实体和操作。

第三节 c++程序的基本结构

【例1.1】一个简单的C++程序。

4

# include void sayhello(); void main() { sayhello( );

// 在显示器上输出显示一行字符串 cout<<\"This is my first C++ program! \"<//函数定义 void sayhello() { cout<<\"Hello! \"<1.头文件

在C++程序开始部分出现以#开头的命令,表示这些命令是预处理命令,称作预处理器。C++提供了3类预处理命令:宏定义命令、文件包含命令和条件编译命令 C++语言包含头文件的格式有两种:#include<文件名.扩展名> #include\"文件名.扩展名\" 2. 函数

C++的程序是由若干个文件组成,每个文件又由若干个函数组成。函数之间 是相互独立的,相互之间可以调用。但函数在调用之前,必须先定义。

C++的程序中的函数可分为两大类,一类是用户自己定义的函数,另一类是 系统提供的标准函数。使用系统提供的标准函数时,可以直接调用,但需要将 该函数的头文件包含在该程序中。 3. 主函数

在组成C++程序的若干个函数中,必须有一个且只能有一个主函数main()。 执行程序时,系统先从主函数开始运行,其他函数只能被主函数调用或通过主 函数调用的函数所调用,函数可以嵌套调用。 4. 注释

第一种注释方法是以“/*”开始,以“*/”结束,二者之间的所有字符都会被作为注释处理,此时的注释可以是一行,也可以是多行,适合于大块的注释。

第二种注释方法是以“//”表示注释开始,本行中“//”后面的字符都会被作为注释处理,这种注释方式多用于较短的程序注释。 5. 输入/输出

输入/输出语句是C++最基本的语句。

综上所述,一个C++程序的基本结构应该包括以“#”开头的若干个预处理命令,将程序所需要的头文件包含进来;然后定义主函数和其他函数,当然函数也可以在程序的起始部分先利用函数要包括各种语句和注释,这部分是程序的主体部分,所占比重也最大。 C++程序的书写格式:

C++程序的书写格式与C程序书写格式基本相同。原则如下:

⑴一般情况下一行只写一条语句。短语句可以一行写多条,长语句也可以分成多行来写。分行原则是不能将一个单词分开,用双引号括起来的字符串最好也不要分开。

⑵C++程序书写时要尽量提高可读性。为此,采用适当地缩进格式书写程序是非常必要的,表示同一类内容或同一层次的语句要对齐。

5

⑶C++程序中大括号{ }使用较多,其书写方法也较多,建议用户要养成使用大括号{ }的固定风格。例如,每个大括号占一行,并与使用大括号的语句对齐,大括号内的语句采用缩进两个字符的格式书写。

第四节 Visual C++ 6.0集成开发环境

Visual C++ 6.0是微软公司开发的可视化的C++集成开发环境。它集程序代码的编辑、编译、连接、调试等功能为一体,界面友好,用户操作方便。

菜单栏 标准工具栏 编译工 工作区窗口 源程序 输出窗口

1 .菜单栏 2.标准工具栏 3.工作区窗口 4.源程序编辑窗口 5.编译工具栏 6.输出窗口

编辑、编译和运行程序: 可执行程序 目标程序 源程序 结果 编辑 编译 连接 运行 Hello.cpp Hello.obj Hello.exe 有错误 无错误

1. 编辑

编辑是将写好的C++源程序输入到计算机中,生成磁盘文件的过程。默认文件扩展名为*.cpp。 2. 编译

编辑好的源程序必须经过编译,,计算机才能执行,这些二进制代码称为目标代码。将这些目标代码以.obj为扩展名保存成目标程序文件。 3. 连接

编译后生成的目标代码还不能直接在计算机上运行,其主要原因是编译器对每个源程序文件分别进行编译,如果一个程序有多个源程序文件,编译后这些源程序文件还分布在不同

6

的地方。因此,需要把它们连接在一起,生成可以在计算机上运行的可执行文件。 4. 运行

可执行文件可以在Windows环境下直接双击运行,也可以在Visual C++ 6.0的集成开发环境下运行。 在生成可执行文件之前,一定要改正编译和连接时出现的致命错误和警告错误,这样才能保证运行结果是正确的。

参照教材练习C++程序的上机实现过程。 利用Debug调试功能调试程序:

Visual C++ 6.0集成开发环境为我们提供了辅助调试工具,可以实现单步运行、设置断点、观察变量和表达式的值等功能,使我们可以跟踪程序的执行过程,观察不同时刻变量值的变化情况。所谓断点就是程序运行时的暂停点,程序运行到断点处便暂停,这样就可以通过观察断点处变量的值来了解程序的执行过程。

参照教材练习利用Debug调试程序的过程。

作业

教材P18-19所有习题。

第2章 C++程序设计基础

本章课时:

16课时

本章重点: 运算符与表达式 控制语句 本章难点: 控制语句 教学内容及目标:

了解:

1. 为什么会有三种基本的程序控制结构 2. C++的基本数据类型 理解:

1.程序控制结构的控制方式:顺序结构,选择结构,循环结构 2.C++的运算符、关键字、标识符和分隔符、常量和变量语法规则 3.转向语句的使用

4.表达式中数据类型的转换规则 掌握:

1.选择控制的使用:if语句,switch语句

2.循环控制结构的使用:while语句,do_while语句,for语句,循环的嵌套 3.判断表达式的使用

7

第一节 词法符号

标识符:

标识符是程序员为命名程序中的一些实体而定义的专用单词。常见的有函数名,类名、变量名、常量名、对象名等。C++语言中标识符的命名规则如下: ⑴标识符是由英文字母(包括大写和小写)、数字和下划线组成,并且以字母和下划线开始,例如:Abc、X1、_x1、desk都是合法的标识符,而2A是非法的。 ⑵标识符中大写和小写字母是有区别的。

⑶标识符的长度是任意的,但有的编译系统仅识别前32个字符。 ⑷标识符不能和C++语言的关键字同名。 关键字:

关键字是一种有特殊用途的词法符号,是C++系统预定义的保留字,不能再用作其他用途。下面列举一些C++语言中常用的关键字: auto break bool case char catch class Const continue default delete do double else Enum explicit export extern false float for

friend goto if inline int long new Mutable name space operator private protected public register return short signed sizeof Static atruct switch this typedef true union unsigned typename void using virtual volatile while static_cast 运算符:

运算符是C++语言实现各种运算的符号,如+、-、*、/ 等。运算符根据操作对象个数的不同,可以分为单目运算符、双目运算符和三目运算符。

单目运算符又称一元运算符,它只对一个操作数进行操作。例如,求负运算符-、逻辑求反运算符!等。

双目运算符又称二元运算符,它可以对两个操作数进行操作。例如,加法运算符+、乘法运算符*等。

三目运算符又称三元运算符,它可以对三个操作数进行操作。C++语言中只有一个三目运算符,就是条件运算符? :。 分隔符:

分隔符又称标点符号,是用来分隔单词或程序正文的,它可以表示某个程序实体的结束和另一个程序实体的开始。在C++语言中,常用的分隔符有以下几个: ⑴空格符:常用来作为单词与单词之间的分隔符。

⑵逗号:用来作为多个变量之间的分隔符,或用来作为函数多个参数之间的分隔符。

⑶分号:用来作为for循环语句中for关键字后面括号中三个表达式的分隔符,或用作语句结束的标志。

⑷冒号:用来作为语句标号与语句之间的分隔符,或switch语句中关键字case<整型常量>与语句序列之间的分隔符。

8

第二节 基本数据类型

C++语言的数据类型是十分丰富的,大致可分为基本数据类型和非基本数据类型。基本数据类型包括整型、字符型、浮点型和布尔型。非基本数据类型主要包括数组类型、结构体类型、共用体类型、指针类型和空类型等,如图2-1所示。

数据类型决定了数据在内存中所占的空间大小,也确定了其表示范围。各种基本数据类型的长度和取值范围见表2-1。 基本整型(int)

整 型 短整型(short)

长整型(long)

字符型 基本数据类型 单精度型(float) 浮点型 双精度型(double)

布尔型(bool)

数据类型 数组类型

构造数据类型 结构体类型 共用体类型 指针类型

空类型(void)

图2-1 C++语言的数据类型

第三节 常量与变量

常量:

1.整型常量

整型常量即整型常数,可以用十进制、八进制和十六进制3种形式来表示。 ⑴十进制整型常量不能以0开始。例如,234、-67为合法的十进制整型常量。 ⑵八进制整型常量以0为前缀。例如,0134、-076为合法的八进制整型常量。 ⑶十六进制整型常量以0X或0x为前缀。例如,0x2F、0xA3B4为合法的十六进制整型常量。 注意:整型常量中的长整型用L或l作后缀表示。例如,324L、076L等;整型常量中的无符号型用U或u作后缀表示。例如,431U、0x34DU等。 2.浮点型常量

浮点型常量又称实型常量,是由整数部分和小数部分组成的,只能用十进制表示。浮点型常量有两种表示方法:小数表示法和科学计数法。

⑴小数表示法:是由符号、数字和小数点组成。例如,9.55、.25等。 ⑵科学计数法:是用指数形式来表示浮点型常量,即在小数表示法后 面加上E或e表示指数。例如,3.2E-5,7e10,-34.5e2等。 3.字符常量

C++中有两种字符常量,即一般字符常量和转义字符常量。

9

⑴一般字符常量:一对单引号括起来的一个字符,其值为ASCII码值。例如,'a'、'A'、'$'、'5'等都是合法的字符常量。

⑵转义字符

转义字符是一个以“\\”开头的特定字符,表示其后的字符具有特殊意义。例如,‘\\n’中的n不是代表字符n,而是代表回车换行的意思。常用的转义字符见表2-2。 字符形式 ASCII码值 \\0 \\a \\b \ \\f \\n \\v \\r \\\\ \\' \\'' \\? \\ddd \\xhh 0x00 0x07 0x08 0x09 0x0c 0x0a 0x0b 0x0d 0x5c 0x27 0x22 0x3f 0ddd 0xhh NULL 响铃 退格(Backspace键) 水平制表(Tab键) 走纸换页 回车换行 垂直制表 回车(不换行) 字符“\\” 单引号 双引号 问号 1~3位八进制数所代表的字符 1~2位十六进制数所代表的字符 功能

表2-2 C++中常用的转义字符 4.字符串常量

字符串常量是用一对双引号括起来的字符序列。例如,\"a\"、\"123\"、\"hello\"等都是字符串常量。这些字符在内存中连续存储,并在最后加上字符'\\0'作为字符串结束的标志。

例如,字符串“HELLO”在内存中占连续6个内存单元,存放示意图如图2-2所示。

H E L L O \\0

图2-2 字符串\"HELLO\"在内存中的存放示意图

字符常量是用单引号括起来的一个字符。它在内存中只占一个字节。所以,\"x\"和'x'是不同的。

注意:不能将一个字符串常量赋给字符常量。例如,语句char c=\"abc\"是错误的。 5.逻辑常量

在C++程序设计中经常会用到两个逻辑值(也称布尔值)0和1,逻辑值“0”代表“假”、“不成立”、“false”等,逻辑值“1”代表“真”、“成立”、“true”等。

6.符号常量

在C++中,可以用一个标识符来表示一个常数,这个标识符就是符号常量。使用符号常量可以增加程序的可读性和可维护性。C++语言提供了两种定义符号常量的方法:

10

⑴用const语句定义符号常量

一般格式为:const 数据类型 符号常量=表达式; 例如:const double pi = 3.1415926; 注意:在定义符号常量时必须进行初始化 ⑵ 用#define语句定义符号常量

#define是预处理指令,缺点是不能显示声明常量的类型。其一般格 式为:#define 常量名 常量值 例如:#define pi 3.1415926 变量:

变量是指在程序运行过程中其值可以改变的量。C++语言中使用变量前,必须先对它的数据类型进行说明,以便编译程序为变量分配存储空间。 1.变量的命名

变量的命名要遵循C++语言中标识符的命名规定 2.变量的定义

变量定义的一般格式为:数据类型 变量1,变量2,……;

其中数据类型可以是前面讲过的各种数据类型,它决定了变量在内存中所占的存储单元数。 例如:int x,y,z; //定义了3个整型变量x、y、z float a,b,c; //定义了3个实型变量a、b、c 3.变量与初始化

可以在声明变量的同时赋初值: 例如:int x=10,y=20+a; 例如:int x(10);

也可以先定义变量,后赋值。例如: int x1,y1; x1=10;y1=20; 注意:

⑴不能连续赋值。如:int a=b=c=5;是错误的。但可以分别赋值。 ⑵在同一个程序块中,不能有两个相同的变量名。 ⑶ 变量赋值时,等号左右两边类型要匹配。

表达式是由运算符和各种运算对象(常数、变量、常量等,也称操作数)组合而成。在C++程序中,表达式与我们在数学中学到的类似,是用于计算的式子,是计算求值的基本单位。

C++语言定义了丰富的运算符。运算符给出计算的类型,而参与运算的数据叫操作数。按运算符的运算性质又可分为算术运算符、关系运算符和逻辑运算符等。 使用运算符时,要注意以下几点:

⑴运算符的功能。如加、减、乘、除等。

⑵与操作数的关系,注意操作数的个数和类型。 ⑶运算符的优先级别。 ⑷运算符的结合性。

第四节 运算符和表达式

表2-3 C++中常用运算符的优先级、功能和结合性

11

优先级 运算符 ( ) :: 功能说明 改变优先级 作用域运算符 数组下标运算符 成员选择 成员指针选择 指针运算符 取地址 求内存字节数 逻辑求反 按位求反 增1、减1运算符 取正、取负运算符 乘法、除法、取余 加法、减法 左移位、右移位 要求操作数的个数 结合性 左结合 1 [ ] . ―> .* ―>* * & sizeof 2 ! ~ ++ -- + - 1 右结合 3 4 5 6 * / % + - << >> < > <= >= 2 2 2 2 左结合 左结合 左结合 左结合 小于、大于、 小于等于、大于等于

表2-3 C++中常用运算符的优先级、功能和结合性(续表) 优先级 7 8 9 10 11 12 13 运算符 == != & ^ | && || ?: 功能说明 等于、不等于 按位与 按位异或 按位或 逻辑与 逻辑或 条件运算符 要求操作数的个数 结合性 2 2 2 2 2 2 3 左结合 左结合 左结合 左结合 左结合 左结合 右结合 14 = += -= *= /= %= 赋值运算符 <<= >>= &= ^= |= , 逗号运算符 2 右结合 15 左结合

1.基本算术运算符与算术表达式

基本算术运算符有:+(取正或加)、-(取负或减)、*(乘)、/(除)、%(取余)。其中+(取正)、-(取负)是单目运算符,其余是双目运算符。上述运算符与其在数学中的意义、优先级、结合性基本相同,即先进行乘法、除法和求余运算,优先级相同,后执行加

12

法和减法运算,优先级相同。

注意:要求取余运算符(%)的两个操作数必须是整数或字符型数据。 算术表达式是由算术运算符与操作数组成的,其表达式的值是一个数值,表达式的类型由运算符和操作数共同确定。

【例2.1】基本算术表达式的计算。 #include void main() { int i=4,j=5,k=6; int x; x=i+j-k; cout<<\"x=\"<运行程序后,输出结果为: x=3 x=27 x=2 y= -3.5

2.增1、减1运算符及表达式

增1、减1运算符都是单目运算符,这两个运算符都有前置和后置两种形式。前置形式是指运算符在操作数的前面,后置是指运算符在操作数的后面。 例如:

i++; //++后置 --j; //--前置 注意:

⑴增1、减1运算符只能用于变量,不能用于常量和表达式。

⑵增1、减1运算符的结合方向是自右向左,如表达式-i++中运算符“-”和“++”优先级相同,结合方向是自右向左,即表达式可以理解为-(i++)。

⑶增1、减1运算符在很多情况下的使用可能会出现歧异,从而产生意想不到的结果。

【例2.2】增1、减1表达式的计算。 #include void main() { int i,j,k,m,n; i=4; j=i++; cout<<\"i=\"<13

i=4; k=++i; cout<<\"i=\"<运行程序后,输出结果为: i=5 j=4 i=5 k=5 i=3 j=4 i=3 k=3 关系运算符:

关系运算符用于比较两个操作数的大小,其比较的结果是一个布尔型的值。当两个操作数满足关系运算符指定的关系时,表达式的值为true,否则为false。 在C++语言中,关系运算符都是双目运算符,共6个:<(小于)、<=(小于或等于)、>(大于)、>=(大于或等于)、= =(等于)、!=(不等于)。其中前4种的优先级高于后2种。 C++语言中虽然有布尔类型,但它仍然继承了C语言的规定,true等于1,false等于0。所以,关系运算符的比较结果可以作为算术运算中的操作数。例如:表达式2 >= 3的结果为0(false)。

在使用关系运算符时还应注意以下几点:

⑴不要把关系运算符“= =”误用为赋值运算符“=”。也不要将不等于运算符“!=”写成其他语言中的不等于运算符“<>”。

⑵'a'>=60的意思是'a'的ASCII码值与60比较大小。

⑶对于数学中表示“x大于等于5,且x小于等于20”的数学关系式5≤x≤20,正确的表达式应该是:5 <= x && x <= 20

关系表达式是由关系运算符和操作数组成,表达式的值都是1(true)或0(false)。经常出现在条件语句和循环语句中,用于决定问题的执行方法。 【例2.3】关系表达式的计算。 #include void main() { int i=4,j=5; cout<<(i>j)<=j)<14

运行程序后,输出结果为: 0 0 1 1 0 1 return

逻辑运算符与逻辑表达式: 1.逻辑运算符

逻辑运算符共有3个:1个单目运算符!(逻辑求反),2个双目运算符&&(逻辑与)和||(逻辑或)。 注意:

在三个运算符中,逻辑非的优先级最高,逻辑与次之,逻辑或最低。 关系运算和逻辑运算的结果若为真,其值为1;若为假,其值为0。

a 0 0 1 1 b 0 1 0 1 a&&b 0 0 0 1 a||b 0 1 1 1

表2-3 逻辑值的逻辑运算结果 2.逻辑表达式

逻辑表达式由逻辑运算符与操作数组成,表达式的值都应是1(true)或0(false)。 【例2.4】逻辑表达式与关系表达式的计算 #include void main() { int x=3,y=5,z; z=(x>0)||(y<10); cout<<\"z=\"<cout<<\"z=\"<cout<<\"z=\"<赋值运算符:

C++中的赋值运算符分为两种:简单赋值运算符和复合赋值运算符。 1.简单赋值运算符“=”

其表达式的一般形式为:变量 = 表达式 2.复合赋值运算符

如果以‘#’表示数值型运算符,则复合赋值表达式的一般形式为:

15

变量 #= 表达式 该表达式等价于:

变量 = 变量 # 表达式 例如:

a += 5 等价于 a = a+5 m %=7 等价于 m = m % 7

复合赋值运算符的优先级和赋值运算符相同,结合性也相同,都为右结合。 3.赋值表达式

赋值表达式由赋值运算符与操作数组成。赋值表达式的作用就是把赋值运算符右边表达式的值赋给左边的变量。赋值表达式的类型为左边变量的类型,其值为赋值后左边变量的值。在C++语言中还可以连续赋值。 【例2.5】赋值表达式的应用。 #include void main() { int m=3,n=4,k; k=m++ - --n; cout<<\"k=\"<运行程序后,输出结果为: k=0 z=0 z=1 z=1

a=10,b=9,c=3 其他运算符: 1.条件运算符

条件运算符“?:”是一个三目运算符,其使用的一般形式为: 表达式1?表达式2:表达式3

该表达式执行时,先分析表达式1,其值为真时,则表达式2的值为条件表达式的值;否则表达式3的值为条件表达式的值。条件运算符的优先级仅高于赋值运算符和逗号运算符 例如,求a和b中较大者,可写成表达式:max = a > b ? a : b 2.逗号运算符

16

由逗号运算符构成的表达式称为逗号表达式,其一般形式为: 表达式1,表达式2,…,表达式n

逗号表达式的执行规则是从左到右,逐个表达式执行,最后一个表达式的值是该逗号表达式的值。

注意:逗号运算符“,”的优先级最低。 例如,表达式“a=3,a+l,a*a”的结果为9。 表达式中数据类型的转换: 1. 隐含转换

当操作数的类型不一致时,表达式的类型就取决于操作数中类型最高的操作数类型,C++语言将自动进行类型转换,隐含转换的示意图如图2-3所示,其转换规则如下:

注意:隐含转换是由编译系统自动完成的,它实际并不改变操作数的数据类型,只是在计算表达式值时,临时改变操作数的数据类型,计算完成后,操作数仍保持原有的数据类型。 2. 强制转换

强制转换的作用是将表达式的类型强制转换成指定的数据类型。 其一般形式为:

数据类型(表达式)或 (数据类型)表达式 例如:

double(a) //将a强制转换成double型 float(5%3) //将5%3的结果转换成float型

注意:如果将高类型转换成低类型,会造成数据精度的损失。因此,这是一种不安全的类型转换。

第五节 控制语句

C++语句概述: 1.表达式语句

表达式语句是由一个表达式加上分号组成。例如: int i; //将i声明为整型变量的语句 a=3*4+5; //赋值语句 2.复合语句

复合语句也称块语句,是由两条或两条以上的语句组成, 并用“{ }”括起来的语句。复合语句在语法上相当于一条语句。 注意:在复合语句的右括号后不再需要分号。 3.控制语句

控制语句通常包括选择语句、循环语句和转移语句。 4.空语句语句

空语句只有一个分号,它不作任何操作,常用在需要一 条语句而又不需要任何操作的地方,如循环语句中。

选择语句: 1.if语句

if语句用来有条件地执行某一语句系列。if语句主要有3种语法格式: (1)简单if语句

17

格式:

if(表达式) {

语句; }

功能:首先计算表达式的值,如果表达式的值不为0,表示条件判定为真,花括号{}内的语句将被执行;否则,将执行{}后面的语句。

其中的表达式一般是关系表达式,并且表达式必须用()括起来。语句可以是一条语句,也可以是多条语句。如果只有一条语句,则{ }可以省略。

【例2.7】简单if语句的应用。 #include void main() {

float score;

cout<<\"Please enter your score:\"<>score; if (score>=60) cout<<\"Passed!\"<cout<<\"No passed!\"<cout<<\"You should do your best to study\"<运行程序后,屏幕上输出显示: Please enter your score: 提示用户输入成绩,当用户输入成绩信息后,程序会根据用户的输入,输出显示相应的信息。如输入70,则显示: Passed!

(2)两分支if语句 格式:

if(表达式) { 语句1; } else {

语句2; }

功能:首先计算表达式的值,如果表达式条件判定为真,则执行语句1,否则将执行语句2。该格式的流程图如图2-5所示。 【例2.8】利用两分支if语句改写例2.7。 #include

18

void main() {

float score;

cout<<\"Please enter your score:\"<>score; if (score>=60) cout<<\"Passed!\"<cout<<\"No passed!\"<cout<<\" You should do your best to study\"<(3)多分支if语句 格式:

if(表达式1) <语句1> else if(表达式2) <语句2> else if(表达式3) <语句3> ┇

else if(表达式n) <语句n> else <语句n+1>

功能:首先计算表达式1的值,如果表达式1条件判定为真,则执行语句1,否则判定表达式2,如果条件判定为真,则执行语句2,……依此类推,直到所有的表达式条件均不满足,此时将执行语句n+1。该格式实际上提供了多重条件选择。该格式的流程图如图2-6所示。

【例2.9】利用多分支if语句比较两个数的大小。 #include void main() { int x,y; cout<<\"Please input x,y:\"<>x>>y; if (x==y) cout<<\"x=y\"<y)

cout<<\"x>y\"<cout<<\"x程序执行后,屏幕上输出显示: Please input x,y:

计算机提示用户输入两个x和y的值。当用户输入后,计算机将显示相应的判断结果。例如,输入1和2后将显示“x19

三种if语句之间可以实现嵌套。通常为了不破坏程序的可读性,嵌套的层次一般不超过两层。

【例2.10】利用if语句的嵌套改写例2.9。 #include void main() { int x,y; cout<<\"Please input x,y:\"<>x>>y; if (x!=y) if (x>y) cout<<\"x>y\"<2.switch语句

switch语句又称开关语句,其语法格式为: switch(表达式M) { case 常量表达式M1:语句1; case 常量表达式M2:语句2; ┇

case 常量表达式Mn:语句n; default:语句Mn+1; }

其中,switch、case和default是关键字,常量表达式通常为整型数值和字符常量,语句1、语句2、……语句n是由1条或多条语句组成的语句段,也可以是空语句。如果是多条语句,可以用花括号{}括起来。 switch语句的执行过程是:首先计算switch语句中的表达式,然后按先后顺序将得到的结果与case中的常量表达式的值进行比较。如果两者相等,程序就转到相应case处开始顺序执行。如果没有找到相匹配的结果,就从default处开始执行。如果没有default,则转到switch语句后面的语句。如果希望switch语句在执行完某一case后面的语句后,不再执行其后面的case和default分支,就需要在每个case的末尾加上一条break语句,表示跳出switch语句。加break语句的switch语句流程图如图2-7所示。

表达式M

M==Mn+1M==M1M==M2M==Mn

... 真语句1

语句2...语句n语句n+120

【例2.11】根据考试成绩的等级给出百分制分数段。 #include void main() { char grade; cout<<\"请输入成绩:\"<>grade; if (grade>='a' && grade<='z')

grade-=32; //若输入小写字母,则转化为大写字母 switch(grade) { case 'A' :cout<<\"90~100\"<< endl; case 'B' :cout<<\"80~89\"<< endl; case 'C' :cout<<\"70~79\"<< endl; case 'D' :cout<<\"60~69\"<< endl; case 'E' :cout<<\"60分以下\"<< endl; default:cout<<\"Input error!\"<运行程序后,屏幕上将显示字符串“请输入成绩:”。假设输入B后,将输出结果: 80~89 70~79 60~69 60分以下 Input error!

显然,这样的输出结果是不符合题目原意的,原因就在于没有用break语句作为每个case的结束语句。现修改例2.11程序如下: switch(grade) { case 'A' :cout<<\"90~100\"<< endl;break; case 'B' :cout<<\"80~89\"<< endl; break; case 'C' :cout<<\"70~79\"<< endl; break; case 'D' :cout<<\"60~69\"<< endl; break; case 'E' :cout<<\"60分以下\"<< endl; break; default:cout<<\"Input error!\"<21

再运行程序,然后输入成绩B,将输出结果: 80~89

循环语句:

在程序设计中经常遇到需要重复执行的操作,这些操作可以使用循环语句来实现。循环语句使得程序在给定条件满足时,能够重复地执行某些操作。C++语言提供了3种循环语句:while循环语句、do-while循环语句和for循环语句。 1.while循环语句

while循环语句的语法形式为: while(表达式) 循环体;

其中,while是关键字,表达式可以是C++语言中任何合法的表达式,它用来判断执行循环体的条件,根据循环条件决定是否执行循环体。循环体由语句组成,可以是一条语句,也可以是多条语句。

while循环执行过程示意图如图2-8所示。

表达式 循环体

图 2 - 8 while 循环执行过程

注意:

如果循环体有多个语句时,要用大括号{}把它们括起来,以复合语句形式出现。 在使用循环语句时,一定要设法改变循环变量,使之在有限次循环之后能满足循环终止条件而结束循环。

【例2.12】编程计算1~100之和。 #include void main() { int i=1,sum=0; while(i<=100) { sum+=i; i++; } cout<<\"sum=\"<22

}

程序运行后,输出结果:sum = 5050 2.do-while循环语句

do-while循环语句的语法形式为: do

…… //循环体部分 while(表达式);

do-while循环语句与while循环语句的区别在于:do-while循环语句首先执行循环体,再求表达式的值。如果其值非0,则再次执行循环体,直至表达式的值为零;而while语句首先求表达式的值,再按其值为零或非零决定是否执行循环体。因此,do-while循环语句中的循环体至少执行一次。do-while循环执行过程如图2-9所示。

注意:do-while循环语句最后的分号不可缺少。 【例2.13】利用do-while循环语句改写例2.12。 #include void main() { int i=1,sum=0; do { sum+=i; i++; }

while(i<=100); cout<<\"sum=\"<循环体表达式真假图2-9 do-while循环执行过程 23

3.for循环语句

for循环语句的功能非常强大。所有while循环语句和do-while循环语句都可以用for循环语句替代。for循环语句的语法形式为:

for(表达式1;表达式2;表达式3) 循环体;

其中,表达式1通常用来给循环变量赋初值;表达式2通常是关系表达式或逻辑表达式,一般用来设置循环条件;表达式3用来在每次循环之后修改循环变量的值。

for语句的执行过程是:首先执行表达式1,给循环变量赋初值;接着执行表达式2,并根据表达式2的值决定是否执行循环体。如果表达式2的值为true或其他非0值,则执行循环体,否则退出循环;每执行完一次循环体后,再执行表达式3,修改循环变量;然后再执行表达式2,并根据表达式2的值决定是否继续执行循环体。For循环语句的执行过程如图2-10所示。

表达式1

表达式2循环体表达式3

图2-10 For循环语句执行过程

在使用for循环语句时,应该注意下列几种情况: (1)for语句中的3个表达式可以没有。但必须注意每个表达式后的分号不能省略。此时for循环语句的形式为:for(;;)

这时在循环体内必须有其他控制循环执行的语句,否则会形成死循环。

(2)表达式1如果没有或不是用来给循环变量赋初值,则应在for语句前给循环变量赋初值。

(3)表达式2如果没有,则在for语句循环体内应有其他控制循环执行的语句,否则会形成死循环。

(4)表达式3如果没有或不是用来修改循环变量的值,则应在for语句循环体内设置相应的语句。

【例2.14】利用for循环语句改写例2.12。 #include void main() { int i,sum=0; for(i=1; i<=100; i++) sum+=i; cout<<\"sum=\"<24

【例2.15】在屏幕上显示0~9共10个整数。 #include void main() { int i=0; for(; i<=9;) cout<程序运行后,将输出结果:

0 1 2 3 4 5 6 7 8 9 return

C++语言还提供了goto语句、break语句和continue语句等转移语句,它们主 要用于改变程序中语句的执行顺序,使程序从某一语句有目的地转移到另一语句 继续执行。 转移语句: 1.goto语句

goto语句语法格式为: goto 语句标号;

goto语句的作用是使程序转移到语句标号所标示的语句处继续执行。语句标号 是一种用来标识语句的符号,其命名遵守标识符的命名规定,放在语句的前面, 并用冒号(:)与语句分开。

C++语言中,goto语句的使用被限制在一个函数体内,即goto语句只能在一个 函数范围内进行语句转移。在同一函数中,语句标号应该是唯一的。

注意:由于goto语句的使用会破坏程序的结构,编程时,应尽量少用或不用。 2.break语句

break语句的语法格式如下: break;

break语句可用在以下两种情况:

(1)break语句用在switch语句中,其功能是退出switch语句。

(2)break语句用在循环语句的循环体中,其功能是退出循环语句。如果是多重循环,它将会在本次循环结束时执行该重循环后面的语句。 3.continue语句

continue语句的语法格式为: continue;

continue语句只能用在循环语句的循环体内。在循环执行的过 程中,如果遇到continue语句,程序将结束本次循环,接着开始 下一次循环。

【例2.16】从键盘上输入10个整数,若是正整数则求和,若是负整数则 不进行计算,继续输入数据,若输入0则终止程序。 #include void main() { int num,sum=0;

25

cout<<\"Please input number:\"<cin>>num;

if(num= =0) break; if(num<0) continue; sum+=num; }

cout<<\"sum=\"<作业

教材P46-47所有习题

第3章 函数

本章课时:

12课时

本章重点: 函数调用 变量作用域 本章难点: 函数调用 教学内容及目标:

了解:

1.参数的传递方式的分类 2.内联函数的含义 理解:

1.变量存储特性与标识符作用域

2.函数调用机制:嵌套调用和递归调用 掌握:

1.函数参数的传递,包括:传值参数,指针参数,引用参数和函数的返回类型2.函数指针:函数的地址,函数指针 3.重载函数的定义与使用方法

第一节 函数的定义和声明

【例3.1】实现两个数相加。 #include

int add(int ,int); //函数原型 void main()

26

{ int sum,x,y; cout<<\"请输入被加数和加数:\"<>x>>y; sum=add(x,y); //函数调用 cout<<\"Sum=\"<int add(int a,int b) //函数定义 { return a+b; }

执行结果:

请输入被加数和加数: 213 625 Sum=838

函数定义的一般语法格式如下: 函数类型 函数名(参数表) {

函数体 }

1.函数类型与返回值

int sum(int a,int b) //有返回值,返回类型为整型 {

return (a+b); }

void printsum(int a,int b) //无返回值 {

cout<函数的返回值由函数体中的return语句给出。return语句的格式为: return (表达式); 或

return 表达式; 或

return;

当程序执行到该return语句时,程序会返回到主调函数中,并带回返回值。在无返回值的函数体中可以没有return语句,遇到花括号“}”时,自动返回到主调用程序。

函数的类型要与return语句的返回值类型相同。如果类型不一致,则以函数类型为准。

2.函数的参数

int max(int a,int b) //有参数 { return a>b?a:b;

27

}

void print(void) //无参数 {

cout<<\"C++ is easy to learn!\"<void print() //无参数 {

cout<<\"Hello world!\"<int max(int a, b)

形参在该函数被调用时才初始化,即从主调函数获取数据。如果被调用函数不需要从调用函数那里获取数据,则该函数可为无参函数。

函数原型:

函数原型又称函数声明,用来告诉编译器函数头的相关内容。函数原型通常位于程序代码的开始处。 函数原型的语法格式为:

类型 函数名(参数列表);

参数列表的个数、顺序和指定的类型必须和函数定义中一致。在函数原型说明中也可以不给出参数名,只给出类型。例如:

int sum(int,int); //不带参数名 int fac(int a); //带参数名

第二节 函数调用

函数调用的概念:

函数调用是用一个表达式表示。 调用格式为:函数名(实参列表); 实参是用来在调用函数时对形参进行初始化的,实参与形式参数个数相同、类型一致、顺序一致。

如果在一个文件中有多个函数,一般都将主程序或主函数放在其他所有函数的前面。在函数调用前进行函数原型的说明,被调用的函数定义放在后面。通常使用函数调用的返回值来给某个变量赋值。

有返回值函数的调用格式为:

变量名=函数名(实参列表); 或

cout<<函数名(实参列表);

在任何情况下,C++能自动将变量的类型转换为与参数一致的类型,这是C++标准类型转换的一部分。任何非法的转换都会被C++编译程序检测出来。 【例3.2】编程求三个整数中最大的数。 #include int max2(int,int);

28

int max3(int,int,int); void main() { int sum,x,y,z,m; cout<<\"请输入三个整数:\"<>x>>y>>z; m=max3(x,y,z); cout<<\"最大的数是:\"<//函数定义

int max2(int a,int b) { return a>b?a:b; }

int max3(int a,int b,int c) { int m1,m2; m1=max2(a,b); m2=max2(m1,c) return m2; }

执行结果:

请输入三个数:25 36 47 最大的数是:47

函数调用的参数传递:

参数形式:数值、引用、指针 参数传递:传值、传址、引用 传值调用是利用参数传递数据最常用的方法。调用时系统先计算实参的值,再把实参的值按位置赋给对应的形式参数。本质是复制实参给形参,以后二者互不影响。 【例3.3】两整型数互换。 #include void swap(int,int); void main() { int a,b; cin>>a>>b; swap(a,b); cout<<\"main program a=\"<//函数定义

void swap(int x,int y) { int t; cout<<\"function swap begin a=\"<29

t=x; x=y; y=t; cout<<\"function swap end a=\"<程序执行结果为: 10 20

function swap begin a=10 b=20 function swap end a=20 b=10 main program a=10 b=20 return

1.函数的嵌套调用

若在一个函数调用中又调用了另外一个函数,则称这样的调用过程为函数的嵌套调用。 程序执行时从主函数开始执行,遇到函数调用时,如果函数是有参函数,系统先进行实参对形参的替换,然后执行被调用函数的函数体。如果函数体中还调用了其他函数,再转入执行其他函数体。函数体执行完毕后,返回到主调函数,继续执行主调函数中的后续程序行。 3.2.3 函数的嵌套调用和递归调用 2.函数的递归调用

在调用一个函数的过程中出现直接或间接调用该函数本身,就称作函数的递归调用,这样的函数称为递归函数。编写递归函数时,必须有终止递归调用的条件 递归调用的两个阶段:

第一阶段:递推。将原问题不断分解为新的子问题,逐渐从未知向已知递推

第二阶段:回归。从已知条件出发,按照递推的逆过程,逐一求值回归,最后达到递归的开始处,结束回归阶段,完成递归调用。

第三节 变量的作用域

在函数或者类内说明的变量是局部变量。局部变量仅在定义它的函数或类内起作用,在这个范围之外不能使用这些变量。

局部变量的作用域也称为块作用域。

函数内部使用的局部变量包括形式参数和函数体内定义的变量。

函数的形式参数的作用域在函数的函数体内部。不同函数如果使用相同的参数或变量,它们仅在其所在函数体内有效,互不影响。

在函数体内定义的变量,其作用域从说明语句开始直到该函数结束为止。 全局变量:

全局变量是在函数和类外部定义的变量。全局变量的作用域从说明点开始直到文件结束。这种作用域也称为文件作用域。

全局变量一般集中在主函数之前说明。 优点:可以减少参数数量和数据传递时间。 缺点:过多的全局变量会降低程序的通用性和程序的可读性,并且全局变量在程序运行过程中始终占用内存

应尽量减少使用全局变量。

如果全局变量与函数的局部变量同名,在函数的局部变量的作用域内,同名的全局变量

30

无效。为了在函数体内使用与局部变量同名的全局变量,应在全局变量前使用作用域作用符“::”。

【例3.6】全局变量和局部变量的使用。 #include int i=3; //定义了全局变量i void main() { double i=2.2; //定义了全局变量i cout<<\"局部变量 i是 \"<程序执行结果为: 局部变量 i是2.2 全局变量 i是3

在程序编译时,编译器将程序中出现的内联函数的调用表达式用内联函数的函数体进行替换。

优点:加快了程序的执行速度 缺点:会增加程序代码的长度。

第四节 内联函数

内联函数必须在程序开头声明。

在C++中,除了带有循环语句、switch语句的函数不能被说明为内联函数外,都可以被说明为内联函数。

内联函数的定义形式为:

inline 类型 函数名(形式参数列表) 【例3.7】利用内联函数计算圆的面积。 #include

inline double sum(double radius) //定义内联函数,计算圆的面积 { return 3.14*radius*radius; }

void main() { double area,r; cout<<\"请输入半径值:\"<>r; area=sum(r); //调用内联函数求圆的面积,编译时此处被替换为sum函数体语句 cout<<\"园的面积为:\"<程序执行结果为: 请输入半径值: 2.5

园的面积为:19.625

31

第五节 函数重载

函数重载是指同一个函数名可以对应着多个不同函数的实现。 函数重载要求编译器能够唯一地确定调用一个函数时应执行哪个函数代码。确定函数时,编译器是通过函数的参数个数、参数类型和参数顺序来区分的。也就是说,进行函数重载时,要求同名函数参数个数不同、参数类型不同或参数顺序不同。 注意:函数的返回类型不能区分不同的函数体。 【例3.8】求三个操作数之和。 #include \"iostream.h\" int sum(int,int,int);

double sum(double,double,double); void main() { cout<<\"Int:\"<int sum(int a,int b,int c) { return a+b+c; }

double sum(double a,double b,double c) { return a+b+c; }

程序执行结果为: Int:9

Double:7.9

在函数的声明或定义中可以预先给出默认的形参值,调用时如给出实参,则采用实参值,否则采用预先给出的形参值。

第六节 带默认参数值的函数

在C++中可以为函数指定默认的形参值,在函数调用时,按从左到右的顺序将实参和形参结合,若参数不够,用函数的默认参数来补足缺少的实参。 默认形参值必须由右向左的顺序定义。如果某个参数有默认值,则其右边的参数必须都有默认值;如果某个参数没有默认值,则其左边的参数都不能有默认值。如: int fun(int a,int b,int c=3); //正确 int fun(int a=1,int b=2,int c); //错误 在使用带默认参数的函数时,只能在函数定义或声明中的一个位置给出默认值,不能在两个位置同时给出

【例3.9】利用带默认参数值的函数求x的n次方(n是正整数)。 #include

double power(double x=10.0,int n=2);

32

void main() { cout<double power(double x,int n) { int i; double s=1.0; for(i=1;i<=n;i++) { s*=x; } return s; }

程序执行结果为: 16 4 100 return

第七节 C++的系统函数

C++系统提供了很多常用的系统函数,为程序员的使用带来了很大的方便。C++将所提供的系统函数的说明分别放在不同的头文件中,即.h文件。在程序中可以使用系统函数,但是要在程序开始处说明函数所在的头文件名。 常用的头文件有:

bios.h BIOS中断 complex.h C++的复数

conio.h 操纵台和I/O端口 ctype.h 字符函数 dos.h DOS中断 graphics.h 图形例程

io.h 文件处理和低级I/O iostream.h C++的流例程 stdio.h C的流例程 stdlib.h 标准库例程

string.h 字符串处理函数 time.h 日期和时间例程

在使用系统函数时,要注意以下几点:

⑴不同的C++编译系统提供的系统函数不完全相同,要了解所使用的C++系统提供了哪些系统函数。

⑵清楚所使用的系统函数的说明在哪个头文件中。

33

⑶调用一个系统函数时,一定熟悉该函数的功能、参数的类型、参数的意义和返回值类型。 return

作业

教材P63-64所有习题

第4章 数组

本章课时:

12课时

本章重点:: 一维数组的使用 二位数组的使用 字符数组的使用 本章难点: 二位数组的使用 教学内容及目标:

了解:

数组的适用范围 理解:

1.一维数组和二维数组的初始化 2.字符串存储和字符串的访问 掌握:

1.一维数组和二维数组的定义和访问方式

2.指针数组的使用:指向基本数据类型的指针数组,指向数组的指针数组,指向函数的指针数组

3.数组作函数参数的应用:向函数传送数组元素,数组名作函数参数 4.字符数组与字符串的使用

第一节 一维数组的定义和数组元素的引用

把若干个同类型的数据线性的组合在一起,就构成一维数组。在使用一维数组之前必须先定义。定义一维数组的一般格式为:

数据类型 数组名[常量表达式]; 例如: int A[100]; float b[20];

在定义一维数组时要注意以下几点:

1.数据类型一般指的是该数组元素的类型。

2.常量表达式必须用方括号括起来,指的是数组的元素个数,即数组长度,可以是常数或符号常量,但不能包含变量。

例如:int a[]; //不合法

34

int a[x]; //不合法。 3.数组元素的下标从0开始

4.一次可以说明多个同类型数组。

例如:int a[10],b[15],c[20]; //定义a,b,c三个整型数组。 注意区别下列语句:

int A(100); //定义了一个整型变量A,并赋予初值为100 int A[100]; //定义了一个整型数组变量A,数组长度为100 一维数组的初始化:

一维数组的初始化格式为:

数据类型 数组名[常量表达式]={初始化列表}; 例如:int a[5]={0,1,2,3,4}; 说明:

⑴在定义数组时既可以对所有元素进行初始化,也可以只对其中的一部分元素进行初始化。例如:int a[4]={7,8}对前两个元素]赋值,其余默认为0。 return

⑵要使一个数组中全部元素的值为0,可以有如下定义方法: int a[4]={ }; int a[4]={0,0,0,0}; int a[4]={0}; ⑶全部数组元素赋初始值时,可以不指定数组长度。

例如:int a[]={1,2,3,4,5}语句表示数组的长度为5。 ⑷利用for循环语句赋初始值。 例如:for(int i=0;i<100;i++) a[i]=i+1;

数组元素引用的格式为:数组名[下标]

【例4.1】求出一个数组a[8],使a[i]的值为下标值的平方,然后按 逆序输出。

#include void main() {

int i,a[8];

for (i=0;i<=7;i++)

a[i]=i*i; //利用for语句给每个数组元素赋初值。 for (i=7;i>=0;i--)

cout<运行结果如下:

49 36 25 16 9 4 1 0 一维数组元素的存储:

一维数组各元素在内存中是连续存储的,例如定义数组:short a[4]={1,2,3,4}; 假设数组存储的首地址为2000,则该数组在内存中的存储情况如图4-1所示。

200020012002200320041a[0]23a[1]a[2]35

另外,数组名就代表数组在内存中的首地址,例如上面的数组a就代表首地址,它是一个地址常量,可以用a+i的形式来依次引用其他元素的地址。 注意:a+n代表的不是加n个字节,而是加n个数据的存储单位。

【例4.2】从键盘上输入任意4个整数赋给数组,显示该数组,最后计算并显示该数组的累加和与平均值。 #include void main() {

int a[4],i,sum=0; //声明数组和变量 double avg;

for (i=0;i<4;i++) {

cout<<\"a[\"<>a[i];

} //直接显示数组元素

cout<for (i=0;i<4;i++) //利用for循环显示数组元素的值 cout<sum=a[0]+a[1]+a[2]+a[3]; //计算数组元素之和,并显示计算结果 cout<<\"sum=\"<for (i=0;i<4;i++)

sum=a[i]+sum; //利用for循环语句求和。 cout<<\"sum=\"<cout<<\"avg=\"<运行结果为:

36

a[0]=1 a[1]=3 a[2]=5 a[3]=7

1 3 5 7 1 3 5 7 sum=16 sum=16 avg=4

第二节 二维数组的定义和数组元素的引用

二维数组定义的一般形式为:

数组类型 数组名[常量表达式1][常量表达式2];

可以把二维数组看作特殊的一维数组,它的元素又是一个一维数组。例如,可以把a[4][3]看作是一个一维数组,它有4个元素:a[0],a[1],a[2],a[3],每个元素又是一个包含3个元素的一维数组,即该数组有4行3列共12个元素,如图4-2所示。在C++语言中,二维数组是按行的顺序存储的。

根据初始化列表的不同,二维数组元素的初始化方法也不同,常用的有以下几种方法: (1)对二维数组元素赋初值,以每行为一组,分行初始化。 例如,int a[4][3]={{0,1,2},{3,4,5},{6,7,8},{9,10,11}}; 例如 , int a[4][3]={{0,1},{},{0,0,2},{0,1}} 例如,a[4][3]={{1},{5},{6},{7}} 注意:省略元素赋值为0

(2)所有的数据写在一个花括弧内,按存储顺序赋值。

例如,int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11},则a[1][1]=5。 例如,int a[4][3]={0,1,2,3,4,5,6,7,8,9,10,11},则a[3][2]=11。 (3)若采用第二种方法,可以省略第一维的长度。 例如,int a[2][3]={1,2,3,4,5,6}可以写成 int a[ ][3]={1,2,3,4,5,6}。

(4)二维数组的元素赋初始值,可用二重循环语句。 例如,for(int i=0;i<4;i++)

for(int j=0;j<4;j++) a[i][j]=i+j; 引用二维数组元素的格式为:

数组名 [行下标][列下标]

例如,int a[2][3]定义了一个2行3列的整数数组,如引用其中的第2行、第1列元素应写为a[1][0]。 注意:

不要把int a[3][2] 写成int a[3,2]。

下标值要在已定义的数组的最大范围内,即不要越界。 【例4.4】已知4名学生的数理化成绩分别为{78,85,79}、{63,72,70}、{86,78,93}、74,63,77},求出并显示每个学生的平均成绩及总的平均成绩。

37

#include void main( ) { float sum=0,d[4][3]={{78,85,79}, {63,72,70},{86,78,93},{74,63,77}}; float c[4]={0}; for(int i=0;i<4;i++) {

for(int j=0;j<3;j++) c[i]+=d[i][j]; //求每名学生的总成绩 cout<cout<程序的执行结果为:

80.6667 68.3333 85.6667 71.3333 76.5 return

第三节 字符数组的定义及初始化

字符数组定义的格式为:char 数组名[n]; 字符数组的初始化一般有如下两种方法: ⑴逐个字符赋给数组中的元素。

【例4.5】逐个字符初始化字符数组。 #include void main() {

char a[13]={'H','e','l','l','o',',','W','o','r','l','d','!'}; cout<注意:如果花括弧中提供的初值字符个数大于数组长度,则作语法错误 处理,如果初值个数小于数组长度,则多余的数组元素自动定义为字符 串结束符‘\\0’。

⑵对整个字符数组赋初值。

例如:char a[13]= \"Hello,World!\"; 运行程序,输出结果为: Hello,World! d

编译系统提供的字符串处理函数放在string.h头文件中,在调用字符串处理函数时,要包含string.h头文件。

1.字符串拷贝函数strcpy() 格式:strcpy(str1, str2);

38

该函数的功能是将str2所指向的字符串复制到str1所指向的字符数组中,然后返回str1的地址值。

2.字符串连接函数strcat() 格式:strcat(str1, str2);

该函数的功能是将str2所指向的字符串连接到str1所指向的字符数组中。然后返回str1的地址值。 注意:

以上两个函数都要保证str1的空间足够大。

两个字符数组连接后,则前一个数组的结束字符'\\0'消失了。

3.字符串比较函数strcmp():功能是从左到右比较两个字符串的大小(按ASCII码值大小比较),直到出现不同的字符或遇到‘\\0’为止。如果两个字符串中全部字符串都相同,则认为两个字符串相等;若出现不相同的字符,则以第一个不相同的字符的比较结果为准,比较的结果由函数值带回。

⑴如果字符串1和字符串2完全相同,函数值为0; ⑵如果字符串1大于字符串2,函数值为1; ⑶如果字符串1小于字符串2,函数值为-1。 格式:strcmp(str1, str2);

4.字符串长度函数strlen():该函数的功能是计算字符串 的长度。

格式:strlen(str);

该函数将计算str所指向字符串的长度,函数值为字符 的实际长度,而不是分配的空间。例如: char str[10]={ \"Good! \" } cout<输出的结果为5,不是6,也不是10。 【例4.7】字符串处理函数的使用。 #include \"iostream.h\" #include \"string.h\" void main() { char stra[50]=\"china\"; char strb[]=\"Beijing\"; char strc[]=\"Shanghai\"; cout<strcpy(stra,strb); //字符串复制 cout<strcat(stra,strc); //字符串连接 cout<程序执行结果为: china Beijing Beijing Beijing

BeijingShanghai Shanghai x1=-1 x2= 0

39

x3= 1

BeijingShanghai length is: 15 return

int x1,x2,x3;

x1=strcmp(\"China\ //字符串比较 x2=strcmp(\"China\ //字符串比较 x3=strcmp(\"China\ //字符串比较 cout<< \"x1= \"<cout<【例4.8】编程求出一个二维字符数组里为'a'的元素个数。 #include #include

void reada(char a[5][4]); void main() {

char a[5][4]; int i ,j,number=0; reada(a);

for(i=0;i<5;i++) for(j=0;j<4;j++) {

if(a[i][j]!='a') continue; number++; }

cout<<\"这个字符串中有:\"<void reada(char a[5][4]) { int i,j;

cout<<\"请输入字符串:\"<>a[i][j]; }

程序的执行结果为: 请输入字符串: sfdsgfaahsfyhsfdahdg 这个字符串中有:3个a return

作业

40

教材P77-78所有习题

第5章 结构体和共用体

本章课时:

8课时

本章重点: 结构体变量的定义 结构体的定义 本章难点: 结构体变量的定义 教学内容及目标:

了解:

结构体和共用体的适用范围和区别 理解:

1.结构体变量与共用体变量的初始化 2.字符串存储和字符串的访问 掌握:

1.结构体和共用体的定义

2.结构体变量和共用体变量的访问 3.结构体数组的使用

第一节 结构体

结构体的定义

结构体定义的一般语法形式为: struct 结构体名 { 数据类型 成员1; 数据类型 成员2; ┇ 数据类型 成员n; };

例如:

struct student //定义名为student(学生)的结构体{ long number; //学号 char name[10]; //姓名 char sex; //性别

41

float shuxue; //数学 float yingyu; //英语 float yuwen; //语文 };

1.结构体的定义仅仅是给出了该结构体的组成情况,系统并不为其分配实际的存储单元,为了使用它,必须定义结构体变量。

2.存储空间的大小是结构体中各成员变量所占空间大小的总和。 结构体变量的定义

定义结构体变量可采用以下3种形式: 1.直接定义

直接定义是指在定义结构体的同时定义结构体变量。例如: struct worker { char name[10]; //工人姓名 float salary; //工人工资 } worker1,worker2;

该例在定义结构体worker的同时,定义了两个worker类型的结构 体变量worker1和worker2。 2.间接定义

间接定义是指先定义结构体,然后再定义结构体变量。例如: struct worker { char name[10]; //工人姓名 float salary; //工人工资 };

struct worker worker1,worker2;

注意:在C语言中使用间接方式定义结构体变量时,struct关键字 仍然要写,而在C++语言中则可以不写struct关键字。 3.无名定义

当采用直接方式定义结构体变量时,可以省略结构体名。例如: struct { char name[10]; //工人姓名 float salary; //工人工资 } worker1,worker2;

注意:无名定义由于省略了结构体名,因此以后不能再用这种结构体类型定义其它结构体变量。

在定义结构体变量的同时可以对结构体变量进行初始化。其语法格式为: struct 结构体名 结构体变量名={初值};

其中,初值的数目、顺序和类型均应与定义结构体时成员的数目、顺序和类型保持一致。例如:

struct student zhangfan={53101,\"zhang fan\结构体变量的使用:

结构体变量一般不能作为一个整体进行输入/输出,可以通过结构体变量的成员来访问它。

42

使用结构体变量的语法格式为:

结构体变量.成员名

对结构体中的成员可以像一般变量一样进行各种运算。例如: zhangfan.number = 53101; //结构体变量的成员被赋值 zhangfan.sex ='m';

注意:字符串型不能直接赋值。

除了上述情况以外,在下述情况下结构体或结构体变量也可以作为 整体参与运算:

sizeof(struct student); //计算结构体或变量所占内存大小

zhangfan=liying; //同类型的结构体变量可作为一个整体赋值

【例5.1】设计一个“学生”结构体,包括姓名、性别、年龄、地址等成 员。然后定义结构体变量并进行初始化,输出显示结果。 #include #include struct student { char name[10]; char sex[3]; int age; char adderss[100]; };

struct student stu1={\"李明\男\北京市\void main() { cout<cout<程序运行后,输出结果为: 李明 男 22 北京市 王芳 女 20 天津市

如果数组中的每个元素都是一个结构体变量,则称这样的数组为“结构体数组”。 1.结构体数组的定义

与定义结构体变量一样,结构体数组可以采用3种定义方式:直接定义、间接定义和无名定义。例如: struct worker { char name[10]; float salary;

}workers[2]; //直接定义

43

struct worker { char name[10]; float salary; };

worker workers[2]; //间接定义 struct { char name[10]; float salary;

}workers[2]; //无名定义

例如,要引用结构体数组workers中的第2个元素的成员name,可表示为workers[1].name。 结构体数组元素的成员和普通变量一样,可以被赋值,也可以参加各种运算。例如: strcpy(workers[1].name, \"li ming\"); workers[1].salary=300; 2.结构体数组的初始化

结构体数组初始化的一般形式为:

struct 结构体名 结构体数组名[ ]={初值}; 例如: struct worker { char name[10]; float salary;

}workers[2]={{\"li ming\数组元素个数可以省略。

【例5.2】在结构体数组中查找工资值最大的记录。 #include struct person { char name[10]; bool sex; int age; float salary; };

struct person a[4]={{\"李明\380},{\"王强\刘刚\王霞\void output(int n) { cout<<\"显示具有person结构的\"<44

cout<<\"男\"<<' '; else cout<<\"女\"<<' '; cout<void find(int n) { int k=0; //k表示当前具有最大工资值的元素下标 float x=a[0].salary; for(int i=1;ix) { x=a[i].salary; k=i; } } cout<void main() { output(4); find(4); }

运行程序,输出结果为:

显示具有person结构的4个记录 李明 男 22 380 王强 男 34 560 刘刚 男 28 450 王霞 女 26 480

显示数组a中具有最大工资值的记录: 王强 男 34 560

第二节 共用体

共用体可以看成是结构体的变种,其定义和使用方式都与结构体极其相似。共用体、共用体变量的定义形式为:

45

union 共用体名 {

数据类型 成员1; 数据类型 成员2; ┇

数据类型 成员n }变量列表; 例如: union example { int x; char y; double z; }a,b;

如果将上例定义成结构体,例如: struct example { int x; char y; double z; }a,b;

结构体与共用体的区别:

1.变量空间不同,前者为各成员空间之和,后者为最大成员所占空间。 2.初始化不同,前者可以对各成员初始化,后者只能对第一成员初始化。

3.成员访问不同,前者可以同时访问每个成员,后者同一时刻只存在一个成员。 return

与结构体同,一般不做整体运算,成员访问仍然通过成员运算符“.”进行。在下述情况下可以对共用体或共用体变量进行整体引用:

取地址运算、sizeof运算、同类型共用体变量之间的赋值 使用共用体时应注意以下几点:

⑴因为共用体成员采用的是覆盖技术,因此,每一时刻共用体变量只有一个成员起作用 ⑵共用体变量的地址和它的各成员的地址都是同一地址。

⑶在定义共用体变量时可以进行初始化,但只能对共用体变量的第一个成员进行初始化。 ⑷共用体可作为结构体成员,结构体也可作为共用体成员,也可定义共用体数组。 【例5.3】共用体变量的使用。 #include union data { char c_data; short s_data; long l_data; };

void main() {

46

data x; x.c_data='m';

cout<< \"c_data=\"<< x.c_data <cout<< \"s_data=\"<< x.s_data <cout<< \"l_data=\"<< x.l_data <运行程序,输出结果为: c_data=m s_data=10 l_data=100 return

作业

教材P90-91所有习题

第6章 指针和引用

本章课时:

8课时

本章重点: 指针在数组中的应用 指针在字符串中的应用 本章难点: 二级指针 教学内容及目标:

了解:

多级指针和指针运算 理解:

1.new和delete的使用 2.引用的定义 掌握:

1.指针的定义和访问方式

2.指针数组的使用:指向基本数据类型的指针数组,指向数组的指针数组,指向函数的指针数组

3.引用作为函数参数和作为函数返回值的作用

第一节 指针

通常,系统对每个存储单元按其顺序进行编号,编号能唯一地确定任何一个字节的位置,于

47

是编号被形象地称为地址。 因为地址指示了字节在存储器中的位置,所以地址也被形象地称为指针(pointer)。所谓指针是一个存储单元的地址值,用来存放地址(即指针)的变量也称指针变量。在上下文意义明确的情况下,常常将指针变量也简称为指针。

1.指针的声明

指针是一个变量,必须先声明后使用。指针声明的一般形式如下: 数据类型 * 标识符;

其中,标识符给出的是指针变量名,“*”号说明其后的标识符是一个指针变量,数据类型可以是C++语言中任一合法的类型。比如: int *p1; //声明p1指向int型变量 double *p2; // 声明p2指向double型变量

在C++语言中定义指针变量时,以下形式均是合法的: int* p //*靠左

double * q //*两边都不靠

2.指针变量运算符 ⑴ 取地址运算符&

既然指针变量是用来存放地址的变量,就可以通过取地址运算符&,将某一变量的地址赋值给指针变量。例如: int a=2,*p; p=&a;

上面的语句定义了整型变量a和指向a的指针变量p,若变量a的地址为0x00347FDF,则通过取地址运算符&将变量a的地址赋值给指针变量p,此时指针变量p的内容为变量a的地址0x00347FDF,如图6-1所示。 ⑵间接访问运算符* 该运算符也称“指针运算符”或“取内容运算符”,它后面必须是一个指针变量。 例如:

int i=1,*p=&i; cout<<*p;

其中第2条语句将输出变量i的值1。当然,在利用指针访问变量的值时,也可以给变量赋值,比如

int i=1,*p=&i; *p=2; cout<<*p;

将在屏幕上输出2。

【例6.1】指针的各种表示形式及其含义。 #include void main() {

int a=10,*p; p=&a; *p=15;

cout<<\"a=\"<48

cout<<\"p=\"<运行程序,输出显示结果: a=15

p=0x0012FF7C &a=0x0012FF7C *p=15

&p=0x0012FF78 3.指针的初始化

如果用户声明了一个指针变量,在使用该指针变量之前必须对它赋初值。否则,在程序中使用该指针变量就有可能导致系统崩溃。

int i,*p1=&i; //将指针变量p1的值初始化为变量i的地址

int *p2=0; //值为0或NULL的指针表示该指针不指向任何数据,又称空指针 为使用安全起见,最好在声明指针变量时就进行初始化,即使是初始化为空指针也可以。如果在声明指针变量时,指针初始化为0或根本没有初始化,在使用前就必须给它赋予有意义的值。

由于数组名表示的是该数组的首地址值。因此,如果声明指针变量指向一个数组,则可以使用下述赋值方法:

int x[5],*p1=x; 或者 int x[5], *p1=&x[0]; 如果需要声明多个指针指向同一变量,我们可以采取下述方法,用这个变量来给这些指针逐个赋值。比如: int i,*p1=&i; int *p2=p1;

就使得指针p1和p2指向同一变量i的内存地址。 【例6.2】分析下面程序的运行结果。 #include void main() {

int i=1,*p1=&i; int *p2=p1;

cout<<\"p1=\"<程序的输出结果为:

p1=0x0012FF7C,p2=0x0012FF7C

下面,我们来看一些对指针的错误赋值。

int i,*p1=i; //错误,不能给指针赋变量本身的值 int *p2;

*p2=2; //错误,指针p2没有初始化

注意:在使用指针前,必须先对它进行合法的初始化。

double *p2=&i; //错误,不能用不同类型变量的地址来给指针赋值, 如果确实需要用不同类型变量的地址给指针赋值,就应该采用强制类型转换。例如:

49

double *p2=(double *)&i; 4.指针的运算 ⑴赋值运算

指针的赋值运算可以通过指针的初始化实现,也可以在程序中通过赋值语句来实现。 ⑵算术运算

指针可以和整数进行加减运算,包括增1和减1运算,其实质是地址的运算。 ⑶关系运算

两个指针进行关系运算时,它们必须指向同一连续存储空间。指针的关系运算一般在指向相同类型变量的指针之间进行,表示它们所指向的变量在内存中的位置关系。例如: int a;

int *p1=&a;*p2=p1;

所声明的两个指针作p1==p2运算,其结果为1(true),即指针p1、p2指向同一个变量。

5.多级指针 可以声明一个指针来指向指针,这个指针称为指向指针的指针,即二级指针。 声明二级指针的格式为:数据类型 ** 标识符

其中,两个“*”号表示二级指针,标识符为二级指针的名字,数据类型是指通过两次间接寻址后所访问的变量的类型。例如: int i,*p1=&i; int **p2=&p;

p2就是二级指针,它指向指针变量p1。

【例6.3】二级指针的使用。 #include void main() { int i; int *p1=&i,**p2=&p1; //声明二级指针p2 i=1; cout<<\"i=\"<运行程序,输出结果为: i=1 *p1=1

p1=0x0012FF7C *p2=0x0012FF7C p2=0x0012FF78

50

**p2=1 return

指针与数组:

1.用指针访问数组元素

对一维数组来说,指向数组的指针变量与指向数组元素的指针变量 的定义方法都与普通变量的指针的定义方法一样。例如: int x[5],*p1; //定义数组x及指针变量p1

p1=x; //将数组的起始地址赋给指针变量p1,使p1指向数组x, 数组名x代表数组的起始地址,实际上就是指向第一个元素x[0]的指针,*x表示的就是元素x[0]的值,而*(x+2)则表示元素x[2]的值。

【例6.4】通过数组名访问数组元素。 #include void main() {

int x[5]={1,2,3,4,5};

for(int i=0;i<5;i++) //利用下标法输出数组元素 {

cout<cout<for(i=0;i<5;i++) //利用数组名输出数组元素 {

cout<<*(x+i)<<'\'; }

cout<运行程序,将输出结果: 1 2 3 4 5 1 2 3 4 5

【例6.5】利用指向数组某个元素的指针访问数组中的每个元素。 #include void main() { int x[5]; int *p=x; //声明指针,指向数组的第一个元素 for(i=0;i<5;i++) //利用指向数组的指针给数组元素赋值 { *p++=2*i; } p=x; for(i=0;i<5;i++) { cout<<*p++<<'\';

51

} cout<运行程序,将输出结果: 0 2 4 6 8

数组元素的访问,既可用下标法,也可用指针法。下标法简单直观,指针法在采用指针变量的自增或自减运算时,

能使目标程序短,运行速度快。如果要访问一维数组的第i+1 个元素,则下标法和指针法分别为: ⑴下标法

数组名下标法:x[i]。 指针变量下标法:p[i]。 ⑵指针法

数组名指针法:x+i表示数组元素x[i]的地址,*(x+i)表示数组元素x[i]。 指针变量指针法:p+i表示数组元素x[i]的地址,*(p+i)表示数组元素x[i]。 在使用指向一维数组的指针变量时,要注意以下几点: ⑴p+i并不是简单地使指针变量的值加上I

⑵利用指针对数组进行操作时,必须注意越界问题。比如: int x[5];

int *p=x; //指针p指向数组x的首地址 p=p+5; *p=10;

⑶可以通过改变指针变量本身值的方法(如p++)来指向不同的数组元素,但是数组名表示数组的起始地址,是一个地址常量,是不能改变的,如写成x++就是错误的。 ⑷要注意指针变量的当前值。 2.指针数组

由指针组成的数组称为指针数组,即数组的每一个元素都是指针。指针数组常用于指向多个字符串,使字符串处理更加方便灵活。 声明指针数组的一般格式如下:

数据类型 *数组名[常量表达式1][常量表达式2]…; 例如:

int *p1[6];

double *p2[3][4];

就分别声明了含有6个元素的一维int型指针数组p1和含有12个元素的二维double型指针数组p2。

【例6.6】指针数组的使用。 #include void main() {

int x[2][3]={{1,2,3},{4,5,6}}; int i,j;

int *p[2]={x[0],x[1]}; //声明指针数组并初始化 for(i=0;i<2;i++) {

52

for(j=0;j<3;j++) { cout<<*(p[i]+j)<<'\'; //利用指针数组输出其指向的元素的值 }

cout<运行程序,将输出结果: 1 2 3 4 5 6 3.数组指针

数组指针就是一个指向数组的指针,其声明格式如下: 数据类型 (*指针名)[常量表达式1][常量表达式2]…; 其中,(*指针名)中的圆括号不能省略,原因在于方括号[ ]的优先级别比*高。例如: int (*p)[5];

该语句声明了一个指向具有5个元素的int型数组的指针。如果省略圆括号(),则编译器将把上面的语句解释为: int *(p[5]);

这显然不符合程序设计的初衷。

【例6.7】利用数组指针改写例6.6。 #include void main() { int x[2][3]={{1,2,3},{4,5,6}}; int i,j; int (*p)[3]=x; for(i=0;i<2;i++) { for(j=0;j<3;j++) { cout<指针与字符串:

在C++语言中,字符串被表示成一个字符数组。由于字符串中的每 一个字符对应字符数组中的一个数组元素,故用户可以利用指针指向

字符数组中的任何一个数组元素,即指向字符串中的任何一个字符。在C++语言中,字符串既可以用字符数组表示,也可以用字符指针 变量来表示。

用户可以在定义字符数组的同时进行初始化。

C++规定:字符数组的最后一个元素必须是‘\\0’字符。

53

引用字符串时,既可以逐个字符引用,也可以作为一个整体引 用。

【例6.8】分析下面程序的运行结果。 #include #include void main() { char a[]=\"01234\ char *sa=a,*sb=b; for(int i=0;i<5;i++) *sa++=*sb++; cout<运行程序,输出结果为: 56789 56789

【例6.9】将字符串中的小写字母转换为大写字母。 #include void main() { char string[]=\"good morning!\"; cout<<\"转换前字符串为:\"<='a'&&*s<='z') *s-=32; ++s; } cout<<\"转换后字符串为:\"<运行程序,输出结果为:

转换前字符串为:good morning!

转换后字符串为:GOOD MORING! 指针与函数:

1.指针作为函数的参数

【例6.10】利用指针作为函数参数交换实参变量的值。 #include void swap(int *a,int *b); void main() { int x=1,y=2; cout<<\"交换前\"<54

cout<<\"x=\"<void swap(int *a,int *b) { int temp; temp=*a; *a=*b; *b=temp; }

运行程序,输出结果: 交换前 x=1,y=2 交换后 x=2,y=1

2.数组作为函数的参数

【例6.11】将一个数组中的元素前后逆置。#include

void transpose(int x[],int n); void main() { int a[6]={1,2,3,4,5,6}; int i; cout<<\"原数组:\"; for(i=0;i<6;i++) cout<<'\'<void transpose(int x[],int n) { int temp,i; for(i=0;i55

}

运行程序,将输出结果:

原数组:1 2 3 4 5 6 逆置后:6 5 4 3 2 1

【例6.12】用选择排序法把n个整数按从大到小的顺序排列。 #include #define n 8

void sort(int x[],int m); void main() { int a[n],i; cout<<\"请输入要排序的8个整数\"<>a[i]; //从键盘输入要排序的数据 sort(a,n); //用选择排序法实现降序排列 cout<<\"排序结果为\"<void sort(int x[],int m) { int i,j,k,t; for(i=0;ix[k]) k=j; //存在更大元素,保存其下标 if(k!=i) { t=x[i]; //交换位置 x[i]=x[k]; x[k]=t; } } }

运行程序,输出结果为: 请输入要排序的8个整数 23 35 56 45 26 4 9 17 排序结果为

56 45 35 26 23 17 9 4 动态内存分配:

所谓动态内存分配是指在程序运行期间根据实际需要随时申请内存,并在不需要时释放,它实际是一种在程序运行时动态申请和释放内存的技术。

56

应用程序数据所占的内存可以分为3类:静态存储区、栈和堆 静态存储区: 在程序运行开始前就分配. 栈: 局部变量

堆: 也称为自由存储单元,动态内存分配就是在堆中进行的。 1.运算符new

运算符new用于申请所需的内存单元。它的使用格式如下: <数据类型> *<指针变量 > = new <数据类型>; 若分配成功,则返回其首地址;否则,返回一个空指针。new返回的内存地址必须赋给指针。

2.运算符delete

当程序中不再需要使用运算符new申请到的某个内存单元时,就必须用运算符delete释放它。这一操作的表述形式如下:

delete 指针名; //释放非数组内存单元 delete[] 指针名; //释放数组内存单元 注意,在这一操作中,指针本身并不被删除,必要时可以重新赋值。 【例6.13】动态内存分配的演示。 #include #include void main() { int *p=new int; //动态申请内存 if(p==0) //检查内存分配是否成功 { cout<<\"Error,Menory allocation failure!\"<运行程序,输出结果为: *p=10 *p=20

57

第二节 引用

引用的概念:

在C++语言中,提供了一种为变量起一个别名的机制,这个别名就是引用。声明引用的过程也就是为某个变量建立别名的过程。 引用声明的一般格式如下:

数据类型 &引用名=变量名; 或

数据类型 &引用名(变量名);

其中,数据类型是指被引用变量的类型,变量名是被引用变 量的名字,“&”是引用运算,被引用的变量可以是任一类型的变 量。例如:int a;

int &b=a; //为int型变量a声明了一个引用b 使用引用应注意以下几点:

⑴声明引用时,除了引用作为函数参数或返回引用的函数这两种情况外,必须要初始化。因此,赋值运算符右边的变量必须是已存在的变量。

⑵一旦为一个变量声明了一个引用,该引用就不能再作为别的变量的引用。 ⑶引用和其所代表的变量使用同一片存储空间,它并不另外占用存储空间。 ⑷&”出现在赋值运算符的左边或函数形参表中时,是“引用”,否则为取地址。 【例6.14】引用的声明和使用。 #include void main() { int a=1; int &b=a; //b是变量a的引用 cout<<\"a=\"<运行程序,将输出结果: a=1 b=1 a=2 b=2

&a=0x0012F7C &b=0x0012F7C return

1.引用作为函数参数

【例6.15】利用引用作为函数参数改写例6.10的程序。 #include

58

void swap(int &a,int &b); void main() { int x=1,y=2; cout<<\"交换前\"<void swap(int &a,int &b) { int temp; temp=a; a=b; b=temp; }

运行程序,输出结果与例6.10完全一样。由此可以看出,通过 引用作为函数参数,被调用函数可以改变主调函数中实参的值,引 用调用完全可以实现传址调用的功能,而且使用起来像普通变量一 样,维护也非常方便。 2.返回引用的函数

函数的返回值可以是引用,其一般形式为: 数据类型 &函数名(形参表)

若函数的返回值类型为引用,可以通过对函数赋值,实现对函数返 回的引用的赋值。

注意:在使用返回引用的函数时,return语句的返回值通常为全局变量或静态变量,否则有可能当函数调用结束时,变量的作用域消失,从 而造成错误。

由于指针可以实现的功能,大部分都能用引用替代,而且引用更容 易使用,更清晰,故用户在编程时,应该多使用引用,少使用指针。不 过指针能实现引用的全部功能,但引用却无法完全替代指针,原因为: ⑴首先,引用不可以是空引用,但指针却可以是空指针。引用空对象在 程序中是错误的,有可能导致严重的后果。因此,如果对象有可能为空 时,就必须采用指针。

⑵其次,引用是常量,不能重新赋值。如果程序需要先指向一个对象, 后又指向另一对象,此时应该采用指针。

作业

教材P111-112所有习题。

59

因篇幅问题不能全部显示,请点此查看更多更全内容

Top