《C++程序设计教程.docx》由会员分享,可在线阅读,更多相关《C++程序设计教程.docx(132页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、第1章C+程序设计初步C+是在C语言的基础之上发展起来的。它既适合于编写面向过程的程序,也适合于编 写面向对象的程序。在C语言推出之前,操作系统等系统软件主要是用汇编语言编写的。由于汇编语言依赖 于计算机硬件,因此程序的可移植性和可读性就较差。但汇编语言也有它的好处,它能对硬 件直接进行操作,速度快,效率高,一般高级语言没有这种功能。于是,1973年,贝尔实 验室的Thompson和Ritchie开发了 C语言,并用它重写了 UNIX的大部分代码。C语言是面向过程的程序设计语言,随着面向对象技术的成熟,贝尔实验室的 Stroustrup又在C的基础上推出了 C+语言,使之可以支持面向对象的程序
2、设计。目前较为流行的C+版本为Visual C+6.0,它既可以支持DOS下的程序设计,也可以 用来开发Windows环境下的应用程序。1.1 C+的基本结构1.1.1 一个简单的C+程序首先,我们来看一个C+例程。例L L 1/* filename:exll1. cpp这是个求两个数和的例程/#i ncludeint main()int x=0, y=0, sum=0; 声明三个整型变量,其中,sum初始化为coutEnter 2 integers separated by space cinxy;sum=x+y;coutThe sum is ”sumendl;return 0;)C+程序具
3、有与c程序相同的结构形式,每个C+程序由注解、编译预处理和程序主体 三部分组成。C+除了支持原先的/* . */”注释外,又提供了一种新的注释方法“/”。注意, “/*. */”是按段注释,/只支持按行注释。iostream. hw是C+的标准输入输出头文件,cin、cout是iostream. hw中定义的 C+标准输入输出设备标识符。C+的程序入口必须从main。开始,称为主函数,其返回类型默认为整型。每个C+语句以“:”作为个语句的结束。C+程序文件名以CPP作为扩展名。C+所有过程都用函数来实现,每个函数都有一个名字,函数体用对花括号括起来。1.1.2 C+的基本数据类型在C+中,任何
4、数据在使用之前都要进行数据类型的定义,然后才能使用。所谓基本数据类型是种程序设计语言预先定义好的数据类型。C+的基本数据类型分 为三大类,即整型、浮点型和无值型。表1. 1 C+所提供的各种基本数据类型及其值的范围类 型说 明二进制位值 域char字符型8-128-127signed char有符号字符型8-128127unsigned char无符号字符型8255int整型16-3276832767signed int有符号整型16-3276832767unsigned int无符号整型1665535short int短整型16-3276832767signed short int有符号短整
5、型16-3276832767unsigned short int无符号短整型1665538long int长整型32-231-(23 -1)signed long int有符号长整型32-2羽(2 -1)unsigned long int无符号长整型32-1)float浮点数327位有效位double双精度型6415位有效位long double长双精度型8019位有效位1.1.3 C+的标识符C+的标识符只能由下边三种字符组成:大小写字母下划线数字9标识符只允许字母或下划线打头,长度不限,但只有前32个字符有效。C+对字母的大 小写是有区别的。通常也不常用下划线打头。例如:DrawCircl
6、e, DrawRectangle、varl23, i v !等都是合法的标识符。标识符主要用来 标识常量、变量以及函数等等。1.2 常量与变量1.2.1 常量常量是指在程序运行过程屮保持不变的量。常用的有字面常量和符号常量。字面常量又称直接常量,C+有如下几种常量:整型常量、实型常量、字符常量、字符 串常量。整型常量如2、100、-1等。实型常量如3. 14159、2.0、1.0等。字符型常量如,A la l0 7、n,、 a,等。带斜杠的为转义字符,表示特殊的含义。如、表示换行,a,表示响铃等,见表1.2。字符串常量也简称字符串,它们是括在双引号内的字符序列。如The area is :、
7、“Beijing、“Hello, World !n”等。符号常量是用标识符表示的常量,用关键字const声明。如:const double Pi=3. 14159;const int MAXINT=32767;例 1. 2. 1/filename:ex2_l. cpp#includevoid main()(const double Pi=3. 1415926, r=2. 0;double area, circum;area=Pi*r*r;cout=% 二+4-=逻辑运算符!、&、II位运算符1&赋值运算符=条件运算符? :逗号运算符*指针运算符*&字长运算符sizeof强类型转换运算符(类型)
8、分量运算符.-下标运算符 口其它如函数调用运算符1.3.1 算术运算符1 .双目算术运算符双目算术运算符有+-*/%。如:a=b+c;d=e%f;应注意、%的优先级比+、-高。2 .自反运算符自反运算符是种简化的特殊运算符,有+= -= *= /= %=,分别称为自反加赋值、 日反减赋值、日反乘赋值、白反除赋值和自反模赋值。如:a+=b;/Z 等同于 a=a+ba-=b;/Z 等同于 a=a-bC+的自反运算符虽然简洁,但阅读起来困难,应少用为好。3 .增量和减量运算符增量和减量运算符属于单目运算符,有+、。如:int i=0;i+;增量和减量运算符有前缀形式和后缀形式。如:int i=0;i
9、+;/ /int j=0;+j;这两种形式的运算结果是样的,但在某些表达式中却有可能不一样。如:int i=5;x=i+; / x的运算结果为5/ /int i=5;x=+i! x的运算结果为6个是先引用后增量,个是先增量后引用。但在实际使用时,一般也应尽量避免这种 写法,以免造成不必要的错误。可以将其拆成两句,如:int i=5;x=i;i+;/ x的运算结果为5应该注意的是,增量和减量运算符的作用对象只能是变量。如5+、(a+b)+都是错误 的,因为作用对象都不是变量。4 .正负号运算符正负号运算符也属于单目运算符,有+和一,如:-a*b,相当于(O-a)*b。正号一般不写, 没有太大意义
10、。1.3.2 关系运算符关系运算符是指对两个操作数之间的大小进行比较。C+中提供的关系运算符有: = c; / a 的值为 关系运算符常用在条件语句中,如:if (ab)else1.3.3 逻辑运算符C+有三个逻辑运算符,它们是:逻辑与&逻辑或| 逻辑非!为单日运算符,其运算方向是自右向左结合的;&和I丨为双目运算符,其运算方向是 自左向右结合的。例1.3写出描述点A(x,y)落在图1.1中阴影部分的C表达式。解:-2x & x2 & -2y & yl1.3.4 条件运算符条件运算符是种在两个表达式的值中选择一个的操作。它的一般形式为:el?e2:e3其操作过程为:若el为真,则此条件表达式的
11、值为e2;若el为假,则表达式取e3的值。 条件运算符是C+中唯一的三元运算符。例如:max=ab?a:b;1.3.5 位运算符位运算是C+的一大特色,使它兼有了低级语言的功能,而其它许多高级语言没有。C+ 中的位运算符有以下两类:按位逻辑运算符:位与(&)、位或(I)、位取反、位异或。)移位运算符:左移()、右移)位运算只能对整型和字符型的数据进行运算,而不能对浮点型的数据进行运算。例如:a=0x67J即进制数 01100111a;求反后a的值为10011000移位运算是将一个操作中的各位都向左或右移动几位,后面的用填补。例如:若 a=10001101,则经过a3的操作后,a的值就变成011
12、01000。应注意到移位运算的以下特 点,左移一位相当于乘2,右移一位相当于除2。1.4 语句及其流程控制1.4.1 语句语句是源语言级的操作指令。C+中语句可分为如下5种: 表达式语句如a=2. O*Pi*r;声明语句如int a=l;空语句如只有一个分号块语句由一对花括号括起来的一段复合语句流程控制语句用以控制程序的执行顺序,常用的有顺序结构、循环结构、选择结构。 下面重点讨论。1.4.2 if .else 选择结构基本结构:if (判断表达式) “真”语句;else“假”语句;例 1. 4. 1/ filename:ex 141. cpp/返回两数较大者的程序#include int m
13、ain()(int x, y;cout Enter 2 integers separated by a space :;cinxy;cout“The max is :;if(xy)coutxendl;elsecoutyendl;return 0;:if . else结构也可以嵌套,请看下面的例子。例L 4.2/ filename:ex 142. cpp/返回三个数中较大个的程序#include int main() int x, y, z;coutyz;couty) if(xz)coutxendl; elsecoutzz)coutyendl;elsecoutzendl;return 0;1.4
14、.3 switch选择结构switch (开关表达式)(case常量1:语句序列;case常量2: 语句序列;default:语句序列:例1.43/ filename:exl43.cpp/Z测试输入的字符是否数字的程序#includeint main()char c;coutuEnter a character:n;cinc;coutIt is a:;switch(c)casecase *r: case casecase2:casecase case case 8:case 9:cout,digiter.,endl;break;default: coutvv”nondigiter.v vend
15、l;break;return 0;)1.4.4 while重复结构while (条件表达式)语句:/ fi1 ename:ex 144. cpp/Z计算1到100的整数和的程序#includeint main()int i=0;int sum=0;while(i+100)sum+=i;coutThe sum is: sumendl;return 0;例L4.5欧几里德算法:求两个非负整数m,n的最大公因子。解:求两个非负整数m,n的最大公因子,可用迭代相除法。我们用u表示被除数,v表 示除数,r表示余数,迭代相除法可以描述为u=m; v=n;当r=u%v不为0时,u=v; v=r;输出v;如m
16、=36, n=21,计算过程为u: 3621156v: 211563r:15630/ filename:ex 145. cpp/Z计算非负整数m和n的最大公约数程序#inc1udeint main()(int m, n, u, v, r;cout“Enter two positive integers:cinmn;u=m; v=n;if(u*v!=0)while(r=u%v)( u=v; v=r;coutThe ged is: vendl;)elsecoutDivided by zero! endl;return 0;例 1. 4. 6 Fibonacci 问题。&=1ax =1% =*+ %
17、求第n项的值。/ f i1ename:f i bonacc i. cpp/ Fibonacci 数列#includeint main()(unsigned int fib,fibl, fib2;unsigned int number,n=0;cout,rEnter a number of Fibonacci terms: cinnumber;coutThe Fibonacci series are:;while(+n=number)if(n3)fib=fibl=fib2=l;else(fib=fibl+fib2;fibl=fib2;fib2=fib;)coutfib,;)coutendl;re
18、turn 0;1.4.5 do . while 重复结构do语句:while(条件表达式);do . while结构的特点是先执行,后判断。例 L4.7/ f ilename:ex 14I. cpp/Z求!到100的和#includeint main()(int i=l;int sum=0;dosum+=i;while(i+100);cout“The sum is: sumendl;return 0;1.4.6 for循环结构for (表达式1I表达式2I表达式3) 语句;例 1.4. 8int main()int i, j;/Z打印表头cout( Ifor(i=l;i=9;i+) couti
19、 coutendl;/Z打印表线COUtI ;for(i=l;i=9;i+) coutcoutendl;/Z打印表体 for(i=l;i=9;i+) couti I;for(j=l;j=9:j+)if(i*j=9)couti*j* else couti*j*)coutendl;)return 0;1.4.7程序中止函数exit。exit。是系统函数库stdlib.h中的一个函数,它的功能是中止程序执行,并在程序退 出之前对现场进行淸理,如关闭被程序打开的文件等,然后返回到操作系统。例1.4. 9计算个数的平方根。/ filename:exl49. cpp/Z计算个数的平方根#include#i
20、nclude#includemath. hint main()float f;cout“Enter a real;cinf;if (f0)(coutIllegal digiter! endl;exit (-1);coutThe square root is: sqrt (f)endl; return 0;第2章过程的组织和管理2.1函数2.1.1函数结构和函数定义个大型的程序一般可以分成一系列“単一功能模块”的集合。在C+中,单功能模 块通常设计成一个函数。因而C+程序可以设计成一系列函数的组合,这是面向过程程序设 计的一般方法。个完整的C+程序一般包含一个主函数和若干个子函数,主函数可以调用
21、 子函数,子函数也可以调用其它的子函数。利用函数可以大大降低程序设计的工作量,使程 序更加清晰可靠。很多编译系统本身就带有很多预定义的函数,并把它们以库函数的形式提 供给用户,这大大方便了程序设计人员。函数定义的一般形式如下:类型标识符函数名(形参列表)(函数体;)类型标识符为函数的返回类型,可以是整型、浮点型等C+的合法类型,也可以是无值 型(void型。函数名是函数的标识,可以是一个有效的C+标识符。形参列表是括在圆括号内的0个或多个以逗号分隔的形式参数。它定义了函数将从调用 函数中接收儿个数据及它们的类型,所以称为形式参数。所谓形式参数的含义是指仅当函数 被调用时,系统为其分配存储空间。
22、与之相应,主调程序传递过来的参数称之为实在参数。 通常,形式参数和实在参数简称为形参和实参。函数的返回值由返回语句return来实现。例 2. 1. 1/ filename:ex211. cpp/判断个数是否素数#includechar prime(unsigned int number);int main()int m;coutThe primers from 3-100 are:endl;for(m=3;m=100;m+)if(prime(m)=l) coutm,;return 0;char prime(unsigned int number) char f=l;unsigned int
23、n;for(n=2;nint max (int x, int y);double max(double x,double y);int main()coutmax (10, 20) endl;coutmax(1. 23, 4. 56)y?x:y;)double max(double x,double y)return xy?x:y;函数重载的好处是主调函数会根据参数自动选择正确的子函数,这大大提高了程序的通 用性和可读性。2.1.3 内嵌函数程序在执行过程中,每调用一次函数,就要在调用与返回过程中付出一定的时间和空间 代价用于处理现场,通常是用堆栈进行保护,返回时退栈恢复现场。但当函数较小,又
24、反复 使用时,处理现场的开销会急剧增大。若把函数嵌入函数调用处,便可以大大提髙运行速度。 这当然是以牺牲存储空间作为代价的。内嵌函数在程序编译时直接将代码嵌入到调用处,这 增加了代码的长度,但运行速度大大加快。例2.L 3III filename:ex213. cpp/判断两数较大者#includeinline double max(double x, double y);int main()int i;double a, b;for(i=l;iab;coutmax (a, b) endl;)return 0;double max(double x,double y)return xy?x:y
25、;)内嵌函数有如下限制:(1)内嵌函数中不能有循环结构或switch结构及goto语句;(2)内嵌函数中不能含有任何静态数据及数据声明。由于有以上限制,使用起来不是太方便。因此,除非必要,一般尽量不使用内嵌函数。2.1.4 递归函数个函数直接或间接调用自身,便构成了函数的递归调用。递归在程序设计屮经常用到, 它可以大大简化程序的设计。例2. 1.4递归计算n!的函数。int rfact(int n)if(n0)cout*Negative argument. Mendl;exit (-1);)elseif(n=l) return 1;elsereturn n*rfact (n-l);递归过程不应
26、无限制地进行下去,应当能在调用有限次以后,就到达递归调用的中点得 到个确定值,然后进行回代。回代的过程是从个已知推出下个值的过程。任何有意义 的递归总是由两部分组成,递归形式与递归终止条件。本例的算法就是基于如下的递归数学 模型:非法( 1)fact(n) = 1)例 汉诺塔问题(Tower of Hanoi) / f i1ename:hanio. cpp/ Tower of Hanoi#includeint hanoi (int number, char a, char b,char c);int main()|int number;cout“Please enter the number
27、of disks to be moved:*;coutnumber;hanoi(number, PileA, PileB, PileC);return 0;)int hanoi(int number, char a, char b,char c)(if(number0) hanoi(number-1, a, c, b);coutMove disc ”number“ from a to bendl;hanoi(number-1, c, b, a);return 0;2.1.5C+库函数C+语言的核心部分很小,其外壳却十分丰富。这个外壳中提供丰富的库函数。程序员 使用库函数无须再自行定义,只要注意
28、以下三点便可:(1)了解函数的功能(2) 了解函数的原型(3)库函数按功能分为不同的库,每个库都有相应的头文件,给出了该库中各个函数的 原型声明等有关信息。程序员使用库函数之前只需在程序中使用#include指令嵌入相应的头 文件而不必再进行函数的原型说明。/filename:ex215. cpp#include-includemath. hint main()float f;cout“Enter a real number:*;cinf;coutThe square root of *fis: * io. h、stdio. h con io. hdos. hmem. h、string, hm
29、ath, h、complex, h、bed. h、float. h stdlib. halloc. h dos. hstdlib. h dos. h、!ocate, hprocess.h signal, hconio. htime, h、dos. h2.2 程序实体及其存储类程序实体也称程序对象,对应着程序中的块内存空间。每个程序实体都有一个标识符, 用以保存程序中用到的各种变量、标号、参数和函数等等。每个程序实体都有一定的作用域 和生存期,这反映了它的存储属性。2.2.1 程序实体的生存期和作用域每个程序实体在程序执行中都有从创建到被撤消的一段时间,这段时间就称为该程序实 体的生存期。在生存
30、期内程序实体的标识符与它的存储区相关联。因此,程序实体的生存期 由系统为其分配的内存方式所决定。C+为程序实体提供了四种内存分配方式:静态分配(编 译器预分配)、栈分配(自动分配)、堆分配(动态分配)、只读分配。(1)静态分配系统可以为每个程序开辟个固定的静态数据区。存于这区域中的程序实体在编译时即 被预分配存储空间,并且在程序开始执行时就被创建,一直到程序结束被撤消,故称为永 久存储。静态分配的特点是与程序共存亡,具有静态生存期。这种分配适合于那些在程序中 用得不多,但要为多个函数共用的程序实体。(2)栈分配栈是系统为程序开辟的活动存储区,它是程序使用最频繁的存储区。个实体,一旦在 个函数内
31、部或个块内部被声明,系统便在栈中创建它们:该块或函数执行结束,遂将其 弹出撤消。这种程序实体具有局部生存期,即它与所在的块共存亡。这种分配适合于那些在 程序中使用频繁的程序实体,随建随撤,节省空间。(3)动态分配动态分配将产生一种完全由程序员控制生存的程序实体。在C+中,程序员可以利用专 门的运算符new和delete来创建和撤消程序实体。(4)只读分配即用const声明的程序实体,可以认为是被创建在程序的只读存储区中。作用域实际上就是程序实体的作用范围,而在此范围之外,该程序实体是不可见的。C+ 的这种特性使得在同一个程序中使用两个名字相同的程序实体成为可能,只要这两个程序实 体的作用域不同
32、就行。2.2.2 C+的存储属性存储属性是对作用域和生存期的抽象。C+的存储属性有以下四种:auto (自动)register (寄存器)extern (外部)static (静态)在声明和定义程序实体时,可使用上述关键字来说明程序实体的存储属性。其格式为: 存储属性类型标识符=初始化表达式;1. auto 型属于auto型的程序实体,称为自动程序实体,它采用的是栈分配存储模式。在C+中, auto可以不写,即程序实体的默认方式为auto。如:auto int a; /Z 等价于 int a在C+中,以自动型变量用得最多,它的作用域具有局部属性,即从定义点开始至本函 数(或块)结束。其生存期自
33、然也随函数(或块)的销毁而销毁。因而通常称其为局部变量, 具有动态生存期。2. register 型register型程序实体和auto型程序实体的作用相同,只不过其采用的是寄存器存储模 式,执行速度较快。当寄存器全部被占用后,余下的register型程序实体自动成为auto 型的。只有整型程序变量可以成为真正的register型变量。3. extern 型用extern声明的程序实体称为外部程序实体。它是为配合全局变量的使用而定义的。所谓外部变量,就是在块外保持不变,并不因块内发生变化而影响到块外。例如: /filename:ex221. cpp #include int a=7;/定义全局
34、变量 int main() extern int a: 声明a引用的是全局变量,a=7 coutaendl;(int a=3;屏蔽了全局变量acoutaendl ;/a=3 extern int a;coutaendl ;/a=7 return 0;由于使用外部变量容易造成程序员的混淆,故现在很少使用。在面向对象的程序设计语 言中,更是不允许使用外部变量。4. static 型用static声明的程序实体称为静态程序实体,它们有如下特点:(1)静态程序实体是永久存储,其生存期是静态的。它的初始化是在编译时进行的,在 整个程序运行期间,它都存在。(2)静态程序实体的生存期虽然是永久的,但其作用域
35、却可以是局部的,当然也可以是 全局的。/fi1ename:ex222. cpp#include void increment();int main()(increment();increment ();increment (); return 0;void increment ()(static int i;永久生存期,局部作用域 i+;coutiendl;表2.1 C+的存储属性存储属性registerautostaticextern存储位置寄存器主存生存期动态生存期永久生存期作用域局 部局部或全局全 局2.3 编译预处理C+语言允许在程序中用预处理命令写些命令行。这些预处理行都以“#”打头
36、,末尾 不加分号以区别于语句行。它们可以出现在程序中的任何位置,但一般写在程序的头部。C+ 编译器在进行实质性的编译前,先要用它们的预处理程序对这些预处理命令行进行处理。C+ 提供的预处理命令有:宏定义指令#tdefine文件包含指令tinclude条件编译指令#if . #else.#end if行控制指令tline其它如 tpragma,terror1 .宏定义宏定义也称宏代换,实际就是用个宏名字来命名个字符串,其形式为:define 宏名宏体下面是宏定义的一些例子:#defineEOF-1定义文件结束符defineMAXIM2147483647定义4字节最大值#defineTRUE1定义
37、逻辑真#defineFALSE0定义逻辑假#defineDELETE取消DELETE宏定义#definePI3. 1415926#defineRADIUS2.0#defineCIRCUMreturn(2. O*PI*RADIUS)#defineCUBE (x)x*x*x宏代换虽然很方便,增加了程序的可读性,但也同时会产生一些副作用。如函数调用时 系统要进行参数类型检查,而宏调用没有内部类型检査,当实参与形参的类型不匹配时,会 出现难以预料的结果。2 .文件包含文件包含的作用是让编译器把一个已经进入系统的源文件嵌入到当前源文件中该指令 处。它有两种格式:include 文件名/编译器默认路径include“文件标识” 当前文件合法路径,可包含路径名头文件中主耍用来存放一些常量,常用数据结构,函数原型声明等等。这是模块化程序 设计的种有效的手段。3 .条件编译条件编译是源文件内系统级的选择结构,其格式如下: if判断表达式语句或预处理命令表列 else语句或预处理命令表列 end if使用条件编译可以有选择地对源程序
限制150内