已阅读5页,还剩321页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C+应用与开发案例教程(上),第1章 引言,在20世纪70年代后期,由于应用程序的规模变得越来越大,程序的复杂性也越来越难以控制。为了满足管理程序复杂性的需要,1980年,贝尔实验室的Bjarne Stroustrup开始对C进行改进和扩充。最初的成果称为“带类的C”,1983年正式取名为C+,在经历了3次修改后,于1994年制定了ANSI C+标准草案。由于C+是建立在C的基础之上的,所以它包括了C的全部特征、属性和优点,同时它还支持面向对象的编程。 C+是一种面向对象的程序设计语言,使用它可以实现面向对象的程序设计。面向对象的设计与面向过程的设计是有很大区别的,面向对象的程序设计是在面向过程的程序设计的基础上一个质的飞跃。要学会面向对象的程序设计,首先要学会一种支持面向对象的语言,而C+语言就是其中的一种。目前C+已经被应用于程序设计的众多应用领域中,它尤其适用于中等和大型的程序开发项目。从开发时间、费用到形成的软件,1.1 C+语言概述,1.1 C+语言概述,的可重用性、可扩充性、可维护性和可靠性等方面都显示出了C+语言的优越性。 首次学习面向对象的程序设计语言时,总会碰到一些在传统的面向过程的程序设计语言中从未见到过的概念,如:类、对象、封装、继承、多态性等,而这些都是面向对象语言的基本概念。,1.2 面向对象语言的基本概念,在深入了解和学习面向对象程序设计之前,有必要先简单介绍一下面向对象方法中的几个基本概念。 1.2.1 对象 在现实世界中,对象有两大类。我们身边存在的一切有形事物和抽象概念都是对象。有形事物的例子如一个学生、一辆汽车、一本书、一个工厂、一个书店、一棵树等;抽象概念的例子如学校校规、企业规章等。我们身边发生的一切事件都是对象,例如一场乒乓球比赛、一次寒流侵袭、一次到商场的购物过程、一次到银行的提款过程等。不同的对象具有各自不同的特征和功能。例如,工厂具有工厂的特征和功能、书店具有书店的特征和功能、购物过程具有购物过程的特征和功能、提款过程具有提款过程的特征和功能等。 由此可见,现实世界中的对象具有如下特征: 有一个名字用来唯一标识该对象;,1.2.1 对象,有一组状态用来描述其特征; 有一组操作用来实现其功能。 例如,有一个学生对象,姓名叫李四,性别男,专业为计算机,学历为硕士,可从事计算机软件开发和计算机硬件开发的工作。在这里,李四是这个对象的名字;男性,计算机专业和硕士学历是这个学生的特征;能从事计算机软件开发和计算机硬件开发是这个学生具有的能力(功能)。,1.2.2 类,类是面向对象方法中的另一个重要的概念。在现实世界中,类这个术语是对一组相似对象的抽象描述。例如,作为学生对象,有张三、李四、王五等,每个对象有不同的性别,专业和学历特征,有从事不同行业的能力。而学生类则是对学生这类对象所应具有的共同特征和能力(功能)集合的抽象描述;教师这类对象应具有性别,专业和学历特征,应有从事某种行业的能力。 在面向对象方法中,类是对具有相同属性和相同服务的一组相似对象的抽象,或者说,类所包含的属性和服务描述了一组对象的共有属性和服务。即类是建立某个具体对象时使用的模型或模板。 在面向对象方法中,程序设计的主体是类。类是相同属性和服务的封装体,因此类具有模块性;类是对具有相同属性和服务的一个或多个对象的抽象描述,因此类具有抽象性;子类,1.2.2 类,可以在继承父类所有属性和服务的基础上,再增加自己特有的属性和服务,因此类具有继承性。类的这种模块性和抽象性,使面向对象方法设计的模块较传统方法设计的模块具有更好的可重用性;类的这种继承性使面向对象方法设计的软件系统的可维护性和系统升级能力得到大大的提高。,1.2.3 封装,类是对具有相同特征的客观对象的抽象描述,它将抽象出来的数据和操作行为封装在类中。在类中将一部分行为作为对外部的接口,将数据和其他行为进行有效的隐藏。用户只需根据对象提供的外部接口访问对象,这就可以达到对数据访问权限的合理控制。 封装具有以下几个特性: (1)一个清楚的边界,所有对象的内部变化范围限制在这个边界内; (2)一个接口,用来描述对象本身和其他对象之间的相互作用; (3)受保护的内部实现,它给出了由软件对象提供的功能细节,在外部不能访问这些细节。,1.2.4 继承,继承是面向对象方法中重要的概念之一。在面向对象方法中,若一个类描述的是一组对象的共性信息,另一个类描述的是一组对象的特性信息,则可以把前一个类定义为父类,后一个类定义为子类。父类通常也称作基类,子类通常也称作派生类。继承是指子类自动继承父类中定义的属性和服务。 面向对象方法中的类的继承性,完全和现实世界中人们描述事物的方法相同。例如,在现实世界中,我们要描述猫、狗、猪、马、羊,由于猫、狗、猪、马、羊都属于哺乳类动物,所以我们可以先定义哺乳类动物。我们把哺乳类动物所共有的特征和习性定义在哺乳类动物中,然后再分别定义猫、狗、猪、马、羊类动物各自特有的特征和习性。由一般到特殊的分类方法是人们总结出的高效率地分类认识世界的方法。 一个系统中所有类按继承关系构成的结构图称作该系统的类层次或类结构。类层次是一个树状结构。从类层次可知,除,1.2.4 继承,一个类层次最根部的类外,所有类的上层可以有父类,下层可以有子类。类层次最根部的类只有子类。 在一个面向对象系统中,当类层次中的所有类只允许有一个父类时,这样的类继承称作单重继承;当类层次中的所有类允许有一个以上的父类时,这样的类继承称为多重继承。 类的继承具有传递性,即如果类C是类B的子类,类B是类A的子类,则类C不仅继承类B的所有属性和服务,还继承类A的所有属性和服务。因此,一个类实际上继承了它所在类层次以上层的全部父类的属性和服务。这样,属于该类的对象也就不仅具有自己的属性和服务,还具有该类的所有父类的属性和服务。 子类会继承基类中的全部属性,但子类对基类中服务的继承方式可分为三种类型: 完全继承,即子类全部继承基类中的所有服务;,1.2.4 继承,修改继承,即子类对基类中的一些服务在继承的基础上做一些补充或修改。修改继承实现的具体方法是在子类中重新设计基类中的这些服务,重新设计的服务将首先执行原先基类中的服务,然后执行补充或修改的服务; 覆盖继承,即在子类中重新设计基类中的这些服务,从而用新的服务覆盖了旧的服务。覆盖继承实现的具体方法是在子类中重新设计基类中的这些服务,重新设计的服务执行作为新的内容的代码。由于系统对对象中服务的查找次序是沿类层次的当前类逐层向上查找的,所以当该对象在当前层查找到了所要的服务(此时为新服务)后,就不再向上层查找以前定义的服务(此时为旧服务)了,从而实现了覆盖继承。 利用继承,特别是修改继承和覆盖继承,使得大型软件的功能修改和功能扩充较传统的方法容易了许多。当要对系统的一些原有功能进行补充和修改时,可以重新设计原先类的一,1.2.4 继承,个子类,利用修改继承方法重新设计子类中要补充和修改的服务;当要废弃系统的一些原有功能,重新设计完全不同的新的功能时,可以重新设计原先类的一个子类,利用覆盖继承方法重新设计子类中要更改的服务;当要对系统添加一些新的功能时,可以重新设计原先类的一子类,并新设计一个新的服务来实现所要添加的新的功能。 对象的继承性是面向对象方法的关键技术。这是因为对象的继承性所构成的对象的层次关系和人类认识客观世界的过程和方法吻合。从而使得人们能够用和认识客观世界一致的方法来设计软件。,1.2.5 多态性,面向对象方法的另外一个基本概念是多态性。所谓多态,是指一个名字有多种语义;或一个相同界面有多种实现。 下面我们来考察多态性问题的一个类比问题。当一汽车司机为避免撞车时刹车,他关心的是快速刹车(效果),而不是关心刹车是鼓式刹车还是盘式刹车(实现方法的细节)。这里,刹车的使用与刹车的结果是分离的概念,可能有多种结构的刹车,它们的使用方法是相同的。相同的使用方法(相同界面)对应于不同种类的刹车结构(多种实现),这反映了多态性的思想。 与此类似,用户在使用函数编程时,他关心的是该函数的功能及其使用界面,并不需要了解该函数的使用界面与函数的哪一种实现方法相匹配。也就是说,在设计这一级上,软件人员只关心“施加在对象上的动作是什么”,而不必关心,1.2.5 多态性,“如何实现这个动作”以及“实现这个动作有多少种方法”的细节。在面向对象语言中,重载(或称为超载)表达了最简单的多态性。比较容易理解的是函数的重载。例如: void f(int,char,char); void f(int,char); void f(int,int); void f(char,char); 这几个函数都具有相同的函数名f,但其参数不同,它们的函数体也可以完全不同,编译能根据其函数的不同而自动选择相应的函数体进行匹配。因此,一个函数名代表了多种函数的实现(函数体)。 对于函数重载,若函数调用(界面)与哪一个函数体(函数实现)相匹配是在编译时确定的,称为早期匹配;若函数调用与哪一个函数体的匹配是在运行时动态进行的,称之为晚期,1.2.5 多态性,匹配。 C+中的虚函数提供了晚期匹配带来的良好特征。函数重载强调的是函数名相同,函数参数和函数体不相同(编译器能根据参数的差别进行识别和匹配)。虚函数则强调单界面多实现版本的方法,亦即函数名,返回类型,函数参数的类型、顺序、个数完全相同,但函数体可以完全不同,这在编译阶段是无法识别的,只能由系统在运行时动态地寻找所需的函数体进行匹配。 在C+中,通过继承关系,基类及其派生类之间构成一个树形结构(多重继承为图结构),树中的每个类(基类或派生类)都可以说明一个具有虚特性的函数,称为虚函数。那么在这个类极其派生类中都可以定义这个虚函数的不同实现,但要求这些不同实现必须遵守相同的函数界面,否则虚特性丢失。使用时,系统能在运行时刻动态地寻找所需的实现版本。具体,1.2.5 多态性,细节请参见第章。,1.3 面向对象的思维与方法,1.3.1 面向对象是一种认知方法学 从人们对事物的认识过程来看,主要有以下两种方法: 从一般到特殊的演绎方法。以学校为例,最初人们看到的是“学校”这样一个词。在对其进行分类的过程中可以不断理解这一词的含义:进一步分类知道学校有大学、中学和小学之分;再进一步又知道大学分综合性大学、理、工、农、医、文科大学等;每一科分为不同专业;专业分为不同方向在分类达到一定程度后,用面向对象的方法,对已经分好的各类对象进行状态描述和功能定义,可以明确这一类对象所能完成的工作。最后一步就是怎样让这一类对象运转起来,也就是使各类对象建立联系。对于学校这一系统,就是建立各教学保障单位和各教学单位的联系,教师和学生的联系,从而使整个教学系统正常运转起来。,1.3.1 面向对象是一种认知方法学,从特殊到一般的归纳方法。今天看到一条黄狗,它是一个对象,明天又看到一条黑狗,它也是一个对象,这两个对象除了颜色不一样外,其他有关狗的特征完全一样。这样,便可以构造一个类:“狗”,其中描述了狗的所有共同特征,比如:会叫、具有犬齿、嗅觉灵敏、具有颜色、忠诚等。而黄狗和黑狗都是这个“狗”类的实例。因此,面向对象很适合这种认知方式的组合。 面向对象提供了从一般到特殊的演绎手段(如继承等),又提供了从特殊到一般的归纳形式(如类等),从而说明它是一种很好的认知方法。这种分类、归纳的方法在面向对象设计中是很重要的。,1.3.2 面向对象方法与结构化程序设计方法,结构化程序设计强调了功能抽象和模块性,它将解决问题的过程看作是一个处理过程。面向对象程序设计则综合了功能抽象和数据抽象,它将解决问题的过程看作是一个分类演绎的过程。下面对这两种方法进行简单的比较: 模块与对象 结构化程序设计中,模块是对功能的抽象,每个模块都是一个处理单位,它有输入和输出。而对象是包括数据和操作的整体,是将数据和功能的抽象和统一。可以说,对象包含了模块。 过程调用与消息传递 在结构化程序设计中,过程为一独立实体,显示地被它的使用者所见,而且,对于相同的输入参数,每一次过程调用,其输出结果是相同的。,1.3.2 面向对象方法与结构化程序设计方法,在面向对象的程序设计中,方法(或操作)是隶属于对象的,它不是独立存在的实体,而是对象的功能体现。从对象实现机制看,对象是一台自动机,其中封装的数据表示了对象的状态,该状态只能由对象的操作改变它。每当需要改变状态的时候,只能由其他对象向该对象发送消息(在C+中,借助于成员函数调用来实现消息发送)。对象响应消息后,按照消息模式找出匹配的方法,并执行该方法(C+语言是执行函数调用)。应该注意,发送消息和过程调用是不同的,发送消息只是触发自动机,同样的输入参数,可能因自动机状态不同,其输出结果也不同。因此,同一消息的多次发送可能产生不同的结果。 类型与类 类型与类都是对数据和操作的抽象,即定义了一组具有共同特征的数据和可操纵这些数据的一组操作,但类所定义,1.3.2 面向对象方法与结构化程序设计方法,的数据集(包括数据和操作)比常规语言的类型定义的数据集要复杂得多。 模块的可重用性 结构化程序设计方法的核心是逐步细化。这种自顶向下的方法是通过不断在程序的控制结构中增加细节来开发程序。它生产的模块往往为了满足特定需要。可重用性较差。 面向对象程序设计以数据结构为中心开发模块,同时一体化地考虑操作的功能,抓住了程序设计中最不易变的部分数据,因此对象具有良好的可重用性。,第2章 C+编程基础,在这一章,我们将介绍C+编程的一些基础知识。如C+中的常量与变量,基本数据类型,复合数据类型,指针,运算符,基本的输入和输出,基本的程序控制语句等等。要学好C+,就必须要掌握这些基础知识。学完本章以后,相信能为读者奠定良好的C+编程基础。,2.1 概述,2.2 常量与变量,2.2.1 标识符 标识符是对变量、函数标号和其它各种用户定义对象的命名。标识符的长度可以是一个或多个字符。标识符必须以字母或下划线开头,随后的字符必须是字母、数字或下划线。下面是一些正确或错误标识符命名的实例。 正确形式 错误形式 count 2 count test23 hi! there high_balance highbalance C+语言中的字母是要区分大小写的。因此,count、 Count、 COUNT是三个不同的标识符。标识符不能和C+语言的关键字相同,也不能和用户已编制的函数或C+语言库函数同名。,2.2 常量与变量,2.2.2 常量 常量是不接受程序修改的固定值,常量可为任意数据类型,如下例所示: char d、n、5 int 221、1 、210 、-234 long int 3500、-344 short int 10、-12、930 unsigned int 1000、87、4000 float 1234.23、46.34e-3 double 12.23、23133、-0.986234 还有另一种预定义数据类型的常量,这就是串。串常量括在双撇号之间。如“This is a test“。请注意,不要把字符和串相混淆。单个字符常量是由单撇号括起来的,如 a 。,2.2 常量与变量,2.2.3 变量 其值可以改变的量称为变量。一个变量有一个名字(标识符),在内存中占据一定的存储单元。在该存储单元中存放变量的值。所有的C+变量必须在使用之前定义。定义变量的一般形式是:type variable_list; 这里的type必须是有效的C+数据类型,variable_list(变量表)可以由一个或多个由逗号分隔的标识符名构成。下面给出一些定义变量的范例: int i, j, l; short int n; unsigned int x; double balance, profit,money;,2.3 基本数据类型,2.3.1 整型数据 1.整型常量 它是由十进制、八进制、十六进制数字表示的整数值。 十进制常数的形式是: digits 这里digits可以是从0到9的一个或多个十进制数位,第一位不能是0。 八进制常数的形式是: 0digits 在此,digits可以是一个或多个八进制数( 07之间),起始0是必须的引导符。 十六进制常数的形式是: 0xhdigits 0Xhdigits,2.3 基本数据类型,2. 整型变量 前面已提到, C+规定在程序中所有用到的变量都必须在程序中指定其类型。 如下列程序: main() int a,b,c,d; /*指定a , b , c , d 为整型变量*/ unsigned u; /*指定u为无符号整型变量*/ a=1; b=-21; u=11; c=a+u; d=b+u; printf(“a+u=%d, b+u=%dn“,c,d); 程序的输出结果为: a+u=12, b+u=1 0 可以看到不同类型的整型数据可以进行算术运算。在本例中是int型数据与unsingned int型数据进行相加减运算。,2.3 基本数据类型,2.3.2 实型数据 1.实型常量 实型常量又称浮点常量,是一个十进制表示的符号实数。符号实数的值包括整数部分、 尾数部分和指数部分。实型常量的形式如下: digits .digits E|e+|-digits 在此digits是一位或多位十进制数字(从09)。E(也可用e)是指数符号。小数点之前是整数部分,小数点之后是尾数部分,它们是可省略的。,2.3 基本数据类型,2.实型变量 实型变量分为单精度(float型)和双精度(double型)。对每一个实型变量都应在使用前加以声明。如: float x,y; / *指定x , y为单精度实数* / double z; / *指定z为双精度实数* / 在一般系统中,一个float型数据在内存中占4个字节(32位)。一个double型数据占8个字节(64位)。单精度实数提供7位有效数字,双精度提供1 5 1 6位有效数字,数值的范围随机器系统而异。值得注意的是,实型常量是double型,当把一个实型常量赋给一个float型变量时,系统会截取相应的有效位数。例如: float a; a = 111111.111 ;由于float型变量只能接收7位有效数字,因此最后两位小数不起作用。如果将a改为double型,则能全部接收上述9位数字并存储在变量a中。,2.3 基本数据类型,2.3.3 字符型数据 1.字符常量 字符常量是指用一对单引号括起来的一个字符。如 c,9,!。字符常量中的单引号只起定界作用并不表示字符本身。单引号中的字符不能是单引号()和反斜杠(),它们是特有的表示法。这将在转义字符中介绍。字符是按其所对应的ASCII码值来存储的,一个字符占一个字节。例如: 字符ASCII码值(十进制) ! 33 0 48 1 49 9 57 A 65 B 66 a 97 b 98,2.3 基本数据类型,2.字符串常量 字符串常量是指用一对双引号括起来的一串字符。双引号只起定界作用,双引号括起的 字符串中不能是双引号(“)和反斜杠(),它们特有的表示法在转义字符中介绍。例如: “China“,“Cprogram“, “YES&NO“, “33312-2341“, “A“ 等。 要特别注意字符串与字符串常量的区别,除了表示形式不同外,其存储性质也不相同, 字符A只占1个字节,而字符串常量“ A “占2个字节。,2.3 基本数据类型,3.转义字符 转义字符是C+语言中表示字符的一种特殊形式。通常使用转义字符表示ASCII码字符集中不可打印的控制字符和特定功能的字符,如用于表示字符常量的单撇号( ),用于表示字符串常量的双撇号(“)和反斜杠( )等。转义字符用反斜杠后面跟一个字符或一个八进制或十六进制数表示。下图给出了C+语言中常用的转义字符。,2.3 基本数据类型,2.3 基本数据类型,4.符号常量 如果将一个常量定义为一个标识符,称为符号常量。符号常量一般使用大写英 文字母表示,以区别于一般用小写字母表示的变量。符号常量在使用前必须先定义,定义的 形式是: #define 例如: #define PI 3.1415926 #define TRUE 1 #definr FALSE 0 #define STAR * 这里定义PI、TRUE、FLASE、STAR为符号常量,其值分别为3.1415926、1、0、 * 。 # define称为预处理命令,它表示经定义的符号常量在程序运行前将由其对应的常量替换。,2.3 基本数据类型,5.字符变量 字符变量用来存放字符常量,注意只能存放一个字符,不要以为在一个字符变量中可以 放字符串。字符变量的定义形式如下: char c1, c2; 它表示c1和c2为字符变量,各放一个字符。因此可以用下面语句对c1、c2赋值: c1 = a; c2 = b;,2.4 复合数据类型,2.4.1 数组 1.概述 在程序设计中,把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称为数组。数组属于构造数据类型。一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型。因此按数组元素的类型不同,数组又可分为数值数组、字符数组、指针数组、结构数组等各种类别。本节将主要介绍数值数组和字符数组。,2.4 复合数据类型,2. 一维数组的定义和引用 一维数组的定义方式: 在程序设计中,使用数组必须先进行定义。 一维数组的定义方式为: 类型说明符 数组名 常量表达式; 其中: 类型说明符是任一种基本数据类型或构造数据类型。 数组名是用户定义的数组标识符。 方括号中的常量表达式表示数据元素的个数,也称为数组的长度。 例如: int a10; 说明整型数组a,有10个元素。 float b10,c20; 说明实型数组b,有10个元素,实型数组c,有20个元素。 char ch20; 说明字符数组ch,有20个元素。,2.4 复合数据类型,对于数组类型说明应注意以下几点: 数组的类型实际上是指数组元素的取值类型。对于同一个数组,其所有元素的数据类型都是相同的。 数组名的书写规则应符合标识符的书写规定。 数组名不能与其它变量名相同。 方括号中常量表达式表示数组元素的个数,如a5表示数组a有 5个元素。但是其下标从0开始计算的。因此5个元素分别为a0,a1,a2,a3,a4。 不能在方括号中用变量来表示元素的个数,但是可以是符号常数或常量表达式。 允许在同一个类型说明中,说明多个数组和多个变量。,2.4 复合数据类型,例如: int a,b,c,d,k110,k220; 一维数组元素的引用: 数组元素是组成数组的基本单元。数组元素也是一种变量, 其标识方法为数组名后跟一个下标。下标表示了元素在数组中的顺序号。 数组元素的一般形式为: 数组名下标 其中下标只能为整型常量或整型表达式。如为小数时,编译器将自动取整。 例如: a5 ai+j ai+ 都是合法的数组元素。 数组元素通常也称为下标变量。必须先定义数组,才能使用下标变量。只能逐个地使用下标变量,而不能一次引用整个数组。 例如,输出有10个元素的数组必须使用循环语句逐个输出各下标变量: for(i=0; i10; i+) printf(“%d“,ai); 而不能用一个语句输出整个数组。 下面的写法是错误的: printf(“%d“,a);,2.4 复合数据类型,3. 一维数组的初始化 给数组赋值的方法除了用赋值语句对数组元素逐个赋值外, 还可采用初始化赋值和动态赋值的方法。 数组初始化赋值是指在数组定义时给数组元素赋予初值。数组初始化是在编译阶段进行的。这样将减少运行时间,提高效率。 初始化赋值的一般形式为: 类型说明符 数组名常量表达式=值,值值; 其中在 中的各数据值即为各元素的初值,各值之间用逗号间隔。 例如: int a10= 0,1,2,3,4,5,6,7,8,9 ; 相当于a0=0;a1=1.a9=9; 对数组的初始化赋值还有以下几点规定: 可以只给部分元素赋初值。 当 中值的个数少于元素个数时,只给前面部分元素赋值。,2.4 复合数据类型,例如: int a10=0,1,2,3,4; 表示只给a0a45个元素赋值,而后5个元素自动赋0值。 只能给元素逐个赋值,不能给数组整体赋值。 例如给十个元素全部赋1值,只能写为: int a10=1,1,1,1,1,1,1,1,1,1; 而不能写为: int a10=1; 如给全部元素赋值,则在数组说明中,可以不给出数组元素的个数。 例如: int a5=1,2,3,4,5; 可写为: int a=1,2,3,4,5;,2.4 复合数据类型,4.二维数组的定义和引用 二维数组的定义: 前面介绍的数组只有一个下标,称为一维数组,其数组元素也称为单下标变量。在实际问题中有很多量是二维的或多维的,我们可以在程序设计时构造多维数组。多维数组元素有多个下标,以标识它在数组中的位置,所以也称为多下标变量。本小节只介绍二维数组,多维数组可由二维数组类推而得到。 二维数组定义的一般形式是: 类型说明符 数组名常量表达式1常量表达式2 其中常量表达式1 表示第一维下标的长度,常量表达式2 表示第二维下标的长度。,2.4 复合数据类型,例如: int a34; 说明了一个三行四列的数组,数组名为a,其下标变量的类型为整型。该数组的下标变量共有34个,即: a00,a01,a02,a03 a10,a11,a12,a13 a20,a21,a22,a23 二维数组在概念上是二维的,即是说其下标在两个方向上变化,下标变量在数组中的位置也处于一个平面之中,而不是象一维数组只是一个向量。但是,实际的硬件存储器却是连续编址的,也就是说存储器单元是按一维线性排列的。如何在一维存储器中存放二维数组,可有两种方式:一种是按行排列, 即放完一行之后顺次放入第二行。另一种是按列排列, 即放完一列之后再顺次放入第二列。在+语言中,二维数组是按行排列的。,2.4 复合数据类型,例如: a34 表示a数组三行四列的元素。 下标变量和数组说明在形式中有些相似,但这两者具有完全不同的含义。数组说明的方括号中给出的是某一维的长度,即可取下标的最大值;而数组元素中的下标是该元素在数组中的位置标识。前者只能是常量,后者可以是常量,变量或表达式。 二维数组的初始化: 二维数组初始化也是在类型说明时给各下标变量赋以初值。二维数组可按行分段赋值,也可按行连续赋值。 例如对数组a53: 按行分段赋值可写为: int a53= 80,75,92,61,65,71,59,63,70,85,87,90,76,77,85 ; 按行连续赋值可写为: int a53= 80,75,92,61,65,71,59,63,70,85,87,90,76,77,85; 这两种赋初值的结果是完全相同的。,2.4 复合数据类型,5. 字符数组 字符数组的定义: 用来存放字符量的数组称为字符数组。形式与前面介绍的数值数组相同。 例如: char c10; 由于字符型和整型通用,也可以定义为int c10但这时每个数组元素占2个字节的内存单元。 字符数组也可以是二维或多维数组。 例如: char c510; 即为二维字符数组。 字符数组的初始化: 字符数组也允许在定义时作初始化赋值。其方法和数值数组类似。,2.4 复合数据类型,例如: char c10=c, , p, r, o, g, r, a,m; 赋值后各元素的值为: c0的值为c,c1的值为 ,c2的值为p,c3的值为r ,c4的值为0 ,c5的值为g ,c6的值为r ,c7的值为a ,c8的值为m,其中c9未赋值,系统自动赋予0值。 当对全体元素赋初值时也可以省去长度说明。 例如: char c=c, ,p,r,o,g,r,a,m; 这时C数组的长度自动定为9。,2.4 复合数据类型,字符数组的引用: 可见下面的例子: main() int i,j; char a5=B,A,S,I,C,d,B,A,S,E; for(i=0;i=1;i+) for(j=0;j=4;j+) printf(“%c“,aij); printf(“n“); 本例的二维字符数组由于在初始化时全部元素都赋以初值,因此一维下标的长度可以不加以说明。,2.4 复合数据类型,2.4.2 结构 结构的定义:由基本数据类型构成的、并用一个标识符来命名的各种变量的组合。 在结构中可以使用不同的数据类型。 1结构说明和结构变量定义 在C或C+中, 结构也是一种数据类型, 可以使用结构变量, 因此, 象其它 类型的变量一样, 在使用结构变量时要先对其定义。 定义结构变量的一般格式为: struct 结构名 类型 变量名; 类型 变量名; . 结构变量; 结构名是结构的标识符不是变量名。 类型可以为整型、浮点型、字符型、指针型等。 构成结构的每一个类型变量称为结构成员, 它象数组的元素一样, 但数组中元素是以下标来访问的, 而结构是按变量名字来访问成员的。,2.4 复合数据类型,下面举一个例子来说明怎样定义结构变量。 struct string char name10; int age; char sex2; char depart20; float wage1, wage2, wage3, wage4, wage5; person; 这个例子定义了一个结构名为string的结构变量person, 如果省略变量名 person, 则变成对结构的说明。用已说明的结构名也可定义结构变量。例如可以这样定义: struct string char name8; int age; char sex2; char depart20; float wage1, wage2, wage3, wage4, wage5; ; struct string person;,2.4 复合数据类型,结构变量的使用 结构是一个新的数据类型, 因此结构变量也可以象其它类型的变量一样赋值、 运算, 不同的是结构变量以成员作为基本变量。 结构成员的表示方式为: 结构变量.成员名 如果将“结构变量.成员名“看成一个整体, 则这个整体的数据类型与结构中 该成员的数据类型相同, 这样就可象前面所讲的变量那样使用。,2.4 复合数据类型,3. 结构数组和结构指针 结构是一种新的数据类型, 同样可以有结构数组和结构指针。 (1) 结构数组 结构数组就是具有相同结构类型的变量集合。假如要定义一个班级40个同学 的姓名、性别、年龄和住址, 可以定义成一个结构数组。如下所示: struct string char name8; char sex2; int age; char addr40; ; struct string student40; 需要指出的是结构数组成员的访问是以数组元素为结构变量的, 其形式为: 结构数组元素.成员名,2.4 复合数据类型,(2)结构指针 结构指针是指向结构的指针(指针将在后面的章节中讲到)。它由一个加在结构变量名前的“*“ 操作符来定 义, 例如用前面已说明的结构定义一个结构指针如下: struct string char name8; char sex2; int age; char addr40; *student; 也可省略结构指针名只作结构说明, 然后再用下面的语句定义结构指针。 struct string *student; 使用结构指针对结构成员的访问, 与结构变量对结构成员的访问在表达方式 上有所不同。结构指针对结构成员的访问表示为: 结构指针名-结构成员 其中“-“是两个符号“-“和“的组合, 好象一个箭头指向结构成员。,2.4 复合数据类型,例如要 给上面定义的结构中name和age赋值, 可以用下面语句: strcpy(student-name, “Lu G.C“); student-age=18; 实际上, student-name就是(*student).name的缩写形式。 注意: 1) 结构作为一种数据类型, 因此定义的结构变量或结构指针变量同样有局部变量和全程变量, 视定义的位置而定。 2) 结构变量名不是指向该结构的地址, 这与数组名的含义不同, 因此若需要求结构中第一个成员的首地址应该是&结构变量名。,2.4 复合数据类型,2.4.3 联合 联合说明和联合变量定义联合也是一种新的数据类型, 它是一种特殊形式的变量。 联合说明和联合变量定义与结构十分相似。 其形式为: union 联合名 数据类型 成员名; 数据类型 成员名; . 联合变量名; 联合表示几个变量公用一个内存位置, 在不同的时间保存不同的数据类型和不同长度的变量。 下例表示说明一个联合a_bc: union a_bc int i; char mm; ;,2.4 复合数据类型,联合访问其成员的方法与结构相同。同样联合变量也可以定义成数组或指针, 但定义为指针时, 也要用“-“符号, 此时联合访问成员可表示成: 联合名-成员名 另外, 联合既可以出现在结构内, 它的成员也可以是结构。 例如: struct int age; char *addr; union int i; char *ch; x; y10; 若要访问结构变量y1中联合x的成员i, 可以写成: y1.x.i; 若要访问结构变量y2中联合x的字符串指针ch的第一个字符可写成: *y2.x.ch; 若写成“y2.x.*ch;“是错误的。 结构和联合是由区别的,区别如下: (1). 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合中只存放了一个被选中的成员, 而结构的所有成员都存在。 (2). 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存 在了, 而对于结构的不同成员赋值是互不影响的。,2.4 复合数据类型,2.4.4枚举 枚举是一个被命名的整型常数的集合, 枚举在日常生活中很常见。 例如表示星期的SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, 就是一个枚举。 枚举的说明与结构和联合相似, 其形式为: enum 枚举名 标识符=整型常数, 标识符=整型常数, . 标识符=整型常数, 枚举变量;,2.4 复合数据类型,如果枚举没有初始化, 即省掉“=整型常数“时, 则从第一个标识符开始, 顺次赋给标识符0, 1, 2, .。但当枚举中的某个成员赋值后, 其后的成员按依次加1的规则确定其值。 例如下列枚举说明后, x1, x2, x3, x4的值分别为0, 1, 2, 3。 enum stringx1, x2, x3, x4x; 当定义改变成: enum string x1, x2=0, x3=50, x4, x; 则x1=0, x2=0, x3=50, x4=51,2.4 复合数据类型,注意: 1. 枚举中每个成员(标识符)结束符是“,“, 不是“;“, 最后一个成员可省略 “,“。 2. 初始化时可以赋负数, 以后的标识符仍依次加1。 3. 枚举变量只能取枚举说明结构中的某个标识符常量。,2.5 指针基础,2.5.1 指针的基本概念和定义 我们知道变量在计算机内是占有一块存贮区域的, 变量的值就存放在这块区 域之中, 在计算机内部, 通过访问或修改这块区域的内容来访问或修改相应的变 量。C+语言中, 对于变量的访问形式之一, 就是先求出变量的地址, 然后 再通过地址对它进行访问, 这就是这里所要论述的指针及其指针变量。,2.5 指针基础,所谓变量的指针, 实际上指变量的地址。变量的地址虽然在形式上好象类似 于整数, 但在概念上不同于以前介绍过的整数, 它属于一种新的数据类型, 即指 针类型。C+中, 一般用“指针“来指明这样一个表达式 则&d的类型是指向以精度数d的指针, 而&d的值是双精度变量d的地址。,2.5 指针基础,我们可以用下述方法来定义一个指针类型的变量。 int *ip; 首先说明了它是一指针类型的变量, 注意在定义中不要漏写符号“*“, 否则它为 一般的整型变量了。另外, 在定义中的int 表示该指针变量为指向整型数的指针 类型的变量, 有时也可称ip为指向整数的指针。ip是一个变量, 它专门存放整型 变量的地址。 指针变量的一般定义为: 类型标识符 *标识符;,2.5 指针基础,其中标识符是指针变量的名字, 标识符前加了“*“号, 表示该变量是指针变 量, 而最前面的“类型标识符“表示该指针变量所指向的变量的类型。一个指针变 量只能指向同一种类型的变量, 也就是讲, 我们不能定义一个指针变量, 既能指 向一整型变量又能指向双精度变量。 指针变量在定义中允许带初始化项。如: int i, *ip=,2.5 指针基础,2.5.2 指针变量的引用 既然在指针变量中只能存放地址, 因此, 在使用中不要将一个整数赋给一指 针变量。下面的赋值是不合法的: int *ip; ip=100; 假设 int i=200, x; int *ip; 我们定义了两个整型变量i, x, 还定义了一个指向整型数的指针变量ip。i, x中 可存放整数, 而ip中只能存放整型变量的地址。我们可以把i的地址赋给ip: ip= 此时指针变量ip指向整型变量i, 假设变量i的地址为1800, 这个赋值可形象理解,2.5 指针基础,通过指针访问它所指向的一个变量是以间接访问的形式进行的, 所以比直接访问一个变量要费时间, 而且不直观, 因为通过指针要访问哪一个变量, 取决于指针的值(即指向), 例如“*p2=*p1;“实际上就是“j=i;“, 前者不仅速度慢而且目的不明。但由于指针是变量, 我们可以通过改变它们的指向, 以间接访问不同的变量, 这给程序员带来灵活性, 也使程序代码编写得更为简洁和有效。 指针变量可出现在表达式中, 设 int x, y *px= px+*/,2.6 运算符及其使用,2.6.1 赋值运算符 简单赋值运算符和表达式: 简单赋值运算符记为“=”。由“= ”连接的式子称为赋值表达式。其一般形式为: 变量=表达式 例如: x=a+b w=sin(a)+sin(b) y=i+-j,2.6 运算符及其使用,2.6.2 数学运算符,在C+语言中,运算符“ +”、“”、“*”和“ /”的用法与大多数计算机语言的相同,几乎可用于所有C+语言内定义的数据类型。当“ /”被用于整数或字符时,结果取整。例如,在整数除法中,10/3=3。 一元减法的实际效果等于用- 1乘单个操作数,即任何数值前放置减号将改变其符号。模 运算符“%”在C+语言中也同它在其它语言中的用法相同。切记,模运算取整数除法的余数,所以“%”不能用于float和double类型。,2.6 运算符及其使用,2.6.3 关系运算符和逻辑运算符 关系运算符中的“关系”二字指的是一个值与另一个值之间的关系,逻辑运算符中的 “逻辑”二字指的是连接关系的方式。因为关系和逻辑运算符常在一起使用,所以将它们放在一起讨论。 关系和逻辑运算符概念中的关键是True(真)和Flase(假)。C+语言中,非0为True,0为Flase。使用关系或逻辑运算符的表达式对Flase和Ture分别返回值0或1 。,2.6 运算符及其使用,2.6.4 ?运算符 C+语言提供了一个可以代替某些i f - t h e n - e l s e语句的简便易用的操作符?。该操作符是三元的,其一般形式为: EXP1 ? EXE2 : EXP3 EXP1,EXP2和EXP3是表达式,注意冒号的用法和位置。 操作符“ ? ”作用是这样的,在计算EXP1之后,如果数值为True,则计算EXP2,并将结果作为整个表达式的数值;如果EXP1的值为Flase,则计算EXP3,并以它的结果作为整个表达式的值,2.6 运算符及其使用,请看下例: x = 10 ; y = x 9 ? 100 : 200 ; 例中,赋给y的数值是100,如果x被赋给比9小的值,y的值将为200,若用i f - e l s e语句改写,有 下面的等价程序: x = 1 0 ; if(x9) y=100; else y=200;,2.6 运算符及其使用,2.6.5 自增和自减运算符 C+语言中有两个很有用的运算符,通常在其它计算机语言中是找不到它们的自增和自减运算符, + +和- -。运算符“ + +”是操作数加1,而“- -”是操作数减1,换句话说: x = x +1 ; 同+x ; x = x-1 ; 同- - x ;自增和自减运算符可用在操作数之前,也可放在其后,例如: x = x+1;可写成+x;或x+;但在表达式中这两种用法是有区别的。,2.6 运算符及其使用,自增或自减运算符在操作数之前, C+语言在引用操作数之前就先执行加1或减1操作;运算符在操作数之后,C+语言就先引用操作数的值,而后再进行加1或减1操作。请看下例:x=10 ; y =+x ; 此时,y = 11。如果程序改为:x=10 ; y = x+ ;则y
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 河南省西学中考试题目及答案
- 2025年网站内容审核专员岗位招聘面试参考试题及参考答案
- 2025-2026学年高一政治上学期第一次月考卷(北京)含答案解析
- 2025年非营利组织管理专员招聘面试参考题库及答案
- 人力资源文员的岗位职责
- 大数据在企业人力资源管理中的应用研究
- 2025年采购员人员岗位招聘面试参考题库及参考答案
- 【《安井食品公司跨文化冲突管理问题的分析案例》开题报告3900字】
- 浅析如何将学习力转化为生产力
- 员工存在的问题及对策分析论文
- 新产品开发流程与管理规范
- 小儿胆总管囊肿护理查房
- 肿瘤免疫学机制与治疗进展
- 医院水电维护协议书
- 软件系统维护操作手册
- 房屋委托代管协议书
- 浙江开放大学2025年《社区治理》形考任务1-3答案
- 高中数学思政元素教学设计
- 建筑行业项目经理职业规划
- 招标代理工作制度及流程
- 珍爱生命远离毒品主题班会
评论
0/150
提交评论