




已阅读5页,还剩353页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
02:22:41,1,C + 程序设计教程(第二版),第一章 c+概述 Chapter 1 Introduction,清华大学出版社,一、面向对象的方法是在计算机语言发展过程中产生的。 早期:机器语言、汇编语言 50年代中期:FORTRAN语言引进了许多现代仍然使用的程序设计概念。 50年代后期:ALGOL60提出块结构的思想。 60年代:SIMULA67首先提出对象和类的概念,并支持类的继承,是面向对象语言的鼻祖 70年代:ADA不能全面地支持继承,称为基于对象的语言。,1 面向对象的由来和发展,后来出现的Smalltalk是最有影响的面向对象的语言之一。 80年代中后期以后,随着面向对象的程序设计语言的广泛应用,出现了更多的面向对象的语言。,面向对象的语言可分为以下两类: 1、开发全新的面向对象的语言 ObjectC Eiffel Smalltalk80 2、对传统语言进行面向对象的扩展,称为混合型语言,其代表有C+语言。,C+,C,C+ 语言具有C语言的丰富的应用基础和开发环境的支持,对于已经掌握C语言的人讲,更易学易普及。,二、从C到C+ C语言是贝尔实验室为DEC公司开发PDP 系列计算机操作系统时研制的。 C作为UNIX操作系统的开发语言而广为应用 和流行。1989年制定为ANSI C标准。,1、语言简洁、紧凑,使用方便、灵活。 2、运算符和数据类型丰富。 3、访问内存地址、寄存器、进行位操作, 具有汇编语言的功能。 4、生成的目标代码质量高、程序运行效率高。,C语言的独有特点是:,局限: 1、对类型的检查机制相对较弱、程序中的一些错误不能在编译时发现; 2、无支持代码重用的语言结构; 3、当程序规模达到一定的程度时,难以控制程序的复杂性;,为满足管理程序复杂性需要,1980年,贝尔实验室对C进行了改进和扩充:,“带类的C”,C,1983年取名为C+,后经过三次修订。 1994年制定了ANSI C+标准的草案。,1、C+是C的扩展,C是C+的子集,C+ 包括C的全部特征、属性和优点。同时,增加了对面向对象编程的完全支持。 2、与C 一致, C+程序结构采用函数驱动机制实现。 3、C+实现了类的封装,数据隐藏、继承及多态,使其代码可重用并容易维护。 4、C+是一门高效使用的程序设计语言,既可进行过程化程序设计,又可进行面向对象程序设计。,C+的特点,在面向过程的程序设计中,程序是处理数据的一系列过程。过程(或函数)定义为实现特定功能的一组指令。 其主要设计思想是功能分解并逐步求精。数据与程序过程分开存储,编程的主要技巧在于关注模块之间的调用关系及数据的变化。,1.2 面向过程的程序设计,1、当数据量增大时,数据与处理这些数据的方法之间的分离使程序变得越来越难以理解。 2、相对于老问题的新方法都要带来额外的开销,程序的可重用性小。,面向过程程序设计的主要缺点,面向对象程序设计 OOP (Object-Oriented Programming)的三要素: 对象、类和继承 面向对象程序设计的实现需要: 封装和数据隐藏技术 继承和多态性技术,1.3 面向对象程序设计,对象的模型结构,多态性 封装性、继承性、多态性是构成面向对象 程序设计的三大特征。 封装性是基础 继承性是关键 多态性是补充 什么是多态性? 多态是指一个名字有多种语义,或一个相同界面有多种实现; 或是指发出同样的消息被不同类型的对象 接受而导致完全不同的行为。即对象根据所接收到的消息做出相应的操作。,例如:在学籍管理系统中,学生类(基类) 计算成绩的操作,中学生类(派生类) 计算成绩的操作,大学生类(派生类) 计算成绩的操作,1.4 程序开发过程,例1: /* /*ch1.0.cpp* /* void main( ) ,1.5 最简单的程序,运行结果为:,例2: /* /*ch1.1.cpp* /* # include void main( ) cout “I am a student.n”; ,1.5 最简单的程序,运行结果为: I am a student.,例 3: /* ch1.2.cpp * #include void main( ) int interger1; int interger2; int result; cout interger1 interger2; result=3*interger1-2*interger2+1; cout “Result is ” resultendl; ,内存的概念 Memory Concepts,cin integer1; Assume user entered 45 cin integer2; Assume user entered 72 sum = integer1 + integer2;,C+程序是由函数构成的,由一个主函数和若干个函数构成。 C+程序是函数驱动的。 例3: /*ch1.3.cpp* #include #include double max(doubl x, doubl y); / function prototype void main( ) double a, b, c; cout “Input two numbers:n”; c=max(a,b); cout “The squart of maximum=”sqrt( c); , 1.6 函 数,double max(double x, double y) if (xy) return x; else return y; ,运行结果: Input two numbers: 10.0,25.0 The squart of maximum=5.0,学习本课程目的,C + 程序设计教程(第二版),第二章 基本编程语句 Chapter 2 Basic Programming Statements,清华大学出版社 钱 能,第二章内容,说明语句 ( Declarative Statements ) 条件语句 (Condition Statements ) 循环语句 ( Loop Statements ) 循环设计(Loop Designs ) 输入输出语句( Input/Output Statements ) 转移语句 ( Move Statements ) 再做循环设计(More Loop Designs ),1. 说明语句 ( Declarative Statements ),数据说明: 求解问题所使用的数据是什么性质,进行什么运算,表达范围如何,必须预先说明 说明方式: 既要指明其名字,也要指明其是什么类型,还可以顺便初始化如: int a; double d = 3.5; 说明数据的另一个目的是创建一个所需大小的实体空间给该名字,以便存储所用的数据值 若数据名字没有说明,使用其便是非法的,过程(函数)说明: 求解中需要通过函数调用来实施求解时,便要对函数的性质进行说明,说明其返回类型,参数类型,参数个数 函数说明分函数声明和函数定义两种: 函数声明是说明函数的名字,函数的返回类型,以及函数的参数和个数如: double area(double ra); 函数定义是在函数声明的基础上,对整个实现过程进行详细定义如: double area(double ra) return ra*ra*3.14; ,调用函数就是使用函数名字,使用名字前必须清楚名字的性质,所以必须先对函数进行声明 运行程序中,会涉及到被调用函数的执行,所以凡是被调用的函数都必须有函数定义,不管该定义在程序的什么位置如: double sphere(); / 声明 int main() double result = sphere(); / 调用 coutr; return r*r*3.14; ,. 条件语句(Condition Statements ),if语句的两种形态:,语句1,条件,语句1,条件,语句2,是,是,否,否,对应语句: if(ab) coutaendl; if(a=b) coutaendl; else coutbendl;,错综复杂时,必须注意两义性: if(x0) if(x50) cout”x is ok.n”; else cout”x is not ok.n”;,正解:else从属于紧挨的if if(x0) if(x 50) cout”OKn”; else cout”NOT OKn”; ,误解:else从属于外面的if if(x0) if(x 50) cout”OKn”; else cout”NOT OKn”;,条件表达式: 对于 if(x) a = 327981; else b = 327981; 可表示为: x ? a=327981 : b=327981; 如果a和b为同类型,则还可以: (x?a:b) = 327981;,switch多分支语句: switch(整数表达式) case value1: 语句1; break; case value2: 语句2; break; default: 语句n; 等价于: if(整数表达式=value1) 语句1; else if(整数表达式=value2) 语句2; else 语句n; ,虽然switch有等价的复合if表示, 而且,分支判断值只能是整数,显得应用范围狭窄, 但是switch在使用上的直观和灵活形式, 使得其仍具有编程价值. 如: break可选,甚至case可以重叠: case value1: 语句1; case value2: 语句2; case v1: case v2: case v3: 语句;,3. 循环语句 ( Loop Statements ),for循环结构:,对应语句为: for(int i=1; i=10; i+) cout”hello.n”;,循环初始状态,条件判断,状态修正,循环体,每次循环体执行,都改变循环状态,直到条件不满足而终止. 如,设置求和的初始值,交给循环计算,完成循环后,输出求和结果: int sum = 0; for(int i=1; i=100; i+) sum = sum+i; coutsumendl;,循环开始,循环结束,因为并不是所有循环都有明显的循环初始状态和状态修正的,所以,while循环是一种for循环的简洁形式. 如,同样的求和: int sum=0, i=1; while(i=100) sum += i+; coutsumendl;,循环开始,循环结束,4. 循环设计 ( Loop Designs ),(1)简单字符图形的双重循环 M MM MMM MMMM MMMMM MMMMMM MMMMMMM MMMMMMMM MMMMMMMMM MMMMMMMMMM,分析方法: 该图形一共10行,每一行增加一个字符,所以,应循环10次,每次输出一行,其循环模式为: for(int i=1; i=10; +i) 输出第i行(循环) 换行 行 i M个数 1 1 1 2 2 2 3 3 3 4 4 4 . 10 10 10,for(int i=1; i=10; +i) for(int j=1; j=i; +j) cout”M”; coutendl; ,(2)判断素数:(利用数学定律) mij 假定ij, 则 i2ijmj2 即 i2mj2 即 imj bool isPrime(int m) double sqm=sqrt(m*1.0); for(int i=2; i=sqm; +i) if(m%i=0) return false; return true; ,5. 输入输出语句( Input/Output Statements ),标准输出流: 可以控制输出格式 cout3)3); / 0 false coutfixed12345.678; / 12345.678000 coutscientific123456.678; / 1.234568e+05,控制宽度和填充字符的操作是带参数的,注意width(n)为一次性操作,即第二次显示时将不再有效。默认为width(0),表示仅显示数值。例如: cout.width(5); cout.fill(S); cout coutsetw(6)setfill($)27endl; / 输出: $27,文件流的输入出操作与标准输入出基本相同,只是需要以一定方式打开和关闭 如,将文件a.in打开,逐行读入字符,输出到文件a.out: ifstream in(“a.in”); ofstream out(“a.out”); for(string s; getline(in, s); ) outsendl; 其中文件流读入操作总是伴随着状态返回,判断状态就可以确定文件是否正常读入,如getline(in,s)当读到文件尾时,便返回false,以使循环结束,. 转移语句 ( Move Statements ),break除了用在switch之外,主要的是用在终结本次循环 for(int i; ; ) for( ; ; ) / . if(i=1) break; / . a=1; / . ,break跳到此处,continue一般是用条件判断执行的,通过反条件,可以免去continue的使用,所以,它用来构筑良好的程序风格 for(int n=100; n=200; +n) if(n%3=0) continue; coutnendl; 免去continue的情形: for(int n=100; n=200; +n) if(n%3!=0) coutnendl;,goto的程序段除了系统跟踪和架构困难外,阅读也相对复杂: int a; goto Init; Forward: a = a + 1; Print: coutaendl; goto Down; Init: a = 1; goto Print; Down: if(a100) goto Forward; 等价于: for(int i=1; i=100; +i) couti“n”;,break语句的可取之处: / 用break语句的代码段 bool flag=false; / 用于做退出记号 for(int i=1; i100; +i) for(int j=1; j100; +j) if(i*j=651) flag=true; break; else / . if(flag) break; / goto语句的代码段 for(int i=1; i100; +i) for(int j=1; j100; +j) if(i*j=651) goto End; / . End:,7. 再做循环设计( More Loop Designs ),逻辑判断类的语句控制结构: for(所有可能情况) / 可为多重循环 if(条件1不满足) continue; if(条件2不满足) continue; / if(条件n不满足) continue; 输出所要的结果 ,百鸡问题的例子: for(int c=1; c=13; +c) for(int h=1; h=18; +h) for(int s=1; s=96; +s) if(7*c+5*h+s/3-100) continue; if(c+h+s-100) continue; if(s%3) continue; cout“Cock:“c “, Hens:“h “, Chicks:“100-c-hendl; ,级数逼近问题 前后项之差与0的邻域(精度要求)的比较作为循环退出条件,是控制精度的必要方法 项值计算 由循环变量,根据通项公式,直接求第i项的值 也可先给出第一项的值,然后反复根据前项求后项,求级数 的例子: double sum=0, item=1; for(int n=1; abs(item)1e-6; +n) item *= (-1.0)*(2*n-3)/(2*n-1); sum += item; cout“Pi = “ setiosflags(ios:fixed) sum*4endl;,第三章内容,整型 ( int Types ) 整型子类 ( sub-int Types ) 浮点型 ( Floating-Point Type ) C-串与string ( C-string & string ) 数组 ( Arrays ) 向量 ( vectors ) 指针与引用 ( Pointer & References ),整型数的内部表示:二进制补码 位数既定的二进制补码运算没有加减的区别;对于溢出,只是简单的舍弃而不是错误 整型数的表示范围:取决于二进制位数 整型数的操作:+,-,*,/,%,=,!,=,=,=,&,|,&=,|=,&,|,&=,|=,!=,=,+=,-=,*=,/=,%=,+,-,,,? :,编译器的机器字长总是与整型的位长有关如: 32位编译器的整型数一定为32位长 整型字面值分八进制,十进制和十六进制不同表示如: 0123 / 8进制 0x12af3 / 16进制 12345 / 10进制 超过表示范围的整型数其值不可预料或者出错如: int a = 12345678912345678912345; / 错,数据类型: 一定的数据在计算机的内部表示; 该数据所表示的值的集合; 在该数据上的一系列操作。 内部数据类型: 1.整型 长整型,短整型,字符型,布尔型 2.浮点型 单精度,双精度,. 整型子类( Sub-int Types ),字符型: 表示范围: 有符号:-128127 无符号:0255 输出形式与整型数不同: int a = 65; char b = 65; couta“n”; coutb“n”; 结果为: 65 A,枚举型: 自定义整数区间,甚至列举单个整数值 enum Week Mon, Tue, Wed, Thu, Fri, Sat, Sun ; 最大特点是可以给每个值指定一个在程序中直接使用的标记(枚举符) 编程中将其当作整数常量用如: int a = 7; if ( a = Sun) cout “Sundayn”;,布尔型: 表示范围仅含整数和1,也可以表示成true和false,相当于: enum bool false, true ; 因为条件表达式、逻辑运算的结果都是或,所以,相当大数量的表达式的值与布尔型对应,3. 浮点型 ( Floating-Point Types ),浮点数的内部表示: 国际标准IEEE754浮点表示法,它与编程所用的浮点数字面量以及输出的十进制浮点数之间有一个转换关系 浮点数的表示范围: 32位浮点数3.41038 64位浮点数1.810308 浮点数的操作: 常规的加、减、乘、除等操作,4. C-串与string ( C-string & string ),C-串结构 每个字符占据1个字节 一个C-串是一个字符序列,用来表示各种名字或者文字说明 C-串的字符序列的最后总是添加有一个结束标志.即在6个字符的字串(“Hello!”)其空间存储有7个字节 左边三图是不同细节的同一空间结构描述,Hello!0,72 101 108 108 111 33 0,知道了C-串首地址,即可知道整个串,所以可以藉字符首址(字符指针)来操作C-串,但要注意,串的第一个字符与整个串的操作不同,如,C-串的输出操作: char* str = ”Hello”; cout *str endl; / 显示H cout str endl; / 显示Hello,C + 程序设计教程(第二版),第三章 数据类型 Chapter 3 Data Types,清华大学出版社 钱 能,C-串不能直接比较,因为字符指针的比较只是地址值的比较而不是C-串的字典序比较: cout(“join”=”join” ? ” : ”not “)”equaln”; / 字面值比较 char* str1=”good”; char* str2=”good”; cout(str1=str2 ? ” : ”not “)”equaln”; / 字符指针比较 char buffer16=”Hello”; char buffer26=”Hello”; cout(buffer1=buffer2 ? ” : ”not “)”equaln”; / 字符数组比较 结果: not equal not equal not equal,不得不配备专门操作C-串的库函数: strcpy(s1, s2); /从s2拷贝到s1 strcmp(s1, s2); /比较s1与s2 strcat(s1, s2); /连接s2到s1 strrev(s); /将s倒排 strset(s, c); /将s全置为c strstr(s, “ell”); /查找s中的子串 strchr(s,c); /查找s中的字符 等等,但字符指针操作C-串的安全性受到质疑: char* str1; char* str2 = new char5; strcpy(str2, ”ugly”); strcpy(str1,str2); / 错: str1没有空间可储 strcpy(str2, ”Hello”); / 错: str2空间不够大 str2 = ”Hello”; / 错:原来的”ugly”空间脱钩,导致内存泄漏 根源:复制操作须以足够的目的地空间为前提,而所有C-串操作的空间调配都是人为安排的,C-串库函数一概不管,类串string串类自定义串 对应字符指针的C-串操作: string a, s1 = “Hello “; string s2 = “123“; a = s1; / copy cout(a=s1 ? “ : “ not“)“equaln“; / compare couta+s2endl; / concatenate reverse(a.begin(), a.end(); coutaendl; / reverse couta.replace(0,9,9,c)endl; / set cout(s1.find(“ell“)!= -1 ? “ : “not “)“foundn“;/ find string cout(s1.find(c)!= -1 ? “: “not “)“foundn“; / find char,输入C-串的string承载方式: cin的读入方式总是将前导的空格(所谓空格,即包括空格、回车、水平或垂直制表符等)滤掉,将单词读入,在遇到空格时结束本次输入 getline总是将行末的回车符滤掉,将其整行输入 对字串”Hello, How are you?”的两种输入方式 for ( string s; cins; ) couts” “; coutendl; string s; getline(cin, s); coutsendl;,string流: 将string实体看作是一个输入设备给一个像cin这样的取名,作为流来操作,会很有用 例如,如果一个文件aaa.txt,有若干行,每行中含有不知道几个的整数,要输出每行的整数和: ifstream in ( “aaa.txt“ ) ; for ( string s ; getline ( in, s ) ; ) int a, sum=0 ; for ( istringstream sin ( s ) ; sin a ; sum += a ) ; cout sum “n” ; ,5. 数组( Arrays ),数组是同类元素的集合,它的元素排列在连续的空间中,按下标来标记 描述数组必须给出元素类型,元素个数 元素个数必须在编程时确定,任何变量都不允许 int aa ; / 表示int a97; int n = 100 ; int an ; / 错: 元素个数必须预知 const int n = 100 ; int an ; / ok int a ; / 错: 无元素个数 int a = 1, 2, 3, 4, 5 ; / ok:通过初始化确定元素个数,数组初始化可选,但须遵循语法无初始化的数组按规定取默认值 int array15 = 1, 2, 3, 4, 5, 6 ; / 错: 初始值个数超元素个数 int array25 = 1, , 2, 3, 4 ; / 错: 不能以逗号方式省略 int array35 = 1, 2, 3, ; / 错: 同上 int array45 = ; / 错: 初始值不能为空 int array55 = 1, 2, 3 ; / ok: 后面元素取0 int array65 = 0 ; / ok: 元素全为0 int array75 ; / ok: 元素值不确定 int a35 = 1, 2, 3, 4, 5 , 2, 3, 4, 5, 6 , 3, 4, 5, 6, 7 ;,数组有诸多缺陷,造成编程艰难和不安全 int a5 = 1,2,3,4,5, c5; int b5 = a; / 错:无法拷贝创建 c = a; / 错:无法整体拷贝和局部拷贝 a8 = 10; / 错:无法动态扩容和随意增减元素 for(int i=0; i=5; +i) / 错:无法防范下标溢出 ai = i+1; if(a=c) a0 = 2; / 错:不可比较 int a5 = 1; / 初始化呆板,无法获得全初值,二维数组的初始化,下标访问及输出 int array123=1,2,3,4,5; int array223=1,2,4; cout“array1: “; for(int i=0; i2; +i) for(int j=0; j3; +j) coutarray1ij“,“; cout“narray2: “; for(int i=0; i2; +i) for(int j=0; j3; +j) coutarray2ij“,“; cout“n“; 结果为: array1: 1,2,3,4,5,0, array2: 1,2,0,4,0,0,.向量( vector ),向量与数组的共同特征是元素的排列在逻辑上是线性序列结构,可以用下标进行访问 向量可以按需创建,拷贝创建,局部拷贝创建,异类拷贝和创建 灵活的初始化 随意扩容和元素增减 可通过异常来进行下标溢出追踪和处理 可比较 等等,int n=10; int t5=1,2,3,4,5; vector a(n); /按需创建 vector b(10, 1); /元素赋全,灵活的初始化 vector c(b); / 整体拷贝创建 vector f(t, t+5); /异类拷贝创建 vector d(b.begin(), b.begin()+3); /局部拷贝创建d为b的前个元素 a.assign(100); /动态扩容至100个元素,向量常用操作 a.assign(b.begin(), b.begin()+3); / b的前3个元素赋给a a.assign(4,2); / a向量含4个元素,全初始化为2 int x = a.back(); / a的最后一个元素赋给变量x a.clear(); / a向量清空(不再有元素) if(a.empty() cout”empty”; / a判空操作 int y = a.front(); / a的第一个元素赋给变量y a.pop_back(); / 删除a的最后一个元素 a.push_back(5); / a最后插入一个元素,其值为5 a.resize(10); / a元素个数调至10。多删少补,其值随机 a.resize(10,2);/a元素个数调至10。多删少补,新添元素初值为2 if(a=b) cout”equal”; / a与b的向量比较操作,向量操作尤其适合于函数参数传递(-D以上的数组参数的传递十分丑陋): 传递一个矩阵,无论其每行中的元素个数不同.输出之: typedef vector Mat; void print(const Mat ,7. 指针与引用 ( Pointers & Reference ),指针指向存放数据的地址 指针必须初始化或者赋值(指向了数据)后,才能进行间接访问(间访)操作 int* ip; int iCount = 18; int* iPtr = / 间访操作,指针操作与指向数据的类型密切相关 float f = 34.5; int* ip = reinterpret_cast( 结果为: fAddr: 1245064=34.5 iAddr: 1245064=1107951616 int: 100 float: 1.4013e-43,指针加减整数的操作表示空间位置上的挪动 但是挪动的字节数与其数据类型相关: 对float指针加6实际增加了24个字节 对long int指针加5实际增加了20个字节 对char指针减7实际减少了7个字节 对double指针减2实际减少了16个字节,数组名本身就是表示元素集合的首地址 可以将数组名赋给指针 int a3; for(int i=0; i3; +i) ai = i*2; for(int* iP=a; iPa+3; iP+=1) coutiP“: ”*iP“n”; 结果为: 1245036: 0 1245040: 2 1245044: 4,指针限定 const int a = 78; int b = 10; int c = 18; const int* ip = / ok,引用必须初始化,因为引用总是附属于某个实体 int someInt = 5; int 结果为: 8 引用多用在函数参数的传递上,C + 程序设计教程(第二版),第四章 计算表达 Chapter 4 Computational Expressing,清华大学出版社 钱 能,计算表达: 表达计算使用一系列操作,它依赖于特定语言的操作符功能,关乎数据类型的内在特性,故计算表达目的在于深入剖析数据类型对于编程的影响,从而准确使用操作符 学习方法: 1.掌握操作符的功能和相互关系(优先级和结合性) 2.针对内部数据类型,对一些典型的操作中的典型问题留下深刻印象,第四章内容,名词解释( Name Explainations ) 算术运算问题 ( Arithmetic Problems ) 相容类型的转换 ( Cast Campatible Type ) 关系与逻辑操作 ( Relation & Logic Operations ) 位操作 ( Bit Operations ) 增量操作 ( Increment Operations ) 表达式副作用 ( Expressions Side Effects ),1. 操作符 ( Operators ),单目操作符:在一个操作数上施加的操作,如:-3 双目操作符:在二个操作数上施加的操作,如:- 故有些操作符既是单目操作符,又是双目操作符 表达式:若干个操作数和操作符按语法规则构成的操作,如: a = -3-5+6*7/-8,优先级:表达式中多个操作符的执行顺序的规定性,如: *x+; / 先做x+ 结合性:同级操作符的执行顺序的规定性,如: a=b=6; / 先做b=6,. 算术运算问题( Arithmetic Problems ),整型数表示范围有限,如: 不能用整型变量累计的一般循环方法来解: int sum = 0; for(int i=1; i=10000; +i) sum += i; coutsum“n”;,整型数的周而复始性,如: unsigned int a = 2000000000; unsigned int b = 3000000000; cout a+b“n”; 结果为: 705032704 超过表示范围的整型数不是报错,而是表示成一个去掉进位后的余数,中间结果溢出导致计算错误,如: int a = 100000; int b = 100000; int c = 1000; couta*b/c“n“; couta*(b/c)“n“; 结果为: 1410065 10000000,浮点数的精度和有效位 影响比较的正确性,如: float f1 = 7.123456789; float f2 = 7.123456785; if ( f1=f2 ) cout“f1 equal to f2n”; float f = 1.0/3.0; double d = 1.0/3.0; if ( g=d ) cout“g not equal to dn”; 结果为: f1 equals to f2 g not equals to d,浮点数计算的近似性 使精确性比较失败,如: double d1 = 123456789.9*9; double d2 = 1111111109.1; if ( d1!=d2 ) cout “Not samen” ; else cout “Samen” ; if ( abs ( d1-d2 ) 1e-05 ) cout “Samen” ; else cout “Not samen” ; 结果为: Not same Same,3. 相容类型转换 ( Cast Compatible Type ),隐式转换:整型和浮点型都是数值型,所以它们是相容类型指针与整型不相容,如: 7.0 / 3 = 7.0 / 3.0 /将隐式转换成浮点 = 2.33333333 int a = 9; int* ap = 3 + ap /错,从表达能力弱的类型到强的类型的转换 是安全的,反之,会引起精度丢失如: float f = 7.0/3; / doublefloat int a = 7.0/3; / doubleint cout.precision(9); cout fixed 7.0/3 “n” ; cout f “n” a “n” ; 结果为: 2.333333333 2.333333254 2,可以用显式转换的方法,人为控制运算 在一定的数据类型下工作,如: double d = sqrt ( 123456.0 ) ; int a = static_cast(d) * 8 + 5; int b = d * 8 + 5; / 隐式转换为浮点 couta“n”b“n”; 结果为: 2813 2815,4. 关系与逻辑操作 (Relations & Logic Operations ),=与=的区别 int x = 9; if ( x = 0 ) cout “test 1 okn” ; if ( x = 5 ) cout “test 2 okn” ; if ( x = 0 ) cout “test 3 okn” ; 结果为: test 2 ok,!=是操作符,=!不是操作符 int x = 3; if ( x!=9 ) cout “not 9n” ; if ( x=!9 ) cout “impossiblen” ; 条件表达式(x!=0)与(x)等同 int x = 3; if ( x != 0 ) cout x ; if ( x ) cout x ;,不等式连写的错误: int a = -1, b = 0, c = 1; if ( abc ) cout “ok1n” ; if ( ab 结果为: ok2,短路求值的妙用: 避免除0的恶果 if ( b ,5. 位操作( Bit Operations ),左移操作 将整数最高位挤掉,在右端补0。如: int a = 12; / a为:00000000000000000000000000001100 a = a1; / a为:00000000000000000000000000011000,右移操作 在整数的高位挤一个0或1进去(有符号数挤符号位,无符号数挤 ),而整数最低位被挤掉。如: short int a = -2; / 1111111111111110 a = a1; / a=-1 即1111111111111111 unsigned short int b = 65535; / 1111111111111111 b = b1; / b=32767即0111111111111111,位与操作 结果为:( 比较 & 与 & 的区别 ) 4 1,位与操作 | 将两个操作数每一位做或操作,如: int a = 12; / a为: 00000000000000000000000000001100 int b = 6; / b为: 00000000000000000000000000000110 / a | b为: 00000000000000000000000000001110 int cbit = a | b; int clogic = a | b; cout cbit “n” clogic “n” ; 结果为:( 比较 | 与 | 的区别 ) 14 1,.增量操作(Increment Operations),前增量与后增量: 操作数为左值才能做增量操作 const int d = 8 ; d+ ; / 错: d不是左值 3+ ; / 错: 3不是左值 int a = 3, x = 3, b, c ; b = +a ; / a的前增量操作,使b 为4 c = x+ ; / x的后增量操作,使c 为 5 a+ -= 2 ; / 错: a+不是左值 +a += 5; / ok: +a 是左值且a最后为11 +a+; / 错: 先做a+,而a+不是左值,编译的贪吃特征: int a = 3, b = 5, c; c = a + b ; /错: 理解为a+ b c = a + b; /ok: a+ +b c = a + b; /错: 理解为a+ +b c = a + b; /错: 理解为a+ + +b,指针的增量操作: char s110, s2 = “hello” ; char *p1 = s1, *p2 = s2; while ( *p1+ = *p2+ ) ; 等价于下列操作序列: while ( *p2 ) *p1 = *p2 ; p1+ ; p2+ ; *p1 = 0 ;,7. 表达式副作用 ( Expressions Side Effects ),表达式的值 由操作数和操作符决定. 操作符决定对操作数施加的操作 操作的先后由优先级和结合性作主 访问操作数的先后,语言没有明确规定 表达式的副作用 表达式的值因为访问操作数先后顺序不同而不同所引起,使结合律失效 int a = 3, b = 5 ; c = a*b + +b; d = +b + a*b; / c与d不同 /c为21,d 为24 或反之 使括号失效 int a = 3 , b = 5 ; int c = +b * ( a+b ) ; /可能为54,副作用的根源 表达式中,多于一个的实体值发生改变 int a = 3, b = 5 ; c = a*b + +b ; / c和b改变 此时,若其中一个实体被访问两次以上,则副作用可能发生 a = ( b=25 ) += 5 ; / a和b改变,但都被访问1次 a = ( b=25 ) + b ; / 副作用: a,b改变,b被访问2次,消除副作用分开语句写,如: c = a*b + +b ; 可以写成: c = b + a*b ; b+ ; 或者 b+ ; c = b + a*b ;,C+程序设计教程(第二版),第五章 函数机制 Chapter 5 Function Mechanism,清华大学出版社 钱 能,函数 C+的函数是完成既定任务的功能(过程)体,它涵盖了数学函数和一般过程所以基于过程编程本质上就是基于函数编程 函数机制 一是指程序运行过程中对函数调用的数据管理和处理过程 二是指编程中函数的使用规范它包括函数参数的属性和传递规则,函数返回类型的匹配与审查,函数名字的识别原则,函数体效率的选择,函数体中数据的访问权限等,第五章内容,函数性质( Function Character ) 指针参数 ( Pointer Parameters ) 栈机制 ( Stack Mechanism ) 函数指针 ( Function
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 煤矿实务考试真题及答案
- 医学政策法规试题及答案
- 2025江西南昌动物园百花园管理所招聘3人考前自测高频考点模拟试题及答案详解(全优)
- 2025年初中入学化学试题及答案
- 小白欧数与代数试卷及答案
- 吉林省一模语文考试试卷及答案
- 南宁市2025年中考数学试卷及答案
- 主楼砖胎膜专项施工方案
- 中医传统养生咨询方案范文
- 三年级乒乓球活动方案策划
- 全国学科专业目录及名称代码表
- 项目安全管理考核表
- 食品生产企业安全检查表含日管控、周排查及月调度检查记录表
- 单病种住院诊疗费用控制表
- 2023年工业地产市场分析报告
- 老旧小区改造监理实施细则
- 礼品售后服务承诺书
- 音乐治疗和心理剧演出你内心的音乐
- 液塑限自动计算程序
- 掩耳盗铃儿童故事绘本PPT
- CIED植入围手术期抗凝治疗
评论
0/150
提交评论