资源描述
C+语言基础,盐城工学院 惠为君,C+概述,C+的特点 发展历史和未来 (CC+(AT const int Number_of_Student=100; 常变量必须也只能在说明时进行初始化; 常变量初始化之后,不允许再被赋值; 常变量必须先说明后使用; 常变量存储在数据区,并且可以按地址访问,编译时系统对常变量进行类型检查。 C+建议使用常变量,而尽量不使用字面常量。,2.3.3 结束,2.1.7 变 量,1 变量说明,2 变量赋初值,变量,在程序中是指可以改变值的量; 变量必须用标识符进行标识,称为变量名; 变量有类型之分,如整形变量、字符变量等; 任何变量都必须先说明后使用;一是便于编译程序为变量分配空间,二是便于编译时进行语法检查; 变量使用的第一步,是给变量赋初始值;,ok,变量说明,在C+中,变量说明的一般格式为: 存储类型数据类型 变量名1,变量名2, ,变量名n;,下面是变量说明的几个例子: int i, j, k; /说明三个整型变量i, j, k float x, y, z; /说明三个实型变量x, y, z char c1, c2; /说明两个字符型变量c1, c2 double dx; /说明一个双精度型变量dx,变量说明 结束,变量赋初值,(1)变量说明时直接赋初值。 例如:int a=3, b=4, c=5; float x=3.0; (2)用赋值语句赋初值。严格的说,只有前者可称赋初值 例如:float x, e; x=3.5; e=2.71828;,结束,给变量赋初值称为初始化,有两种方法:,2.2 基本运算符,对常量和变量进行运算是通过运算符来实现的. 常量和变量通过运算符组成C+表达式,由表达式再组成C+语句. 运算符是完成对常量和变量进行运算的符号. 把参与运算的对象称为操作数.,按照要求的操作数的个数,运算符分为单目(一元)运算符、双目(二元)运算符和三目(三元)运算符。单目运算符只对一个操作数运算,如负号运算符“”等;双目运算符要求有两个操作数,如乘号运算符“*”等;三目运算符要求有三个操作数,三元运算符只有一个“?:”。,1.算术运算符,ok,运算符重载: 当两个操作数均为整数时,*和/重载为整乘和整除,结果为整数,除法运算后舍去小数取整。如: 5/4/结果为1,整数,当两个操作数均为整数,%定义为求余运算,也称求模运算,结果为两个整数相除后的余数。如果两个整数中有负数,则先用两数绝对值求余,最后结果的符号与被除数相同。例如 6%3/结果为0 6%7/结果为6 7%6/结果为1,C+中算术运算应注意数据溢出问题,即运算结果超出对应数据类型的表示范围。编译程序只会对除法运算时除数为0这种情况提示出错,而特别容易溢出的整数的加、减和乘法运算产生溢出的情况,系统不作为错误处理,程序将继续执行并产生错误的计算结果。因此,程序设计者必须在程序中解决检查并处理整数溢出问题。,只要有一个操作数是实数,两个操作数均转换为double型,*和/重载为普通的乘和除,结果是实数: 5/4.0/结果为1.25,实数,2.关系运算符和逻辑运算符,ok,关系运算符都是二元运算符,包括:(大于)、(不小于)、(小于)、(不小于)、= =(等于)和!=(不等于)。关系运算符完成两个操作数大小的比较,结果为逻辑值true(真)或false(假)。每种可比较大小的数据类型,都重载了关系运算符。不同类型,自动转换为同一类型后,采用对应关系运算符进行比较。,在C+中这两个逻辑值与整数之间有一个对应关系,真对应1,假对应0;反过来,0对应假,非0整数对应真。所以关系运算结果可以作为整数参与算术运算、关系运算、逻辑运算及其他运算。,2.关系运算符和逻辑运算符,设有定义 float a=3.2;int b=5;则: 3ab/结果是?,根据右结合 原则其运算 过程如下:,a,5,b,3.2,3,F, 即0,F即0,逻辑运算符,逻辑运算符用来进行逻辑运算。其操作数和运算结果均为逻辑量。运算结果同样可以作为一个整数参与其他运算。,由于逻辑值和整数之间的对应关系,也允许整型和字符型操作数进行逻辑运算: 21/左值不能是常数 x+y=z;/左值不能是表达式 const int N=30; N=40;/左值不能是常变量,5.自增自减运算,运算分前置和后置两种,前置是先增减后引用,即先对变量自加或自减,用新的值参与其他运算;后置则是先引用后增减,即用变量原来的值参与其他运算,然后再对变量进行自加或自减,例如: int i=5, j=5, m, n; m=i+; /后置;相当于m=i; i=i+1; /结果:i的值为6,m的值为5; n=+j; /前置;相当于j=j+1;n=j; /结果:j的值为6,n的值为6;,意义:使变量当前值加1或减1,再赋给该变量。 要求:操作数只能是变量,不能是常量或表达式;,ok,sizeof( ) 运算符,用于计算一个操作数类型或一个变量的字节数。一般格式为:sizeof (数据类型) 或 sizeof(变量名) 例如:sizeof(int) 值为4 sizeof( float) 值为4 double x; sizeof( x) 值为8,结束,2.2.2 表达式,1 算术表达式,2 关系表达式,3 逻辑表达式和逻辑表达式求值的优化,4 赋值表达式与复合赋值表达式,5 逗号表达式,ok,1.算术表达式,使用时注意: 1、表达式中每个变量都有确定的值时才能进行表达式求值; 2、考虑到算术运算溢出和精度问题,应避免: (1)两个很接近的数直接相减; (2)除数是一个很小的数; (3)整数的连续乘运算。,ok,由算术运算符连接的表达式称为算术表达式,例如:a+b*3 ;,2.关系表达式,例如: abc /*等同于(ab)c,先求ab 的值, 再将结果0或1与c比较大小*/ a+bc+d /*等同于(a+b)(c+d), 结果为0或1*/ y=ab /*计算ab的值0或1 赋给y,y的值为0或1*/,由关系运算符连接的表达式。值为true或false。,ok,3.逻辑表达式和逻辑表达式求值的优化,由逻辑运算符连接的表达式称为逻辑表达式。逻辑表达式的值为true或false。这个值可对应整数1或0参与其他运算。,ok,已知: int a=10, b=20, c=30;float x=1.8, y=2.4;,ay|ay)|(a(b-(!c),t1=1,t2=0,t4=0,-, 求: ab | c+ /结果以及a,b,c的值,t1=1,整个表达式的值为 1,可见: 表达式 c+ 已不需要计算所以: c不变仍为 30,编程人员在使用逻辑运算时应当加以小心,优化计算固然提高了运算效率,但可能产生副作用。所谓副作用,就是出乎设计人员的意料,得到预想不到的结果。,4.赋值表达式与复合赋值表达式,赋值表达式的格式为: 变量 = 表达式 例如:x=5+6;a=b=c=d+1; 在C+中,所有的双目算术运算符和位运算符均可与赋值运算符组合成一个单一运算符,称为复合运赋值算符。包括以下10个: + = = * = / = % = = int i1, i2; float x1, x2; 则表达式 x2=c1*i1+c1*x1+c1*c2 的求值过程为:将c1转换成整型,完成c1*i1,结果表示为t1;将c1和x1均转换成双精度型,完成c1*x1,结果表示为t2;将c1和c2均转换成整型,完成c1*c2,结果表示为t3;然后t1转换成双精度型,完成t1+t2,结果表示为t4;将t3转换成双精度型,完成t4+t3,最后结果转为单精度型赋给x2。,2.赋值类型转换,2.5.3结束,系统自动进行类型转换规则: 1、实型数赋给整形变量:取整;注意溢出; 2、整型数赋给实型变量:先转换为实型数; 3、字符型数赋给整形变量:ASCII码为依据;分为两种情况:符号位是0或1时不同; 若符号位为1,则低位字节不变,高位字节全部置1再赋值。 4、绝对值较大的数赋给表达范围较小的数据类型时,注意溢出;,2.5.4 强制类型转换运算符,ok,其格式为: () /形式一 或 ()/形式二,作用:将表达式强制转换为类型, 但表达式的值及其类型不变。,任意数据类型,赋值运算中,当左值与右值类型不一致时, 系统将按照左值的类型,自动进行强制转换。,例如: 设有以下定义 double x=2.3,y; int i=2,j;,(1) j,2.3,x,2.3, ,2,2,(1) j=x;(2) y=i;,由系统按 左值j 、y 类型自动 完成强制 转换功能,(2) y,2,i,2, ,2.0,2.0,2.5.4 强制类型转换运算符,第三章: 简单输入/输出,3.1 cin cin用来在程序执行期间给变量输入数据, 一般格式为: cin变量名1变量名2变量名n; cout实现将数据输出到显示器的操作, 一般格式为: cout,3.1.1十进制数据的输入输出,请看下例: int i, j; float x, y; coutij;/D cinxy; cout 则程序输出: i=10j=20 x+y=13.1 输出时各数据间是无间隔的,因此应当有意输出一些间隔符,ok,3.1.2 输入字符数据 cin 与cin.get( )的区别 (1) cin 例如:char c1, c2, c3; cinc1;/A cinc2c3; 程序执行到A行时,等待用户输入数据。 若输入:A b c 则cin分别将字符A、b、c赋给变量c1、c2、c3。 cin自动跳过输入的空白字符(包括空格,制表,backspace和回车等)。,(2)cin.get() 例如:char c1, c2, c3, c4; cin.get (c1);/B cin.get (c2); cin.get (c3); 程序执行到B行时,若输入:A b 则执行结果是:字符A、空格、字符b分别赋给变量c1、c2、c3;输入行中仍保留回车符。cin.get()把从键盘上输入的所有字符,包括空白字符,都作为输入字符赋给字符变量,关于字符的输出,请看下例,假定字符c1、c2、c3的值分别为字符a、b和c,执行以下语句序列: coutc1tc2n; coutc3endl; coutOkendl; 屏幕上将输出: ab c Ok 输出时字符之间是无间隔的,如果想让字符间有间隔,必须输出间隔符,补充.字符串输入输出,向一个字符数组中输入字符串时,用函数getline() 。getline() 以用户按下回车键作为结束,在此之前的所有输入都放入字符数组中: cin.getline (char ,int) 其中第一个参数是已经定义的字符数组名,第二个参数是读入字符的最多个数n(包括字符串结束符/0)。,ok,常用cout输出字符串。双引号中的字符串常量照原样输出,程序中通常通过输出字符串常量来输出一些提示信息。字符数组将输出串结束符前所有字符。,补充:字符串输入输出,函数保证在执行时总会为字符串的结束符保留一个字节。当键盘的输入字符(字节)数多于(n1)时,后面的字符不会进入字符数组,字符串结束符自动加在字符数组的最后一个字节中。当输入字符数少于该值时,字符串结束符自动加在输入到字符数组中的最后一个字符的后面。请看下例: char city11; cin.getline(city, 10); / 输入城市名最多5个中文字 cout “城市名:“ city endl;,ok,如果要求按八进制或十六进制输入输出,在cin或cout中必须指明相应的数据形式,oct为八进制,hex为十六进制,dec为十进制。例如: int i, j, k, l; cout oct i;/输入为八进制数 cin hex j;/输入为十六进制数 cin k;/输入仍为十六进制数 cin dec l;/输入为十进制数 cout” hex:” i=” hex i endl; cout” dec:” j=” dec jt; cout” k=” k endl; cout” oct:” l=” oct l; cout dec endl; /恢复十进制输出状态,ok,输入输出的格式控制,(1)各种进制数据的输入输出,执行时输出: Input i(oct), j(hex), k(hex), l(dec): 此时从键盘输入: 032 0 x3f 0 xa0 17 则输出结果为: hex:i=1a dec:j=63k=160 oct:l=21 由于已经在cin中指明数制,因此从键盘输入时,八进制和十六进制数可以省略其开头的0和0 x标志。 在cin或cout中指明数制后,该数制将一直有效,直到重新指明用其他数制。 特别注意:输入数据的格式、个数和类型必须与cin中的变量一一对应,否则不仅使输入数据错误,而且影响后面其他数据的正确输入。,输入输出的格式控制,为了使数据间隔开,还可以用C+提供的函数setw() 指定输出数据项的宽度。例如: int i=2, j=3; float x=2.6, y=1.8; cout,ok,(2)设置数据间隔,第4章 流程控制语句,4.1 选择结构程序设计,对程序的运行流程进行控制,主要通过执行专门用来控制流程的语句来实现。流程控制语句也称为过程化语句。分支语句是三种基本流程控制语句之一。C+提供以下三种分支语句:,if 语句 条件运算符 “ ? : ” swith 语句,4.2.1 if 语句,if语句有两种基本格式为: 1、if () ; 2、if () else;,if 语句,【例41】 输入一个年份,判断是否闰年。 算法分析:假定年份为year, 闰年的条件是 : year%4=0 ,ok,分析:读入三个数,先求出两个数中较大者,再将该大数与第三个数比较,求出最大数。 #include void main() int a, b, c, max; coutabc; coutb) max=a; else max=b; if(cmax) cout “最大数为:”cendl; else cout “最大数为:”maxendl; ,if 语句,【例42】 从键盘上输入三个整数,输出其中的最大数。,ok,if 语句中,如果内嵌语句又是if语句,就构成了嵌套if语句。if 语句可实现二选一分支,而嵌套if语句则可以实现多选一的多路分支情况。 嵌套有两种形式,第一种是嵌套在else分支中: if () ; else if () 语句2; else if else ; 第二种是嵌套在if分支中为: if () if () ; else;,if 语句,/方法1:采用if中嵌套形式 #include void main() int a, b, c, max; coutabc; coutb) if(ac) max=a; /ab且ac else max=c; /ab且ac) max=b; /ac else max=c; /a=b且bc cout最大数max=max;,if 语句,【例3.3】用嵌套if语句完成【例3.2】的任务。,ok,/方法2:采用else中嵌套形式 #include void main() int a,b,c,max; coutabc; coutb ,if 语句,ok,要特别注意else和if的配对关系。C+规定了if和else的“就近配对”原则,即相距最近且还没有配对的一对if和else首先配对。按上述规定,第二种嵌套形式中的else应与第二个if配对。如果根据程序的逻辑需要改变配对关系,则要将属于同一层的语句放在一对“”中。如第二种嵌套形式中,要让else和第一个if配对,语句必须写成: if (表达式1) if (表达式2) 语句1 ; else 语句2 ; 第二种嵌套形式较容易产生逻辑错误,而第一种形式配对关系则非常明确,因此从程序可读性角度出发,建议尽量使用第一种嵌套形式。,请看以下两个语句: /语句1: if(n%3=0) if(n%5=0) coutn是15的倍数endl; else cout n是3的倍数但不是5的倍数 endl; /语句2: if(n%3=0) if(n%5=0) coutn是15的倍数endl; else cout n 不是3的倍数 两个语句的差别只在于一个“”,但表达的逻辑关系却完全不同。,【例44】 某商场优惠活动规定,某种商品单 价为80元,一次购买5件以上(包含 5件)10件以下(不包含10件)打9 折,一次购买10件以上(包含10件) 打8折。设计程序根据客户的购买量计 算总价。,if 语句,算法,1、输入购买件数count,设置单价price=80(元) 2、根据count值确定折扣discount; 3、实际售价amount=price*count*discount; 4、输出amount的值。 算法细化: 2.1、if(count=5/单价,折扣,总价 int count;/购买件数 coutcount; if(count5) discount=1; else if(count10) discount=0.9; else discount=0.8; amount=price*count*discount; cout购买件数:countendl; cout单价:pricet折扣:“ discountendl; cout总价:amountendl; 请在VC+平台上运行,输入不同的件数,使程序所有分支都可以被执行一次。,ok,【例45】 求一元二次方程 ax2+bx+c=0 的根。 其中系数a(a0)、b、c的值由键盘输入。 分析:输入系数a(a0)、b、c后,令delta= b24ac,结果有三种情况: 若delta=0,方程有两个相同实根; 若delta0,方程有两个不同实根; 若delta0,方程无实根。,if 语句,算法,1、输入系数a(a0)、b、c; 2、令delta= b24ac; 3、根据delta的值求方程的根; 4、输出方程的根; 算法细化: 3.1、 if(delta=0)方程有两个相同实根;计算 3.2、 if(delta0)方程有两个不同实根;计算 3.3、 if(delta0)方程无实根;计算,ok,#include #include void main() float a,b,c; float delta,x1,x2; const float zero=0.0001;/定义一个很小的常数 coutabc; couta=atb=bt c=cendl; delta=b*b-4*a*c;,求一元二次方程的根源程序,if(fabs(delta)0) delta=sqrt(delta); x1=(-b+delta)/(2*a); x2=(-b-delta)/(2*a); cout方程有两个不同实根:; coutx1=x1tx2=“ x2endl; else /delta0 cout方程无实根!endl; 请在VC+平台上运行,输入不同的系数,使程序所有分支都可以被执行一次。,3.1.2 条件运算符“?:”,if语句在某些情况下可以用条件运算符“?:”来简化表达。“?:”是一个三元运算符,其构成的表达式格式为: ? : 执行逻辑:先计算表达式1,若其值为真(或非0),则计算表达式2(不计算表达式3),并将该值作为整个表达式的值;反之,即表达式1的值为假或为0,则计算表达式3(不计算表达式2),并将该值作为整个表达式的值。 例如:int a=6,b=7, min=ab?a:b; /min=6 min=ab?+a:+b; /min=7 a=7 b=7 min=ab?a+:b+; /min=6 a=7 b=7,ok,3.1.3 switch语句,用嵌套if语句可以实现多选一的情况。另外C+中还提供了一个switch语句,称为开关语句,也可以用来实现多选一: switch (表达式) case 常量表达式: 语句序列break; case 常量表达式n:语句序列nbreak; default:语句序列 ,switch语句格式,(1)各个case(包括default)分支出现的次序可以任意,通常将default放在最后。 (2)break语句可选,如果没有break语句,每一个case分支都只作为开关语句的执行入口,执行完该分支后,还将接着执行其后的所有分支。因此,为保证逻辑的正确实现,通常每个case 分支都与break语句联用。 (3)每个常量表达式的取值必须各不相同,否则将引起歧义。,(4)允许多个常量表达式对应同一个语句序列。 例如: char score; cinscore; switch (score) case A: case a: coutexcellent; break; case B: case b: coutgood; break; default: coutfair; (5)从形式上看,switch语句的可读性比嵌套if语句好,但不是所有多选一的问题都可由开关语句完成,这是因为开关语句中限定了条件表达式的取值类型。,ok,switch语句例子,【例36】 运输公司对所运货物实行分段计费。设运输里程为s,则运费打折情况如下: s250 不打折扣 250=s500 2%折扣 500=s10005%折扣 1000=s20008%折扣 2000=s300010%折扣 3000=s15%折扣 设每公里每吨的基本运费为p,货物重量为w,折扣为d,则总运费f为:f=p*w*s*(1-d) 设计程序,当输入p、w和s后,计算运费f。,算法,1、输入每吨运费p、货物重量w、运输里程s; 2、根据运输里程s计算折扣d; 3、计算总运费f=p*w*s*(1-d); 4、输出计算结果; 算法细化: 2、根据运输里程s计算折扣d 分析:如果用switch语句,必须使表达式符合语法要求,分析发现,里程s的分段点均是250的倍数,因此,将里程s除以250,取整数商,便得到若干整数值。,ok,switch(c=s/250) case 0: d=0; break; case 1: d=0.02; break; case 2: case 3: d=0.05; break; case 4: case 5: case 6: case 7: d=0.08; break; case 8: case 9: case 10: case 11:d=0.1;break; default:d=0.15; ,s250 不打折扣 250=s500 2%折扣 500=s1000 5%折扣 1000=s2000 8%折扣 2000=s3000 10%折扣 3000=s 15%折扣,#include #include void main( ) int c,s; float p,w,d,f; coutpws; c=s/250; switch(c) case 0: d=0; break; case 1: d=0.02; break; case 2: case 3: d=0.05; break; case 4: case 5: case 6: case 7: d=0.08; break; case 8:case9:case10:case11:d=0.1;break; default:d=0.15; f=p*w*s*(1-d); cout运输单价为pt重量为wt 里程为sendl; cout折扣为dendl; cout运费为fendl; 请在VC+平台上运行,输入不同的里程,使程序所有分支都可以被执行一次。,ok,【例37】 设计一个计算器程序,实现加、减、乘、除运算。 分析:读入两个操作数和运算符,根据运算符完成相应运算。 #include void main( ) float num1,num2; char op; coutnum1opnum2; switch(op) case +: coutnum1opnum2=num1+num2endl; break; case -: coutnum1opnum2=num1-num2endl; break; case *: coutnum1opnum2=num1*num2endl; break; case /: coutnum1opnum2=num1/num2endl; break; default : coutop是无效运算符!; 常量表达式采用字符型,上机运行一下。,循环控制语句是三种基本流程控制语句之一。C+提供以下三种循环语句:,while语句 do-while 语句 for语句,4.3循环结构程序设计,4.3.1 while 语句,while语句也称为当循环。 语句格式为: while (表达式) 循环体语句;,图3.1 while语句的执行流程图,求表达式的值,表达式值为真?,是,否,执行循环体语句,while 语句,【例48】 求1+2+3+4的值。,ok,N个连续整数相加算法 1、设置变量i用来放被加数,变量sum用来放和值,并初始化; 2、从第一个数开始,依次将被加数赋给i,并进行操作sumsum+i; 3、输出sum; 细化算法2: while(还有被加数) i=当前被加数; sum+=i; i准备接受下一个被加数; ,源程序如下: #include void main( ) int i=1,sum=0;/循环初始条件 while(i=4) sum+=i; i+;/修改循环条件 coutsum=sumendl; 在VC+平台上运行,试一试是否正确,ok,while 语句,注意: 在有循环语句的程序中,通常循环开始前对循环条件进行初始化;而在循环体语句中要包含修改循环条件的语句,否则循环将不能终止而陷入死循环。 C+表达方式灵活,上例中的循环语句还可以写成: while (i=n) sum+=i+; 或者 while (sum+=i+, i=n) ;/循环体为空语句 修改程序后在VC+平台上运行,看是否正确,4.3.2 do-while 语句,do-while语句称为直到循环, 格式为: do 循环体语句 while( 表达式 ),否,是,表达式的 值为真?,执行循环体语句,求表达式的值,图3.2 do-while语句的执行流程图,do-while 语句,do/while语句和while语句的区别: 多数情况下可以互相替代。 区别是do/while语句至少执行一次循环体后再判断循环条件是否满足; while语句先判断条件是否满足,然后才执行循环体。,【例49】 输入一段文本,统计文本的行数、单词数及字符数。假定单词之间以空格或跳格或换行符间隔,且文本开始没有空行。 算法分析: 1、逐个读入文本中的字符,直到读到一个输入结束符EOF为止。 2、如何算行数?行结束标志为读到字符n; 3、如何算单词数?设一个变量isword,读到字符时isword=1,读到间隔符时isword=0;如果读到一个间隔符而此时isword值为1,则说明刚读完一个单词;(如果读到一个字符而此时isword值为0,则说明刚开始读一个单词;) 4、如何算字符数?,do-while 语句,ok,算法,1、设置变量line、word、ch分别代表行数、单词数、非分隔字符数,并初始化;设置变量isword来辅助统计单词数; 2、do从键盘读入一个字符c; if ( c=n) line+; if (是单词开头) word+; if (c不是分隔符) ch+; while (c!= EOF ); 3、输出统计结果。,将下面的程序在VC+平台上运行,试一试是否正确,#include void main( ) char c; int line=0, word=0, ch=0; /ch为非分隔字符数 int isword=0; do c=cin.get(); if (c= n) line+; /遇换行符行数+1 if (c!= ,4.3.3 for 语句,for循环语句的格式为: for ( ; ; ) ,ok,for语句、while语句、do/while语句实现相同的功能:1+2+3+4,int i=1,sum=0; /循环初始条件 while(i=4) sum+=i; i+; /修改循环条件 ,int i=1,sum=0; /循环初始条件 do sum+=i; i+;/修改循环条件 while(i=4);,for( int i=1,sum=0; i=4; i+ ) sum+=i; /*习惯上:表达式1:循环初始条件;表达式2:循环终止条件;表达式3:修改循环条件*/,ok,for 语句的应用,for语句的几点说明: 1、是先判断型的,同while语句; 2、使用更为灵活: 三个表达式可以是任意表达式,因此他们就可以实现循环初始化、计算、修改循环条件等任务,而不一定非在循环体中进行;,for 语句的应用,【例411】 设计程序输出Fibonacii数列的前20项,要求每行输出5个数据。 Fibonacii数列定义如下:,算法分析:除了第0项和第1项外,每一项都是由类似方法产生,即前两项之和;所以求当前项时,只需要记住前两项;程序不需要为每一项设置专用变量; 属递推算法。,算法: 1、设置变量n表示第几项,变量 f 1和 f 2用来记住当前项f 3之前的两项 ;变量初始化n=0; 2、while (当前项不到第20项) if (当前项是第0项) f 1=0; if (当前项是第1项) f 2=1; if (当前项是第2项或更高项)f 3=f 1+f 2; 按要求输出 f 3 ; f 1=f 2; f 2=f 3; /记住最近两项 当前项后移一位; ,【例311】 设计程序输出Fibonacii数列的前20项,要求每行输出2个数据。Fibonacii数列定义如下: 程序如下: /文件名:Ex3_11.cpp #include #include void main() int fib0=0,fib1=1,fib2; coutsetw(5)fib0setw(5)fib1 endl; for(int n=3;n=20;n+) fib2=fib0+fib1; coutsetw(5)fib2; if(n%5=0) coutendl; /控制每行2个数据 fib0=fib1; fib1=fib2; ,for 语句的应用,在VC+平台上运行 运行结果: 0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181,【例4.12】 输入一个不超过5位的整数,将其反向后输出。例如输入247,变成742输出。 算法分析: 1、将整数的各个数位逐个位分开,用一个数组保存各个位的值,然后反向组成新的整数。 2、将整数各位数字分开的方法是,通过求余得到个位数,然后将整数缩小十倍,再求余,并重复上述过程,分别得到十位、百位,直到整数的值变成0为止。,for 语句的应用,ok,数据: 1、设置变量num表示输入的整数,整型数组digit5用来存放num 的各个位;变量i用来表示数组的当前下标; 算法: 1、输入num; 变量初始化:i=0; 2、while (num!=0) num对10取余,得num的当前个位数digiti; num整除10,即去掉个位数,十位变个位,百位变十位,; i+;数组digit准备记录下一位; 3、将数组元素按下标从高到低的顺序输出;,程序如下: #include void main() int num,subscript; int digit5; coutnum; cout0); for(int i=0;isubscript;i+)/整数的反向组合 num=num*10+digiti; cout反向后整数为:numendl; 在VC+平台上运行,试一试是否正确,4.3.5 循环的嵌套,【例313】 打印九九表。打印格式为: * 1 2 3 4 5 6 7 8 9 1 1 2 2 4 3 3 6 9 9 9 18 27 36 45 54 63 72 81,当循环语句中的循环体中又有循环语句时,就构成了嵌套循环。 嵌套层次一般不超过3层,已保证可读性。,循环的嵌套,分析: 1、计算机的输出是按行进行的,因此可以先用一个循环语句输出第一行表头。 2、表中各行数据的输出可以用下面的算法描述: for (i=1; i10; i+) couti; /输出行号 输出第i行数据; /A coutendl; /准备输出下一行 ,3、第A行需要进一步细化。由于第i行数据是一组有规律的数列,每个数的值是其所在行与列的乘积,因此输出第i行可以: for (j=1; j10; j+) coutsetw(4)i*j; 4、按上述算法输出的每一行都将有九列,即打印出的是矩形表而不是下三角形表。进一步分析发现每一行的列数与所在行数相关,因此要输出三角形表,上面的循环语句需稍作修改: for (j=1; j=i; j+) coutsetw(4)i*j; 将此语句放到顶层算法的A行即可。,循环的嵌套,算法: 1、输出表头,用一个循环语句即可; 2、输出表体: for (i=1; i10; i+) couti; /输出行号 输出第i行数据; /A coutendl; /准备输出下一行 3、A行细化: for (j=1; j=i; j+) coutsetw(4)i*j;,循环的嵌套,在VC+平台上运行下面的程序: #include #include void main() coutsetw(3)*setw(4) ; for(int i=1;i10;i+) coutsetw(4)i; /输出表头(乘数) coutendlendl; for(i=1;i10;i+) coutsetw(3)isetw(4) ; /输出行号(被乘数) for(int j=1;j=i;j+) coutsetw(4)i*j;/输出表中数据(乘积) coutendl; /准备输出下一行 ,3.2.4 循环嵌套_打印九九表,4.4 转向语句,441 break语句,444 return语句,443 goto 语句,442 continue语句,4.4.1 break 语句,break语句只能用在switch语句和循环语句中,用来跳出switch语句或提前终止循环,转去执行switch语句或循环语句之后的语句。 在for循环中可以用break结束循环: for(; ;) if() break; ,break 语句应用,【例4.14】 给定正整数m,判定其是否为素数。 分析:如果m2,m是素数的条件是不能被2,3,,(取整)整除。因此可以用2,3,,(取整)逐个去除m,如果被其中某个数整除了,则m不是素数,否则是素数。算法属于穷举法。 1、输入被测数m(m2);令整型变量 k= sqrt(m) 2、判断m是否素数:设置辅助整型变量i, 使i从2开始直到k依次测试m能否整除i, 若能,则不是素数;for( i=2;i=k;i+)if(m%i=0) break; /* 条件满足,m不是素数,停止测试,结束for语句。*/ 3、根据i是否已达到k,输出结果是否为素数。,#include #include void main() int m,i,k; coutm; if(m=2) coutk) cout m是素数endl;/循环提前终止表示是非素数 else cout m不是素数endl; 在VC+平台上运行,改一下,使程序自动算出100以内的素数,4.3.2 continue 语句,continue语句只能用在循环语句中,用来终止本次循环。当程序执行到continue语句时,将跳过其后尚未执行的循环体语句,开始下一次循环。下一次循环是否执行仍然取决于循环条件的判断。 continue语句与break语句的区别在于,continue语句结束的只是本次循环,而break结束的是整个循环。,例:输出1100内3的倍数。 分析:设置整型变量I从1变化到100,依次测试I是否3的倍数,算法属于穷举法。 for (I=1;I=100;I+) if ( I%3!=0) continue; /I不是3的倍数,不输出,继续下一个I; 输出I的值;/I是3的倍数才输出 ,4.3.3 goto 语句,goto语句和标号语句一起使用,所谓标号语句是用标识符标识的语句,它控制程序从goto语句所在的地方转移到标号语句处。goto语句会导致程序结构混乱,可读性降低,而且它所完成的功能完全可以用算法的三种基本结构实现,因此一般不提倡使用goto语句。但在某些特定场合下goto语句可能会显出价值,比如在多层循环嵌套中,要从深层地方跳出所有循环,如果用break语句,不仅要使用多次,而且可读性较差,这时goto语句可以发挥作用。,4.3.4 return 语句,return语句用于结束函数的执行,返回调用者,如果是主函数,则返回至操作系统。 利用一个return语句可以将一个数据返回给调用者。通常,当函数的返回类型为void时, return语句可以省略,如果使用也仅作为函数或程序结束的标志。,在结构化程序设计中,函数是将任务进行模块划分的基本单位。,第四章 函数 和编译预处理,在面向对象的程序设计中,对数据的操作总是封装在函数中,一个函数描述一种操作。不要完全按模块思想讲。也是让学生处于面向对象程序设计的氛围中。这样第5章的教学会顺利一些。,要掌握函数的使用,必须理解函数调用时的内部实现机制,以及与此相关的内存分配机制、变量生命期和作用域。,本章还将介绍关于函数重载的概念,介绍递归算法、内联函数、默认参数函数以及多文件组织、编译预处理、工程文件的概念和运行库函数。,第四章 函数 和编译预处理,51 函数的定义与调用,5. 5 内联函数,54 作用域和存储类,53 函数的嵌套和递归调用,52 函数的参数传递, 返回值及函数原型说明,5 9 程序多文件组织,58 编译预处理,5 7 函数重载,5 6 具有缺省参数值的函数,5.1 函数的定义与调用,5.1.1 函数概述,5.1.2 函数定义,5.1.3 函数调用,4.1.1 函数概述,函数是C+程序的基本组成模块。,通过函数,可以把一个复杂任务分解成为若干个易于解决的小任务。充分体现结构化程序设计由粗到精,逐步细化的设计思想。,组成C+程序的若干函数中,有一个称为main()(Winmain())函数,是程序执行的入口,它可以调用其他函数。而其他一般函数既可以调用也可以被调用。函数之间的调用关系见下图:,5.1.1 函数概述,5.1.1 函数概述,函数按是否带有参数,分为: 无参函数和有参函数,4.1.1结束,函数按其是否系统预定义分为两类: 一类是编译系统预定义的,称为库函数或标准函数,如一些常用的数学计算函数、字符串处理函数、图形处理函数、标准输入输出函数等。这些库函数都按功能分类,集中说明在不同的头文件中。用户只需在自己的程序中包含某个头文件,就可直接使用该文件中定义的函数。 另一类是用户自定义函数,用户可以根据需要将某个具有相对独立功能的程序定义为函数。,5.1.2 函数的定义,1. 无参函数,2. 有参函数,1 无参函数,定义格式为: 数据类型函数名(void)函数体,例: 下面函数的功能是打印一个表头 void TableHead ( ) cout*endl; cout* example *endl; cout*endl; ,有参函数,有参函数的定义格式为 数据类型函数名 (参数类型1形式参数1,参数类型2形式参数2,函数体,例: 下面函数的功能是返回两个整数中较大一个的值 max (int a, int b) return(a=b?a:b); ,定义函数时可能会涉及若干个变量,究竟哪些变量应当作为函数的参数?哪些应当定义在函数体内?这有一个原则:作为一个相对独立的模块,函数在使用时完全可以被看成 “黑匣子”,除了输入输出外,其他部分可不必关心。从函数的定义看出,函数头正是用来反映函数的功能和使用接口,它所定义的是“做什么”,在这部分必须明确“黑匣子”的输入输出部分,输出就是函数的返回值,输入就是参数。因此,只有那些功能上起自变量作用的变量才必须作为参数定义在参数表中;函数体中具体描述“如何做”,因此除参数之外的为实现算法所需用的变量应当定义在函数体内。 C+中不允许函数的嵌套定义,即在一个函数中定义另一个函数。,提示,5.1.3 函数的调用,在C+中,除了主函数外,其他任何函数都不能单独作为程序运行。任何函数功能的实现都是通过被主函数直接或间接调用进行的。所谓函数调用,就是使程序转去执行函数体。 无参函数的调用格式为: 函数名( ) 有参函数的调用格式为: 函数名(实际参数表) 其中实际参数简称实参,用来将实际参数的值传递给形参,因此可以是常量、具有值的变量或表达式。,5.1.3 函数的调用,main( )函数,调用max(2.5,4.7 ),函数max(2.5,4.7 ),return 4.7,主程序后续语句,【例41】 输入两个实数,输出其中较大的数。其中求两个实数中的较大数用函数完成。 程序如下: #include float max(float x,float y) return(x=y?x:y); void main() float x,y; coutxy; coutx和y中较大数为max(x,y)endl; ,5.2 函数的参数传递、返回值及函数原型说明,521 函数的参数传递及传值调用,523 函数原型说明,522 函数返回值,函数调用首先要进行参数传递,参数传递的方向是由实参传递给形参。传递过程是,先计算实参表达式的值,再将该值传递给对应的形参变量。一般情况下,实参和形参的个数和排列顺序应一一对应,并且对应参数应类型匹配(赋值兼容),即实参的类型可以转化为形参类型。而对应参数的参数名则不要求相同。,5.2.1 函数的参数传递及传值调用,按照参数形式的不同,C+有两种调用方式:传值调用和引用调用。顾名思义,传值调用传递的是实参的值,本章主要介绍传值调用。关于引用调用,将在第五章类与对象中介绍。,5.2.1 函数的参数传递及传值调用,调用power(a,3 ),函数power(a,3 ),return 912673,主程序后续语句,【例52】 说明实参和形参对应关系的示例。 #include #include float power(float x,int n) /求x的n次幂 float pow=1; while(n-) pow*=x; return pow; void main() int n=3; float x=4.6; char c=a; coutpower(x,n)=power(x,n)endl; coutpower(c,n)=power(c,n)endl; coutpower(n,x)=power(n,x)endl; ,5.2.2 函数返回值,return语句的一般格式为: return 表达式; 函数的计算结果通过该语句传递回主调函数。,【例43】设计函数,根据三角形的三边长求面积。如果不能构成三角形,给出提示信息。 分析:函数为计算三角形面积,一般三角形返回面积值,若不能构成三角形则返回-1。设计一个主函数完成函数测试。根据返回值情况输出相应结果。 程序见下页:,#include #include float TriangleArea(float a, float b, float c) if (a+babc; area=TriangleArea(a,b,c); if(area=-1) cout(a,b, c )不能构成三角形!endl; elsecout三角形(a,b,c )面积为:areaendl;,5.2.2 函数返回值,函数可以有返回值,也可以没有返回值。对于没有返回值的函数,功能只是完成一定操作,应将返回值类型定义为void ,函数体内可以没有return语句,当需要在程序指定位置退出时,可以在该处放置一个:,return ;,4.2.2结束,5.2.3 函数原型说明,函数原型是一条以分号结束的语句,实际上就是所定义函数的函数头,形如: 函数返回值类型函数名 (形参表),语法上对程序文件中函数的排列次序是没有固定要求的,只要满足先定义后使用即可。但从结构化程序设计的角度,通常是先调用后定义。使用函数原型,则既符合由粗到精的思维方式,又满足了语法要求。,其中形参表可以逐个列出每个参数的类型和参数名,也可以列出每个形参的类型,参数名可省略,各形参之间以逗号分隔。函数原型和所定义的函数必须在返回值类型、函数名、形参个数和类型及次序等方面完全对应一致,否则将导致编译错误。,下面是一个使用结构化程序设计思想开发的企业管理报表程序的框架。它使用了函数原型说明。 #include void menu_print(); void account_report(); void engineering_report(); void marketing_report(); void main() int choice; do menu_print(); cinchoice; while(choice=4); switch(choice) case 1: account_report(); break; case 2: engineering_re
展开阅读全文