版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、C+程序设计,参考文献: 谭浩强,C+程序设计,清华大学出版社; 钱能, C+程序设计教程,清华大学出版社。,计算机诞生初期,人们要使用计算机必须用机器语言或汇编语言编写程序。世界上第一种计算机高级语言诞生于1954年,它是FORTRAN语言。先后出现了多种计算机高级语言。其中使用最广泛、影响最大的当推BASIC语言和C语言。 BASIC语言是1964年在FORTRAN语言的基础上简化而成的,它是为初学者设计的小型高级语言。 C语言是1972年由美国贝尔实验室的D.M.Ritchie研制成功的。它不是为初学者设计的,而是为计算机专业人员设计的。大多数系统软件和许多应用软件都是用C语言编写的。,
2、1.1 从C到C+,但是随着软件规模的增大,用C语言编写程序渐渐显得有些吃力了。 C+是由AT /使用命名空间std int main( ) coutThis is a C+ program.; return 0; 在运行时会在屏幕上输出以下一行信息: This is a C+ program.,1.2 最简单的C+程序,用main代表“主函数”的名字。每一个C+程序都必须有一个 main 函数。main前面的int的作用是声明函数的类型为整型。程序第6行的作用是向操作系统返回一个零值。如果程序不能正常执行,则会自动向操作系统返回一个非零值,一般为-1。 函数体是由大括号 括起来的。本例中主函
3、数内只有一个以cout开头的语句。注意C+所有语句最后都应当有一个分号。 再看程序的第1行“#include ”,这不是C+的语句,而是C+的一个预处理命令,它以“#”开头以与C+语句相区别,行的末尾没有分号。,#include 是一个“包含命令”,它的作用是将文件iostream的内容包含到该命令所在的程序文件中,代替该命令行。文件iostream的作用是向程序提供输入或输出时所需要的一些信息。iostream是i-o-stream 3个词的组合,从它的形式就可以知道它代表“输入输出流”的意思,由于这类文件都放在程序单元的开头,所以称为“头文件”(head file)。在程序进行编译时,先对
4、所有的预处理命令进行处理,将头文件的具体内容代替 #include命令行,然后再对该程序单元进行整体编译。,程序的第2行“using namespace std; ” 的意思是“使用命名空间std”。C+标准库中的类和函数是在命名空间std中声明的,因此程序中如果需要用到C+标准库(此时就需要用#include命令行),就需要用“using namespace std; ”作声明,表示要用到命名空间std中的内容。 在初学C+时,对本程序中的第1,2行可以不必深究,只需知道: 如果程序有输入或输出时,必须使用“#include ”命令以提供必要的信息,同时要用“using namespace
5、std;” ,使程序能够使用这些信息,否则程序编译时将出错。,例1.2 求a和b两个数之和。 可以写出以下程序: / 求两数之和 (本行是注释行) #include /预处理命令 using namespace std; /使用命名空间std int main( ) /主函数首部 /函数体开始 int a,b,sum; /定义变量 cinab; /输入语句 sum=a+b; /赋值语句 couta+b=sumendl; /输出语句 return 0; /如程序正常结束,向操作系统返回一个零值 /函数结束,本程序的作用是求两个整数a和b之和sum。第1行“/求两数之和”是一个注释行,C+规定在一
6、行中如果出现“/”,则从它开始到本行末尾之间的全部内容都作为注释。 如果在运行时从键盘输入 123 456 则输出为 a+b=579,例1.3 给两个数x和y,求两数中的大者。 在本例中包含两个函数。 #include /预处理命令 using namespace std; int max(int x,int y) /定义max函数,函数值为整型,形式参数x,y为整型 /max函数体开始 int z; /变量声明,定义本函数中用到的变量z为整型 if(xy) z=x; /if语句,如果xy,则将x的值赋给z else z=y; /否则,将y的值赋给z return(z); /将z的值返回,通过
7、max带回调用处 /max函数结束 int main( ) /主函数, /主函数体开始 int a,b,m; /变量声明 cinab; /输入变量a和b的值 m=max(a,b); /调用max函数,将得到的值赋给m coutmax=mn; /输出大数m的值 return 0; /如程序正常结束,向操作系统返回一个零值 /主函数结束 本程序包括两个函数:主函数main和被调用的函数max。 程序运行情况如下: 18 25 (输入18和25给a和b) max=25 (输出m的值) 注意输入的两个数据间用一个或多个空格间隔,不能以逗号或其他符号间隔。,在上面的程序中,max函数出现在main函数之
8、前,因此在main函数中调用max函数时,编译系统能识别max是已定义的函数名。如果把两个函数的位置对换一下,即先写main函数,后写max函数,这时在编译main函数遇到max时,编译系统无法知道max代表什么含义,因而无法编译,按出错处理。 为了解决这个问题,在主函数中需要对被调用函数作声明。上面的程序可以改写如下: #include using namespace std; int main( ) int max(int x,int y); /对max函数作声明 int a,b,c; cinab; c=max(a,b); /调用max函数,couty) z=x; else z=y; re
9、turn(z); 只要在被调用函数的首部的末尾加一个分号,就成为对该函数的函数声明。函数声明的位置应当在函数调用之前。,例1.4 包含类的C+程序。 #include / 预处理命令 using namespace std; class Student / 声明一个类,类名为Student private: / 以下为类中的私有部分 int num; / 私有变量num int score; / 私有变量score public: / 以下为类中的公用部分 void setdata( ) / 定义公用函数setdata cinnum; / 输入num的值 cinscore; / 输入score
10、的值 ,void display( ) / 定义公用函数display coutnum=numendl; / 输出num的值 coutscore=scoreendl; /输出score的值 ; ; / 类的声明结束 Student stud1,stud2; /定义stud1和stud2为Student类的变量,称为对象 int main( ) / 主函数首部 stud1.setdata( ); / 调用对象stud1的setdata函数 stud2.setdata( ); / 调用对象stud2的setdata函数 stud1.display( ); / 调用对象stud1的display函数
11、 stud2.display( ); / 调用对象stud2的display函数 return 0; ,在一个类中包含两种成员: 数据和函数,分别称为数据成员和成员函数。在C+中把一组数据和有权调用这些数据的函数封装在一起,组成一种称为“类(class)”的数据结构。在上面的程序中,数据成员num,score和成员函数setdata,display组成了一个名为Student的“类”类型。成员函数是用来对数据成员进行操作的。也就是说,一个类是由一批数据以及对其操作的函数组成的。 类可以体现数据的封装性和信息隐蔽。在上面的程序中,在声明Student类时,把类中的数据和函数分为两大类: priv
12、ate(私有的)和public(公用的)。把全部数据(num,score)指定为私有的,把全部函数(setdata,display)指定为公用的。在大多数情况下,会把所有数据指定为私有,以实现信息隐蔽。,具有“类”类型特征的变量称为“对象”(object)。 程序中第1824行是主函数。 程序运行情况如下: 1001 98.5 (输入学生1的学号和成绩) 1002 76.5 (输入学生2的学号和成绩) num=1001 (输出学生1的学号) score=98.5 (输出学生1的成绩) num=1002 (输出学生2的学号) score=76.5 (输出学生2的成绩),C+程序的结构和书写格式归
13、纳如下: (1) 一个C+程序可以由一个程序单位或多个程序单位构成。每一个程序单位作为一个文件。在程序编译时,编译系统分别对各个文件进行编译,因此,一个文件是一个编译单元。 (2) 在一个程序单位中,可以包括以下几个部分: 预处理命令。上节4个程序中都包括#include命令。 全局声明部分(在函数外的声明部分)。在这部分中包括对用户自己定义的数据类型的声明和程序中所用到的变量的定义。,C+程序的构成和书写形式, 函数。函数是实现操作的部分,因此函数是程序中必须有的和最基本的组成部分。每一个程序必须包括一个或多个函数,其中必须有一个(而且只能有一个)主函数(main函数)。 但是并不要求每一个
14、程序文件都必须具有以上3个部分,可以缺少某些部分(包括函数)。 (3) 一个函数由两部分组成: 函数首部,即函数的第一行。包括函数名、函数类型、函数属性、函数参数(形参)名、参数类型。 一个函数名后面必须跟一对圆括号, 函数参数可以缺省,如int main( )。, 函数体,即函数首部下面的大括号内的部分。如果在一个函数中有多个大括号,则最外层的一对 为函数体的范围。 函数体一般包括: 局部声明部分 (在函数内的声明部分)。包括对本函数中所用到的类型、函数的声明和变量的定义。 对数据的声明既可以放在函数之外(其作用范围是全局的),也可以放在函数内(其作用范围是局部的,只在本函数内有效)。 执行
15、部分。由若干个执行语句组成,用来进行有关的操作,以实现函数的功能。,(4) 语句包括两类。一类是声明语句,另一类是执行语句。 C+对每一种语句赋予一种特定的功能。语句是实现操作的基本成分,显然,没有语句的函数是没有意义的。C+语句必须以分号结束。 (5) 一个C+程序总是从main函数开始执行的,而不论main函数在整个程序中的位置如何。 (6) 类(class)是C+新增加的重要的数据类型,是C+对C的最重要的发展。有了类,就可以实现面向对象程序设计方法中的封装、信息隐蔽、继承、派生、多态等功能。在一个类中可以包括数据成员和成员函数,他们可以被指定为私有的(private)和公用的(publ
16、ic)属性。私有的数据成员和成员函数只能被本类的成员函数所调用。,(7)C+程序书写格式自由,一行内可以写几个语句, 一个语句可以分写在多行上。C+程序没有行号,也不像FORTRAN或COBOL那样严格规定书写格式(语句必须从某一列开始书写)。 (8) 一个好的、有使用价值的源程序都应当加上必要的注释,以增加程序的可读性。C+还保留了C语言的注释形式,可以用“/*/”对C+程序中的任何部分作注释。在“/*”和“*/”之间的全部内容作为注释。 用“/”作注释时,有效范围只有一行,即本行有效,不能跨行。而用“/*/”作注释时有效范围为多行。只要在开始处有一个“/*”,在最后一行结束处有一个“*/”
17、即可。因此,一般习惯是: 内容较少的简单注释常用“/”,内容较长的常用“/*/ ”。,1.3.1 C+的输入输出,输入语句:cin 程序在执行期间,接收外部信息的操作称为程序的输入;而把程序向外部发送信息的操作称为程序的输出。在C+中没有专门的输入输出语句,所有输入输出是通过输入输出流来实现的。,要使用C+提供的输入输出时,必须在程序的开头增加一行: #include 即包含输入输出流的头文件“iostream.h”。,输入十进制整数和实数,cin . (举例说明),int a,b; cinab;/程序运行至此停下,等待从键盘输入变量值,键盘输入:3 5 或:3 5 均可。,输入语句自动过滤空
18、白字符。,浮点型数据同整型数据一样。,float c,d; cincd;,char ch1,ch2; cinch1ch2;,若输入:ab则ch1为a,ch2为b。,若输入:a b则ch1为a,ch2为b。,字符型变量过滤空白字符。cin格式过滤空白字符,float a; int i1,i2; char ch1,ch2; cini1ai2ch1ch2;,在缺省的情况下,cin自动跳过输入的空格,换言之,cin不能将输入的空格赋给字符型变量,同样地,回车键也是作为输入字符之间的分隔符,也不能将输入的回车键字符赋给字符型变量。,输出数据cout 与输入cin对应的输出是cout输出流。,当要输出一个
19、表达式的值时,可使用cout来实现,其一般格式为: cout .; 其中运算符“”称为插入运算符,它将紧跟其后的表达式的值,输出到显示器当前光标的位置。,int a=6; float f1=12.4; char s1 =“abcd”; coutatf1ts1endl;,t为转义字符Tab endl为回车或n,显示器,显示器,显示器,6,12.4,abcd,cout将双引号中的字符串常量按其原样输出,char ch1=a,ch2=b; cout“c1=“ch1t“c2=“ch2endl;,c1=ac2=b,int i1=4,i2=5; float a=3.5; cout“a*i1=“a*i1en
20、dl“a*i2=“a*i2endl;,a*i1=14 a*i2=17.5,指定输出项占用的宽度: 在输出的数据项之间进行隔开的另一种办法是指定输出项的宽度。如上面的两个输出语句可改写为: cout setw(6) isetw(10)jendl;,_ _ _ _ _ 4_ _ _ _ _ _ _ _ _12,cout setw(5)msetw(10)j*kendl;,_ _ _ _ 7_ _ _ _ _ _ _ _ 24,其中setw(6)指明其后的输出项占用的字符宽度为6,即括号中的值指出紧跟其后的输出项占用的字符位置个数,并向右对齐。setw是“set width”的缩写。,使用setw()
21、应注意以下三点: 1、在程序的开始位置必须包含头文件iomanip.h,即在程序的开头增加: #include ,2、括号中必须给出一个表达式(值为正整数),它指明紧跟其后输出项的宽度。,3、该设置仅对其后的一个输出项有效。一旦按指定的宽度输出其后的输出项后,又回到原来的缺省输出方式。,输出八、十六进制数和科学表示法的实数,对于整型数据可指定以十六进制或八进制输出,而对于实型数据可指定以科学表示法形式输出。例如,设有如下一个程序: #include void main(void) float x=3.14,y=100; cout.setf(ios:scientific,ios:floatfie
22、ld); /表明浮点数用科学表示法输出 cout xt; cout yendl; ,执行该程序后的输出为: 3.140000e+000 1.000000e+002,与cin中类同,当在cout中指明以一种进制输出整数时,对其后的输出均有效,直到指明又以另一种进制输出整型数据为止。对实数的输出,也是这样,一旦指明按科学表示法输出实数,则接着的输出均按科学表示法输出,直到指明以定点数输出为止。明确指定按定点数格式输出(缺省的输出方式)的语句为: cout.setf(ios:fixed,ios:floatfield);,在定义变量时,如果加上关键字const,则变量的值在程序运行期间不能改变,这种变
23、量称为常变量(constant variable)。例如, const int a=3; /用const来声明这种变量的值不能改变,指定其值始终为3 在定义常变量时必须同时对它初始化,此后它的值不能再改变。 常变量不能出现在赋值号的左边。例如上面一行不能写成 const int a; a=3; /常变量不能被赋值 可以用表达式对常变量初始化,如,1.3.2 常变量,const int b=3+6,c=3*cos(1.5); /b的值被指定为9,c的值被指定为3*cos(1.5) 变量的值应该是可以变化的,怎么值是固定的量也称变量呢?其实,从计算机实现的角度看,变量的特征是存在一个以变量名命名的
24、存储单元,在一般情况下,存储单元中的内容是可以变化的。 对常变量来说,无非在此变量的基础上加上一个限定:存储单元中的值不允许变化。因此常变量又称为只读变量(read-only-variable)。,请区别用#define命令定义的符号常量和用const定义的常变量。 符号常量只是用一个符号代替一个字符串,在预编译时把所有符号常量替换为所指定的字符串,它没有类型,在内存中并不存在以符号常量命名的存储单元。 而常变量具有变量的特征,它具有类型,在内存中存在着以它命名的存储单元,可以用sizeof运算符测出其长度。与一般变量惟一的不同是指定变量的值不能改变。 用#define命令定义符号常量是C语言
25、所采用的方法,C+把它保留下来是为了和C兼容。C+的程序员一般喜欢用const定义常变量。虽然二者实现的方法不同,但从使用的角度看,都可以认为用了一个标识符代表了一个常量。有些书上把用const定义的常变量也称为定义常量,但读者应该了解它和符号常量的区别。,1.3.4 函数的重载,在编程时,有时我们要实现的是同一类的功能,只是有些细节不同。例如希望从3个数中找出其中的最大者,而每次求最大数时数据的类型不同,可能是3个整数、3个双精度数或3个长整数。程序设计者往往会分别设计出3个不同名的函数,其函数原型为: int max1(int a,int b, int c); double max2(do
26、uble a,double b,double c); long max3(long a,long b,long c); C+允许用同一函数名定义多个函数,这些函数的参数个数和参数类型不同。这就是函数的重载(function overloading)。即对一个函数名重新赋予它新的含义,使一个函数名可以多用。,函数的重载,例求3个数中最大的数(分别考虑整数、双精度数、长整数的情况) #include using namespace std; int main( ) int max(int a,int b,int c); /函数声明 double max(double a,double b,doub
27、le c); /函数声明 long max(long a,long b,long c); /函数声明 int i1,i2,i3,i; cini1i2i3; /输入3个整数 i=max(i1,i2,i3); /求3个整数中的最大者 couti_max=iendl;,double d1,d2,d3,d; cind1d2d3; /输入3个双精度数 d=max(d1,d2,d3); /求3个双精度数中的最大者 coutg1g2g3; /输入3个长整数 g=max(g1,g2,g3); /求3个长整数中的最大者 cout“g_max=“gendl; ,int max(int a,int b,int c)
28、 if(ba) a=b; if(ca) a=c; return a; double max(double a,double b,double c) if(ba) a=b; if(ca) a=c; return a; ,long max(long a,long b,long c) if(ba) a=b; if(ca) a=c; return a; ,运行情况如下: 185 -76 567 (输入3个整数) 56.87 90.23 -3214.78 (输入3个实数) 67854 -912456 673456 (输入3个长整数) i_max=567 (输出3个整数的最大值) d_max=90.23
29、(输出3个双精度数的最大值) g_max=673456 (输出3个长整数的最大值) 上例3个max函数的函数体是相同的,其实重载函数并不要求函数体相同。重载函数除了允许参数类型不同以外,还允许参数的个数不同。,例 编写一个程序,用来求两个整数或3个整数中的最大数。如果输入两个整数,程序就输出这两个整数中的最大数,如果输入3个整数,程序就输出这3个整数中的最大数。 #include using namespace std; int main( ) int max(int a,int b,int c); int max(int a,int b); int a=8,b=-12,c=27; coutm
30、ax(a,b,c)=max(a,b,c)endl; coutmax(a,b)=max(a,b)endl; ,int max(int a,int b,int c) if(ba) a=b; if(ca) a=c; return a; int max(int a,int b) if(ab) return a; else return b; 运行情况如下: max(a,b,c)=27 max(a,b)=8 两次调用max函数的参数个数不同,系统就根据参数的个数找到与之匹配的函数并调用它。,参数的个数和类型可以都不同。但不能只有函数的类型不同而参数的个数和类型相同。例如: int f(int); /函数
31、返回值为整型 long f(int); /函数返回值为长整型 void f(int); /函数无返回值 在函数调用时都是同一形式,如“f(10)”。编译系统无法判别应该调用哪一个函数。重载函数的参数个数、参数类型或参数顺序3者中必须至少有一种不同,函数返回值类型可以相同也可以不同。 在使用重载函数时,同名函数的功能应当相同或相近,不要用同一函数名去实现完全不相干的功能,虽然程序也能运行,但可读性不好,使人莫名其妙。,1.3.5 函数模板,C+提供了函数模板(function template)。所谓函数模板,实际上是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个
32、通用函数就称为函数模板。凡是函数体相同的函数都可以用这个模板来代替,不必定义多个函数,只需在模板中定义一次即可。在调用函数时系统会根据实参的类型来取代模板中的虚拟类型,从而实现了不同函数的功能。看下面的例子就清楚了。 例 将上面例子程序改为通过函数模板来实现。,函数模板,#include using namespace std; template /模板声明,其中T为类型参数 T max(T a,T b,T c) /定义一个通用函数,用T作虚拟的类型名 if(ba) a=b; if(ca) a=c; return a; ,int main( ) int i1=185,i2=-76,i3=567
33、,i; double d1=56.87,d2=90.23,d3=-3214.78,d; long g1=67854,g2=-912456,g3=673456,g; i=max(i1,i2,i3); /调用模板函数,此时T被int取代 d=max(d1,d2,d3); /调用模板函数,此时T被double取代 g=max(g1,g2,g3); /调用模板函数,此时T被long取代 couti_max=iendl; coutf_max=fendl; coutg_max=gendl; return 0; ,定义函数模板的一般形式为 template 或 template 通用函数定义 通用函数定义
34、在建立函数模板时,只要将例子程序中定义的第一个函数首部的int改为T即可。即用虚拟的类型名T代替具体的数据类型。在对程序进行编译时,遇到第13行调用函数max(i1,i2,i3),编译系统会将函数名max与模板max相匹配,将实参的类型取代了函数模板中的虚拟类型T。此时相当于已定义了一个函数:,int max(int a,int b,int c) if(ba) a=b; if(ca) a=c; return a; 然后调用它。后面两行(14,15行)的情况类似。 类型参数可以不只一个,可以根据需要确定个数。如 template 可以看到,用函数模板比函数重载更方便,程序更简洁。但应注意它只适用
35、于函数的参数个数相同而类型不同,且函数体相同的情况,如果参数的个数不同,则不能用函数模板。,1.3.6 有默认参数的函数,一般情况下,在函数调用时形参从实参那里取得值,因此实参的个数应与形参相同。有时多次调用同一函数时用同样的实参,C+提供简单的处理办法,给形参一个默认值,这样形参就不必一定要从实参取值了。如有一函数声明 float area(float r=6.5); 指定r的默认值为6.5,如果在调用此函数时,确认r的值为6.5,则可以不必给出实参的值,如 area( ); /相当于area(6.5); 如果不想使形参取此默认值,则通过实参另行给出。如,有默认参数的函数,area(7.5)
36、; /形参得到的值为7.5,而不是6.5 这种方法比较灵活,可以简化编程,提高运行效率。 如果有多个形参,可以使每个形参有一个默认值,也可以只对一部分形参指定默认值,另一部分形参不指定默认值。如有一个求圆柱体体积的函数,形参h代表圆柱体的高,r为圆柱体半径。函数原型如下: float volume(float h,float r=12.5); /只对形参r指定默认值12.5 函数调用可以采用以下形式: volume(45.6); /相当于volume(45.6,12.5) volume(34.2,10.4) /h的值为34.2,r的值为10.4 实参与形参的结合是从左至右顺序进行的。因此指定默
37、认值的参数必须放在形参表列中的最右端,否则出错。,例如: void f1(float a,int b=0,int c,char d=a); /不正确 void f2(float a,int c,int b=0, char d=a); /正确 如果调用上面的f2函数,可以采取下面的形式: f2(3.5, 5, 3, x) /形参的值全部从实参得到 f2(3.5, 5, 3) /最后一个形参的值取默认值a f2(3.5, 5) /最后两个形参的值取默认值,b=0,d=a 可以看到,在调用有默认参数的函数时,实参的个数可以与形参的个数不同,实参未给定的,从形参的默认值得到值。利用这一特性,可以使函数
38、的使用更加灵活。例如例4.7求2个数或3个数中的最大数。也可以不用重载函数,而改用带有默认参数的函数。,例 求2个或3个正整数中的最大数,用带有默认参数的函数实现。 #include using namespace std; int main( ) int max(int a, int b, int c=0);/函数声明,形参c有默认值 int a,b,c; cinabc; coutmax(a,b,c)=max(a,b,c)endl; /输出3个数中的最大者 coutmax(a,b)=max(a,b)endl; /输出2个数中的最大者 return 0; ,int max(int a,int
39、b,int c) /函数定义 if(ba) a=b; if(ca) a=c; return a; ,运行情况如下: 14 -56 135 max(a,b,c)=135 max(a,b)=14 在使用带有默认参数的函数时有两点要注意: (1) 如果函数的定义在函数调用之前,则应在函数定义中给出默认值。如果函数的定义在函数调用之后,则在函数调用之前需要有函数声明,此时必须在函数声明中给出默认值,在函数定义时可以不给出默认值(如例4.8)。 (2) 一个函数不能既作为重载函数,又作为有默认参数的函数。因为当调用函数时如果少写一个参数,系统无法判定是利用重载函数还是利用默认参数的函数,出现二义性,系统
40、无法执行。,1.3.7 引用,对一个变量可以使用“引用”(reference),这是C+对C的一个重要扩充,引用是一种新的变量类型,它的作用是为一个变量起一个别名。假如有一个变量a,想给它起一个别名b,可以这样写: int a; /定义a是整型变量 int /声明b是a的引用 以上语句声明了b是a的引用,即b是a的别名。经过这样的声明后,a或b的作用相同,都代表同一变量。,引用 1 什么是变量的引用,注意: 在上述声明中, int /企图使b又变成a2的引用(别名)是不行的,例 引用和变量的关系。 #include #include using namespace std; int main(
41、 ) int a=10; int ,2 引用的简单使用,a的值开始为10,b是a的引用,它的值当然也应该是10,当a的值变为100(a*a的值)时,b的值也随之变为100。在输出a和b的值后,b的值变为20,显然a的值也应为20。 运行记录如下: 100100 (a和b的值都是100) 2020 (a和b的值都是20),有了变量名,为什么还需要一个别名呢?C+之所以增加引用类型, 主要是把它作为函数参数,以扩充函数传递数据的功能。 到目前为止,我们介绍过函数参数传递的两种情况。 (1) 将变量名作为实参和形参。这时传给形参的是变量的值,传递是单向的。如果在执行函数期间形参的值发生变化,并不传回
42、给实参。因为在调用函数时,形参和实参不是同一个存储单元。,3 引用作为函数参数,例 要求将变量i和j的值互换。下面的程序无法实现此要求。 #include using namespace std; int main( ) void swap(int,int); int i=3,j=5; swap(i,j); couti jendl; return 0; ,void swap(int a,int b) /企图通过形参a和b的值互换,实现实参i和j的值互换 int temp; temp=a; /以下3行用来实现a和b的值互换 a=b; b=temp; 运行时输出3 5,i和j的值并未互换。 为了解
43、决这个问题,采用传递变量地址的方法。,(2) 传递变量的指针。形参是指针变量,实参是一个变量的地址,调用函数时,形参(指针变量)指向实参变量单元。,例 使用指针变量作形参,实现两个变量的值互换。 #include using namespace std; int main( ) void swap(int *,int *); int i=3,j=5; swap( ,void swap(int *p1,int *p2) /形参是指针变量 int temp; temp=*p1; *p1=*p2; *p2=temp; ,形参与实参的结合见下图,这种虚实结合的方法仍然是“值传递”方式,只是实参的值是变
44、量的地址而已。通过形参指针变量访问主函数中的变量(i和j),并改变它们的值。这样就能得到正确结果,但是在概念上却是兜了一个圈子,不那么直截了当。,C+提供了向函数传递数据的第(3)种方法,即传送变量的别名。 例 利用“引用形参”实现两个变量的值互换。 #include using namespace std; int main( ) void swap(int ,void swap(int 输出结果为 i=5 j=3 在swap函数的形参表列中声明a和b 是整型变量的引用。,实际上,在虚实结合时是把实参i的地址传到形参a,使形参a的地址取实参i的地址,从而使a和i共享同一单元。同样,将实参j的
45、地址传到形参b,使形参b的地址取实参j的地址,从而使b和j共享同一单元。这就是地址传递方式。为便于理解,可以通俗地说: 把变量i的名字传给引用变量a,使a成为i的别名。 请思考: 这种传递方式和使用指针变量作形参时有何不同?,结论: 使用引用类型就不必在swap函数中声明形参是指针变量。指针变量要另外开辟内存单元,其内容是地址。而引用变量不是一个独立的变量,不单独占内存单元。 在main函数中调用swap函数时,实参不必用变量的地址 (在变量名的前面加 int main( ) void sort(int ,void sort(int ,void change (int 运行情况如下: Plea
46、se enter 3 integers: 23 12 -345 sorted order is -345 12 23,可以看到: 这个程序很容易理解,不易出错。由于在调用sort函数时虚实结合使形参i,j,k成为实参a1,b1,c1的引用,因此通过调用函数sort(a1,b1,c1)既实现了对i,j,k排序,也就同时实现了对a1,b1,c1排序。同样,执行change (i,j)函数,可以实现对实参i和j的互换。 引用不仅可以用于变量,也可以用于对象。例如实参可以是一个对象名,在虚实结合时传递对象的起始地址。这会在以后介绍。 当看到 inline int max(int,int, int);
47、/声明函数,注意左端有inline int main( ) int i=10,j=20,k=30,m; m=max(i,j,k); couta) a=b; /求a,b,c中的最大者 if(ca) a=c; return a; ,由于在定义函数时指定它为内置函数,因此编译系统在遇到函数调用“max(i,j,k)”时,就用max函数体的代码代替“max(i,j,k)”,同时将实参代替形参。这样,程序第6行 “m=max(i,j,k);”就被置换成 if (ji) i=j; if(ki) i=k; m=i; 注意: 可以在声明函数和定义函数时同时写inline,也可以只在其中一处声明inline,效
48、果相同,都能按内置函数处理。 使用内置函数可以节省运行时间,但却增加了目标程序的长度。因此一般只将规模很小(一般为5个语句以下)而使用频繁的函数(如定时采集数据的函数)声明为内置函数。,内置函数中不能包括复杂的控制语句,如循环语句和switch语句。 应当说明: 对函数作inline声明,只是程序设计者对编译系统提出的一个建议,也就是说它是建议性的,而不是指令性的。并非一经指定为inline,编译系统就必须这样做。编译系统会根据具体情况决定是否这样做。 归纳起来,只有那些规模较小而又被频繁调用的简单函数,才适合于声明为inline函数。,1.3.10 字符串变量,用字符数组来存放字符串并不是最
49、理想和最安全的方法。 C+提供了一种新的数据类型字符串类型(string类型),在使用方法上,它和char、int类型一样,可以用来定义变量,这就是字符串变量用一个名字代表一个字符序列。 实际上,string并不是C+语言本身具有的基本类型,它是在C+标准库中声明的一个字符串类,用这种类可以定义对象。每一个字符串变量都是string类的一个对象。,字符串类与字符串变量,1. 定义字符串变量 和其他类型变量一样,字符串变量必须先定义后使用,定义字符串变量要用类名string。如 string string1; /定义string1为字符串变量 string string2=“China”; /定
50、义string2同时对其初始化 应当注意: 要使用string类的功能时,必须在本文件的开头将C+标准库中的string头文件包含进来,即应加上 #include /注意头文件名不是string.h,1 字符串变量的定义和引用,2. 对字符串变量的赋值 在定义了字符串变量后,可以用赋值语句对它赋予一个字符串常量,如 string1=Canada; 既可以用字符串常量给字符串变量赋值,也可以用一个字符串变量给另一个字符串变量赋值。如 string2=string1; /假设string2和string1均已定义为字符串变量 不要求string2和string1长度相同,假如string2原来是C
51、hina,string1原来是Canada,赋值后string2也变成Canada。在定义字符串变量时不需指定长度,长度随其中的字符串长度而改变。 可以对字符串变量中某一字符进行操作,如 string word=“Then”;/定义并初始化字符串变量word word2=a; /修改序号为2的字符,修改后word的值为”Than”,3. 字符串变量的输入输出 可以在输入输出语句中用字符串变量名,输入输出字符串,如 cin string1; /从键盘输入一个字符串给字符串变量string1 cout string2; /将字符串string2输出,在上一节中可以看到: 在以字符数组存放字符串时,
52、字符串的运算要用字符串函数,如strcat(连接)、strcmp(比较)、strcpy(复制),而对string类对象,可以不用这些函数,而直接用简单的运算符。 (1) 字符串复制用赋值号 string1=string2; 其作用与“strcpy(string1,string2);”相同。 (2) 字符串连接用加号 string string1=“C+”; /定义string1并赋初值 string string2=“Language” /定义string2并赋初值 string1=string1 + string2; /连接string1和string2 连接后string1为C+ Lang
53、uage。,2 字符串变量的运算,(3) 字符串比较直接用关系运算符 可以直接用 =(等于)、(大于)、=(大于或等于)、=(小于或等于)等关系运算符来进行字符串的比较。 使用这些运算符比使用5.5.5节中介绍的字符串函数直观而方便。,不仅可以用string定义字符串变量,也可以用string定义字符串数组。如 string name5; /定义一个字符串数组,它包含5个字符串元素 string name5=Zhang,Li,Fun,Wang,Tan; /定义一个字符串数组并初始化 此时name数组的状况如下图所示。,3 字符串数组,可以看到: (1) 在一个字符串数组中包含若干个(现为5个)
54、元素,每个元素相当于一个字符串变量。 (2) 并不要求每个字符串元素具有相同的长度,即使对同一个元素而言,它的长度也是可以变化的,当向某一个元素重新赋值,其长度就可能发生变化。 (3) 在字符串数组的每一个元素中存放一个字符串,而不是一个字符,这是字符串数组与字符数组的区别。如果用字符数组存放字符串,一个元素只能存放一个字符,用一个一维字符数组存放一个字符串。 (4) 每一个字符串元素中只包含字符串本身的字符而不包括0。,可见用字符串数组存放字符串以及对字符串进行处理是很方便的。 在定义字符串数组时怎样给数组分配存储空间呢?实际上,编译系统为每一个字符串变量分配4个字节,在这个存储单元中,并不
55、是直接存放字符串本身,而是存放字符串的地址。在本例中,就是把字符串Zhang的地址存放在name0,把字符串Li 的地址存放在name1,把字符串Fun的地址存放在name2图5.11只是一个示意图。在字符串变量中存放的是字符串的指针(字符串的地址)。,例 输入3个字符串,要求将字母按由小到大的顺序输出。 #include #include using namespace std; int main( ) string string1,string2,string3,temp; coutstring1string2string3; /输入3个字符串 if(string2string3) tem
56、p=string2;string2=string3;string3=temp; /使串2串3 if(string1=string2) coutstring1 string2 string3endl; /如果串1串2,则串1串2串3,4 字符串运算举例,else if(string1=string3) coutstring2 string1 string3endl; /如果串1串2,且串1串3,则串2串1串3 else coutstring2 string3 string1endl; /如果串1串2,且串1串3,则串2串3串1 运行情况如下: please input three strings
57、: China U.S.A. Germany China Germany U.S.A.,例 一个班有n个学生,需要把每个学生的简单材料(姓名和学号)输入计算机保存。然后可以通过输入某一学生的姓名查找其有关资料。当输入一个姓名后,程序就查找该班中有无此学生,如果有,则输出他的姓名和学号,如果查不到,则输出“本班无此人”。 为解此问题,可以分别编写两个函数,函数input_data用来输入n个学生的姓名和学号,函数search用来查找要找的学生是否在本班。 程序可编写如下: #include #include using namespace std; string name50,num50; /定义两个字符串数组,分别存放姓名和学号 int n; /n是实际的学生数,int main( ) void input_data( ); void search(string find_name); strin
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 百度外推代发投产比差怎么优化
- 2025-2026学年北京市延庆区高三9月月考语文试题
- 2025-2026年婴幼儿护理知识与技能考核试卷
- 2025-2026年海洋生态保护与海洋资源管理模拟试卷
- 2025-2026年宠物医疗急救技能考核试卷
- 2025-2026年护理学临床思维测试题库
- 2026年大学高等数学导数计算课件
- 小学教师培优辅差工作总结(2篇)
- Unit 4 Amazing Plants and Animals Project 同步练习人教版英语八年级上册
- 外贸跟单员考试试卷(外贸流程与单证操作)及答案
- 2026年全国高中数学联合竞赛一试(A卷)试卷及参考答案
- 山东省济南市2026-2027学年高中三年级摸底考试暨开学考化学+答案
- 2026年浙江经贸职业技术学院高职单招笔试英语试题库含答案解析3套试卷
- JL树木伐移项目监理规划
- 节能技术在化工中创新课题申报书
- 初中数学九年级上册《利用相似三角形原理测量高度》跨学科项目式教学设计
- 《中华人民共和国生态环境法典》应知应会测试题100道
- 2025年山东公务员考试申论试题及答案(B卷)
- 船台施工方案
- 2026年非小细胞肺癌诊疗指南
- 千牛平台服务条款协议合同
评论
0/150
提交评论