800 likes | 1.03k Views
3 C++ 语言基础. 3.1 标识符 标识符( identifier )在程序中可以作为不同类型数据或函数的名字。常见的有: 变量( variable )、结构( struct )、联合( union )、枚举( enum )、函数( function )、类( class )和对象( object )等。 C++ 标识符由大、小写字母、数字和下划线组成,并只能以字母或下划线开始。.
E N D
3 C++语言基础 • 3.1 标识符 • 标识符(identifier)在程序中可以作为不同类型数据或函数的名字。常见的有:变量(variable)、结构(struct)、联合(union)、枚举(enum)、函数(function)、类(class)和对象(object)等。 • C++标识符由大、小写字母、数字和下划线组成,并只能以字母或下划线开始。
在C++中,并非所有的标识符都能作变量。系统所保留的关键字(keyword)在编译程序中有特殊的含义,不能用作变量名。这些关键字除了C语言原有的,如:asm,auto,bool,break,case,char,default,do,extern,false,float,goto,if,int,long,true,while等之外,还有C++增添的,如:class,catch,delete,friend,public,new,private,protected,virtual,template等。在C++中,并非所有的标识符都能作变量。系统所保留的关键字(keyword)在编译程序中有特殊的含义,不能用作变量名。这些关键字除了C语言原有的,如:asm,auto,bool,break,case,char,default,do,extern,false,float,goto,if,int,long,true,while等之外,还有C++增添的,如:class,catch,delete,friend,public,new,private,protected,virtual,template等。
3.2 数据类型 图3.1 C++的数据类型
3.2.1 基本数据类型 • C++语言的基本数据类型包括字符型(char)、整型(integer)、浮点型(float)、void类型 和枚举类型。 • 3.2.2 构造数据类型 • 1)类型定义(typedef) • 关键字typedef用于定义一个标识符,表示一种数据类型,经过定义的标识符可以像基本数据类型一样用在以后的变量说明和类型定义中。如: typedef int Integer;//将标识符Integer定义为int Integer x;//将x声明为Integer型,也就是整型 int
2)结构体(struct) • 结构体是由同一名字引用的变量的集合,集合中的每个元素称为数据成员(或称结构元素),每个元素使用名字来引用。结构体提供了将相关的数据汇集在一起的方法,使程序可以方便地处理像日期和学生信息这样的复杂数据。一经定义,结构体也可以用来声明变量,结构体声明变量的方法和普通数据类型相同。结构体的语法格式为: Struct 标识符{ 数据类型1 数据成员1;
数据类型2 数据成员2; 数据类型n 数据成员n; }; 如: struct date{ int year; int month; int day; }; date my_date; my_date.year=1980;
3)共用体(union) • 共用体(或称联合类型)可以是不同类型的数据共享同一内存资源,它的定义方式和结构类型非常相似,但实质差别却很大。与结构体相比,结构体把不同的数据集合在一起,一个结构体变量拥有多个数据;而共用体每次只能包含一种数据类型的信息,变量中始终只有一个数据。从内存占有情况来说,结构体变量所占内存长度是各成员所占内存长度之和,每个成员分别占有自己的内存单元;而共用体变量
所占的内存长度等于最长的成员的长度。其语法格式为:所占的内存长度等于最长的成员的长度。其语法格式为: union标识符{ 数据类型1 数据成员1; 数据类型2 数据成员2; 数据类型n 数据成员n; }; 如:union data{ int i; char ch;
}u1; u1=1; u1=‘A’; • 3.2.3 数据类型转换 • 1)自动数据类型转换 • C++的自动类型转换总是把较低优先级的数据类型转换为较高优先级的数据类型。各种数据类型的优先级是由低到高的,顺序是:double,float,long,int和short。 • 2)强制类型转换
C++提供的强制类型转换语法格式为: • 类型名(表达式)或(类型名)表达式 • 3.3 数组、字符串和指针 • 3.3.1 数组 • 数组变量(简称数组)是一组相同类型的变量的集合。它用一个统一的名称来表示。其中,每个变量称为数组的元素变量,简称数组元素。数组分一维数组和多维数组,下标的个数称作数组的维数。在C++中,数组是复合数据类型,其元素可以是除void类型和函数外的任何一种数据类型。
1)一维数组 • 一维数组只有一个下标,定义一维数组的格式如下: 数据类型数组名 [常量表达式]; • 其中,数据类型是数组元素的类型,常量表达式的值n即为数组元素的长度(元素个数)。数组的各元素在内存中连续存放,用数组下标来访问数组元素,第一个元素的下标值为0,最后一个元素的下标值为n-1。 • 关于数组的定义要注意以下几点:
①数组的命名和变量命名相同,遵循标识符命名规则。①数组的命名和变量命名相同,遵循标识符命名规则。 • ②C++规定,数组下标只能用方括号表示。 • ③C++的数组下标范围是0~(n-1),不能越界,否则出错。 • ④常量表达式中只能包括常量和符号常量,不能包括变量。下面的定义方式是错误的: int n=10; int a [n];
2)多维数组 • 多维数组是数组的数组,即数组元素也是数组。多维数组的定义形式为: • 数据类型 数组名[常量表达式1][常量表达式2]…[常量表达式n]; • 以二维数组为例,说明给多维数组初始化的方法。 • ①将数组的初始值写在一对大括号内,按照数组元素的存放次序依次向数组元素赋初值。数组元素的存放次序是按行存放,即先存放第1行的元素,再存放第2行的元素等,同一行内,按列的下标由小到大存放。例如:
int array[2] [3]={0,1,2,3,4,5} • 执行完该语句后,数组元素的值为: array[0] [0]=0, array[0] [1]=1, array[0] [2]=2, array[1] [0]=3, array[1] [1]=4, array[1] [2]=5 • 另外,初始值的个数也可以小于数组元素的个数,那么剩余的数组元素的值将被取默认值0。若 int array[2] [3]={0,1,2} • 执行完该语句后,数组元素的值为:
array[0] [0]=0, array[0] [1]=1, array[0] [2]=2, array[1] [0]=0, array[1] [1]=0, array[1] [2]=0 • ②按行给二维数组赋初值,例如: int array[2] [3]={{0,1,2},{3,4,5}} • 执行完该语句后,数组元素的值与第一次赋值结果相同。 • 3.3.2 字符串 • 在C++中,字符串实际上是一个字符数组,它和普通字符数组不同之处在于,它一般作为整体来引用。在C++中,没有专门提供字
符串类型,而是将字符串存放在字符数组中来使用。字符串的末尾字符一定是′\0′。符串类型,而是将字符串存放在字符数组中来使用。字符串的末尾字符一定是′\0′。 • 3.3.3 指针 • 1)指针的概念 • 一个变量的地址称为该变量的“指针”。指针是C++对内存地址的一种抽象。指针变量是一种存放内存地址的变量,在C++中指针的值就是地址。指针的一般定义形式为: 数据类型 *变量名 • 其中的数据类型可以是C++中的任何一种数据类型,*是“指向”的意思。例如: int *p1,*p2;
该语句定义了两个指针变量:p1,p2它们都是指向整型变量的指针变量。该语句定义了两个指针变量:p1,p2它们都是指向整型变量的指针变量。 • 在学习指针变量的引用之前,必须先熟悉以下两个重要的与指针相关的运算符: • & 取地址运算符。 • *指针运算符(或称“间接访问”运算符)。 • 例如:& a为变量a的地址,*p为指针变量p所指向的变量。 • 关于指针变量的引用,要注意以下几点: • ①指针变量只能存放地址(指针),不能将一个整型变量(或任何其他非地址类型的数据)赋给一个指针变量。
②指针变量的值如果为0,则称这个指针变量为空指针。空指针不指向任何变量,它的值在头文件中定义为NULL。一个指针变量说明为空指针,表明不指向任何变量,而指针变量不赋值是说明该指针变量的值尚不确定,需要在后面指定。②指针变量的值如果为0,则称这个指针变量为空指针。空指针不指向任何变量,它的值在头文件中定义为NULL。一个指针变量说明为空指针,表明不指向任何变量,而指针变量不赋值是说明该指针变量的值尚不确定,需要在后面指定。 • ③指针变量表示的是所指向变量的首地址。例如,用字符型指针变量表示字符串时,是把字符串的首地址(即第一个字符的地址)赋给指针变量。 • 一般来说,指针所允许的运算有如下4种:
①赋值运算:可以将一个指针所指向的变量的地址值赋给它,也可以将一个数组的地址值或者一个函数在内存中的入口地址值赋给所对应的指针,还可以将一个已被赋值的指针赋给另外一个相同类型的指针。例如:①赋值运算:可以将一个指针所指向的变量的地址值赋给它,也可以将一个数组的地址值或者一个函数在内存中的入口地址值赋给所对应的指针,还可以将一个已被赋值的指针赋给另外一个相同类型的指针。例如: int a,*p1,*p2; p1=&a; p2=p1;//使p2指向指针p1所指向的变量, 即p2和p1都是指向变量a的指针 • ②一个指针可以加上或减去一个整数值,包括加1或减1运算。
③在一定条件下,两个指针可以相减。例如,指向同一个数组的不同元素的两个指针可以相减,其差便是这两个指针之间相隔元素的个数。③在一定条件下,两个指针可以相减。例如,指向同一个数组的不同元素的两个指针可以相减,其差便是这两个指针之间相隔元素的个数。 • ④在一定条件下,两个指针可以相比较。例如,指向同一个数组元素的两个指针可以比较,当这两个指针相等时,说明这两个指针是指向同一个数组元素的。 • 与指针变量密切相关的两个常用运算符,它们是内存地址的动态申请和释放。同C相比,C++提供了性能更好的运算符new和delete,用于实现内存的动态申请和释放。使用的基本格式为:
ptr1=new type; //ptr1指向一个type类型 的变量 ptr2=new type[n]; //ptr2指向一个n元type类 型的数组 delete ptr1; //释放由ptr1指向的变量 空间 delete [ ]ptr2; //释放由ptr2指向的数组 空间 • 其中,p为指针,type为类型名。
new和delete这两个运算符的优点主要表现在: • ①不需要强制类型转换。 • ②运算符new可以通过参数给内存赋初值,但不能给数组空间赋初值。 • 2)数组的指针和指向数组的指针变量 • 一个变量有地址,一个数组包含若干个元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址。指针变量既可以指向变量,也可以指向数组和数组元素(把数组起始地址或某一元素的地址放到一个指针变量中)。所谓数组的指针就是指数组的起始地址,数组元素的指针就是数组元素的地址。
数组的指针变量的定义与指向变量的指针变量相同。例如:数组的指针变量的定义与指向变量的指针变量相同。例如: int a[10]; int *p; p=&a[0]; • 表示把a[0]元素的地址赋给指针变量p。此时,p指向a数组的第0号元素。C++规定数组名代表数组的首地址,也就是第一个元素的地址。那么,也可以这样赋值: p=a;
注意:数组a不代表整个数组,上述语句仅把a数组的首地址赋给指针变量p,而不是把数组a各元素的值赋给p。注意:数组a不代表整个数组,上述语句仅把a数组的首地址赋给指针变量p,而不是把数组a各元素的值赋给p。 • 引用数组元素可以用下标法(如a[3]),也可以用指针法,即通过指向数组元素的指针找到所需的元素。C++规定p+1指向数组的下一个元素,而不是简单地将p值加1。 • 如果p的初值为&a[0],则: • ①p+i和a+i就是a[i]的地址,即它们都指向a数组的第i个元素。 • ②*(p+i)或*(a+i)是p+i或a+i所指向的数组元素,即a[i]。
③指向数组的指针变量也可以带下标,如p [i]与*(p+i)等价。 • 3)指针数组和指向指针的指针 • 一个数组其元素均为指针类型数据,称为指针数组,也就是说,指针数组中的每一个元素都是指针变量。指针数组的定义形式为: • 类型标识*数组名〔数组长度说明〕; • 例如:int *p[4]; • 指向指针数据的指针变量,简称为指向指针的指针。指向指针的指针的定义形式为:
类型标识**变量名; • 例如:char **p; • 3.4 运算符
3.5 控制结构 • C++的流程控制语句主要是表达式语句、选择语句、循环语句和辅助流程控制的转向语句。 • 3.5.1 表达式语句、空语句和块语句 • 在C++中,大多数语句是表达式语句。在一个表达式后面加上分号,就形成一个表达式语句。例如: int x; • 空语句仅包含一个分号。空语句常用于程序中某处语法要求起码要有一条语句,但实际上又没有操作可执行的情况,常见于for循环语句中。
块语句是以“{”开始,并以“}”结束,其间封装着一个语句序列。组成语句序列的语句可以是单语句、块语句或空语句。例如:块语句是以“{”开始,并以“}”结束,其间封装着一个语句序列。组成语句序列的语句可以是单语句、块语句或空语句。例如: { p_temp=p0; p0=p1; p1=p_temp; } • 除块语句和空语句之外的其他语句称为单语句。块语句主要是为了满足将几条语句作为一条语句使用的要求。块语句在语法上等价于一条单语句,可以用在单语句可以使用的地方。注意:在结束一个块语句的右花括号之后不能加分号。
3.5.2 选择语句 • 1)if语句 • if语句的一般形式如下: • if(表达式) { 语句1; 语句n; } • 其中,表达式必须用圆括号( )括起来。 • 花括号中的语句称为if语句的子语句,当表达式的值为真时,执行子语句;否则跳过子语句执行后面的语句。当子语句只有一条时,花括号{ }可以被省略。
这种形式的if语句的流程图如图3.5(a)所示。 图3.5 if语句的流程图(1)
2)if...else语句 • if...else语句可以根据不同的条件分别执行不同的语句序列,其一般形式如下: • if(表达式) { 语句1; 语句m; } else { 语句m+1; 语句n; }
当表达式为真时,执行语句1到语句m;表达式为假时,执行语句m+1到语句n。同样,若if...else语句中的语句序列只有一条语句时,可以省略花括号{ }。 • 这种形式的if语句的流程图如图3.5(b)所示。 • 当一个if语句用作另一个if语句的子语句时,这个if语句称作嵌套的if语句。使用嵌套if语句可以进行多重判断,不过一定要小心,因为else总是与和它在同一块中最接近它的if语句相匹配的。其一般形式如下:
if(表达式1)语句1; else if(表达式2)语句2; else if(表达式3)语句3; else if(表达式m)语句m; else语句n • 这种形式的if语句的流程图如图3.6所示。
3)条件运算符?: • C++提供了一个三元运算符,称为条件运算符(?:),它可以简化条件表达式的表达形式。其语法格式为: 表达式?语句1:语句2 • 在执行时,首先对表达式进行求值,如果表达式的值非0(真),则执行语句1;否则执行语句2。例如: max=(a>b)?a:b; • 上面的语句与下面的语句序列是等价的: if(a>b)
max=a; else max=b; • 4)switch语句 • switch语句是多分支的选择语句,用于将一个表达式的值与某些常量进行连续测试,如果某一常量与表达式的值相匹配,则与之相应的语句便被执行。其语法格式是: switch(表达式) { case常量1:语句序列;
break; case常量2:语句序列; break; Default:语句序列; } • 3.5.3 循环语句 • 1)for语句 • for循环语句的一般格式为: • for(表达式1;表达式2;表达式3)语句
其中,表达式1是初始表达式,一般是赋值语句,用于为循环的控制变量赋初值;表达式2是条件表达式,它决定退出循环的时间;表达式3是增量表达式,用于决定控制变量的变化方式。其中,表达式1是初始表达式,一般是赋值语句,用于为循环的控制变量赋初值;表达式2是条件表达式,它决定退出循环的时间;表达式3是增量表达式,用于决定控制变量的变化方式。 • for语句的执行次序是:进入for循环时,先对表达式1求值,然后对表达式2进行求值。如果其为假,则终止循环;如果表达式2为真,执行for循环体中的语句。随后对表达式3求值,然后再次对表达式2求值,由表达式2的值决定是否进行下次循环。在for循环中,表达式1是赋值语句,仅求值一次。
C++中规定,初值表达式1中可以包括变量说明,说明的变量在这个循环语句中有效。例如:C++中规定,初值表达式1中可以包括变量说明,说明的变量在这个循环语句中有效。例如: for(int i=1;i<=10;i++) • 在for语句中,表达式1、表达式2和表达式3中任何一个都可以省略,但它们之间的分号不能省略。 • 特别注意的是,如果表达式2被省略,而for语句中又没有某个转移语句时,会造成for语句的死循环。这在程序设计中是不允许的。 • for语句的流程图如图3.7所示。
2)while语句 • while语句的一般形式为: while(表达式)语句 • while语句首先计算表达式的值,在其值为真时,执行循环体中的语句;而在其值为假时,终止循环的执行,程序接着执行循环体后的语句。 • 另外需要说明的是,对于for语句的一般形式: • for(表达式1;表达式2;表达式3)语句 • 可以用while循环语句来描述:
表达式1 while(表达式2) { 语句; 表达式3; } • while语句的流程图如图3.8(a)所示。 • 3)do...while语句 • do...while语句的一般形式为: do 语句 while(表达式);
do...while语句和while语句类似,只是对循环条件的检查是在循环的尾部进行的。do...while语句先执行循环体中的语句,然后对表达式求值,在表达式值为真的情况下重复执行循环体中的语句,而在其值为假时,终止循环的执行,程序接着执行循环体后的语句。特别注意,“while(表达式)”后面的分号不要遗漏。do...while语句和while语句类似,只是对循环条件的检查是在循环的尾部进行的。do...while语句先执行循环体中的语句,然后对表达式求值,在表达式值为真的情况下重复执行循环体中的语句,而在其值为假时,终止循环的执行,程序接着执行循环体后的语句。特别注意,“while(表达式)”后面的分号不要遗漏。 • do...while语句的流程图如图3.8(b)所示。
3.5.4 转移语句 • 1)break语句 • break语句有两个用途,一个是用于switch语句中,前面已作介绍;另一个是用在循环语句的循环体中,起到强制退出循环语句的作用。当在循环体中遇到break语句时,循环立即终止,程序跳过break语句后的其余循环体语句,从循环语句后的第一条语句继续执行。 • 2)continue语句
continue语句和break语句有点相像,不过当程序在循环体中遇到continue语句时不会退出循环,而是跳过continue语句后的其他循环体语句,继续下一次循环。continue语句和break语句有点相像,不过当程序在循环体中遇到continue语句时不会退出循环,而是跳过continue语句后的其他循环体语句,继续下一次循环。 • 3)goto语句 • goto语句是无条件转移语句,它需要一个标号,标号是一个标识符,它的命名规则与变量名相同。标号是goto语句转向的目标。goto语句的一般形式是: goto语句标号; • 其中的语句标号可以在goto语句之前,也可以在其后。
由于goto语句会破坏程序的结构化,造成程序运行的混乱和不可预测的后果,原则上应该限制goto语句的大量使用。由于goto语句会破坏程序的结构化,造成程序运行的混乱和不可预测的后果,原则上应该限制goto语句的大量使用。 • 3.6 函数 • 1)函数的定义 • 函数定义的一般格式为: • 函数类型 函数名(形式参数表) • 函数体 • 其中的函数类型就是函数使用return语句返回值的类型,如果没有设置函数类型,系统会将其缺省设为整型。如果函数执行完毕后无需返回任何值,将函数类型设为void。
形式参数说明表(数据类型参数1,数据类型参数2,...)是以逗号分隔的变量类型和变量名表。例如:形式参数说明表(数据类型参数1,数据类型参数2,...)是以逗号分隔的变量类型和变量名表。例如: int sum(int x,int y,int z) { return(x+y+z); } • 函数可以没有形式参数,但圆括号是必须有的。函数体是函数功能的实现部分。 • 另外C++中,允许程序内含有多个名称相同的函数,这就是函数重载。下面声明的3个函数具有相同的函数名,但每个函数的自变量不同: