《程序基本结构》PPT课件.ppt
2023/7/28,1,第二章 程序基本结构,2.1 关系运算和逻辑运算2.2 分支结构2.3 循环结构2.4 break和continue语句2.5 goto 语句2.6 指针程序设计2.7 经典算法举例,2023/7/28,2,引言,第一章中我们学习了顺序结构的C程序设计方法,但是实际应用中,很多问题仅有顺序结构的方法是无法解决的。,算法,算法,2023/7/28,3,问题1的算法:,S1:输入3个整数,分别赋值给a,b,cS2:如果ab,则a bS3:如果ac,则acS4:如果bc,则bcS5:输出a,b,c的值,分支结构,输入a,b,c的值,a b,输出a,b,c的值,a c,bc,2023/7/28,4,2.1关系运算和逻辑运算2.1.1 关系运算符和关系表达式,一、关系运算符种:、=、=、!=说明:1、优先级:前4种相同,后2种也相同,但前4种高于后两种;所有关系运算符的优先级都低于算术运算符而高于赋值运算符。2、结合性:自左至右,ab-c,a(b-c),a=b=c,a=(b=c),a=b!=c,a=(b!=c),2023/7/28,5,二、关系表达式用关系运算符将两个表达式连接起来的式子。其中被连接的表达式可以是算术表达式、关系表达式、逻辑表达式、赋值表达式或字符表达式。如:a+bc+d、xy=c+d、aA,关系表达式的值只能是1或0,当表达式成立即为“真”时,值为整数1;否则为“假”,值为整数0。因此可看作整型表达式。,假设a=3,b=2,c=1,求以下关系表达式的值:ab(ab)=cabc f=ab=c,1,1,0,1,2023/7/28,6,2.1.2 逻辑运算符和逻辑表达式,一、逻辑运算符种:&|!,、优先级:!(非)&(与)|(或),、结合性:!是右结合性,&和|是左结合性,、逻辑运算真值表:,例:,ab&x/y,(ab)&(x/y),a=b|b!=c,(a=b)|(b!=c),a=1|!b,(a=1)|(!b),二、逻辑表达式逻辑表达式的值应该是“逻辑真”或“逻辑假”。语言以数值代表“真”,以数值代表“假”;但参加运算的运算量可以是任何数值,进行判断时,非零值代表“真”,零值代表“假”。,若a=100,b=5,则!a=?a&b=?a|b=?!a&b=?4&0|2=?,a+b|ca&038&2|54-!0,0,1,1,0,1,1,0,0,表示x-1,1区间,应写为:x=-1&x=1不能写为:-1=x=1,规律:在逻辑表达式的求解过程中,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符。,、在&表达式中,若左端为,则不必再计算右端,表达式值为0;即:0&a=0、类似有:1|a=1(假设a、b取值为1或者0),0|a=a 0&a=01|a=1 1&a=aa|a=a a&a=aa|!a=1 a&!a=0!(a|b)=!a&!b!(a&b)=!a|!b,例:a=1,b=2,c=3,d=4,m=n=1(m=ab)&(n=cd)m=?n=?,0,1,注意:,2023/7/28,9,C语言运算符的“优先级口决”1,小括中括指向点,(),-,.)非反后来自加减;(!+-)负类指针有地址,(-,类型转换,*,(从右至左)逗号不是停顿符,(,)顺序求值得结果.(顺序求值运算符),2023/7/28,10,C语言运算符的“优先级口决”2,括号成员第一;/括号运算符()成员运算符.-全体单目第二;/所有的单目运算符比如+-+(正)-(负)指针运算*/注意顺序:优先级(|)底于 优先级(&)条件高于赋值,/三目运算符优先级排到 13 位只比赋值运算符和“,”高/需要注意的是赋值运算符很多!逗号运算级最低!/逗号运算符优先级最低,2023/7/28,11,2.2分支结构2.2.1 单分支结构,例2.1:输入两个整数,按从小到大的顺序输出这两个数。,算法:S1:输入两个整数a,bS2:如果ab,则a bS3:输出a,b,C语言单分支结构:if(表达式)语句;,2023/7/28,12,if(表达式)语句,一般形式:,流程图:,注意:此位置不使用分号“;”!,#include void main()int a,b,temp;printf(Input a,b:);scanf(%d%d,/*按从小到大顺序输出*/,例2.1的C语言程序如下:,复合语句:在同一个条件下作为一个整体执行的多条语句,例2.2输入三个数x1,x2,x3,按从小到大的顺序输出这三个数。,#include void main()int x1,x2,x3,temp;scanf(“%d%d%d”,输入:3 5 1输出:1,3,5,2023/7/28,15,2.2.2 双分支结构,例2.3:输入两个整数,输出其中较大的一个。,算法:S1:输入两个整数a,bS2:如果ab,则输出a,否则输出b,C语言单分支结构:if(表达式)语句1;else 语句2;,2023/7/28,16,一般形式:,if(表达式)语句1else 语句2,流程图:,2023/7/28,17,例2.3 输入两个整数,输出其中较大的一个。,N-S流程图,#includevoid main()int x1,x2;scanf(“%d%d”,2023/7/28,18,判断某年是否闰年?若是,输出XXXX年是闰年,若不是,输出XXXX年不是闰年。,提示:闰年的判断,能被4整除不能被100整除,或者能被400整除的都是闰年。,2023/7/28,19,2.2.3 多分支结构一、if语句嵌套,一般形式:,流程图:,if(表达式1)语句1else if(表达式2)语句2 else if(表达式3)语句3 else if(表达式n)语句n else 语句n+1,关于if语句的说明:,1、表达式一般为关系表达式或逻辑表达式。但在C语言中它也可以是任意的数值表达式。,if(3)n=1;,if(a)printf(%d,a);,if(n=3-3)x=1;else x=-1;,2、表达式后面不能有任何标点符号!,3、else只能与if配对使用。仅else本身不能单独作为一个语句使用。,if(x5);y=x;else y=2*x-1;,if(x5);y=x;else y=2*x-1;,将出现语法错误,2023/7/28,21,4、每个语句序列可以是一个语句也可以是若干个语句,但要用花括号括起来构成复合语句。,if(ab)t=a;a=b;b=t;,if(a+bc,复合语句的花括号后不能再写分号。复合语句在语法上是一个整体,相当于一个语句。,2023/7/28,22,5、if语句的嵌套,在if语句的原“语句”中又包含一个或多个if语句,1.if(表达式1)if(表达式2)语句,2.if(表达式1)语句1 else if(表达式2)语句2,3.if(表达式件1)语句1 else if(表达式2)语句2 else 语句3,4.if(表达式1)if(表达式2)语句1 else 语句2,二义性?,语言规定:else总是与它前面最近的且未曾配对的if配对。,if(表达式1)if(表达式2)语句1 else 语句2,if(表达式1)if(表达式2)语句1 else 语句2,2023/7/28,23,例2.4 输入3个数,判断组成什么类型三角形,if(a+b)c,2023/7/28,24,例2.5 编程求解函数:,程序1:if(x0)y=-1;else if(x=0)y=0;else y=1;,程序2:if(x=0)if(x0)y=1;else y=0;else y=-1;,eg502.c,程序3:y=0;if(x!=0)if(x0)y=1;else y=-1;,2023/7/28,26,例:求一元二次方程ax2+bx+c=0的根,a,b,c由键盘输入。,分析:对于一元二次方程有以下几种可能:a=0,不是二次方程;b2-4ac=0,有两个相等的实根;b2-4ac0,有两个不等的实根;b2-4ac0,有两个共轭复数根。,例2.6 求一元二次方程ax2+bx+c=0的根,a,b,c用键盘输入。,#includevoid main()float a,b,c,d,x1,x2,realpart,imagpart;scanf(“%f%f%f”,a,b,c);if(fabs(a)1e-6),x1=(-b+sqrt(disc)/(2*a);x2=(-b-sqrt(disc)/(2*a);printf(“has distinct real roots:%f,%fn”,x1,x2);else realpart=-b/(2*a);imagepart=sqrt(-disc)/(2*a);printf(“%f+%fin”,realpart,imagpart);pritnf(“%f-%fin”,realpart,imagpart);,2023/7/28,28,1、条件运算符:?:(C中唯一的三目运算符)优先级仅高于赋值类,右结合性,2、条件表达式的一般形式:表达式1?表达式2:表达式3,运算过程:首先求表达式1的值,若为真(非0),则求表达式2的值,且整个表达式的值为表达式2的值;若表达式1为假(0),则求表达式3的值,且整个表达式的值为表达式3的值。,二、条件运算符,2023/7/28,29,(2)右结合性:,(3)“表达式1?表达式2:表达式”中,表达式2和表达式3不仅可以是数值表达式,还可以是赋值表达式或函数表达式例如:ab?(a=100):(b=100)ab?printf(“”%dn”,a):printf(“%dn”,b),(4)表达式1、表达式2和表达式3的类型都可以不同。表达式值的类型是表达式2、3中类型较高的类型。例如:xy?1:1.5 表达式值是double类型,(1)优先级高于赋值,低于关系运算符和算数运算符,例:x=ab?a:b+1;,x=(ab)?a:(b+1);,ab?a:cd?c:d,ab?a:(cd?c:d),if(ab)x=a;else x=b+1;,2023/7/28,30,例2.7:输入一个字符,如果是大写字母,转换为小写,如果不是不转换。最后输出。,#includevoid main()char ch;scanf(“%c”,*/,2023/7/28,31,三、switch(多分支)语句,switch结构与else if结构是多分支选择的两种形式。else if:多条件并列测试,从中选一switch:单条件测试,从多种结果中选取一种执行,2023/7/28,32,1、格式:,switch(表达式)case 常量表达式1:语句组1;break;case 常量表达式2:语句组2;break;case 常量表达式n:语句组n;break;default:语句 组n+1,2、功能:先计算表达式的值,测试该值是否与某常量表达式的值相同、若有相同者,流程转向其后面的语句执行、若无,再看有没有default部分:若有default,则执行其后面的语句;若无default,则switch语句什么也不做,流程转向其后继语句。,说明:,1、switch后面括号内的表达式可以是整型,也可以是字符型2、各个case后常量表达式的值必须互不相同;3、各个case和default的出现次序不影响执行结果;4、case后的语句为复合语句时可省略花括号;,例:#include void main()int x,y;scanf(“%d”,5、case后常量表达式只起语句标号的作用,每个case之后通常都有一个break,使流程跳出switch语句,否则流程转到下一个case(default)中继续执行;,2023/7/28,34,6、多个case可以共用一组执行语句;,case 6:case 7:printf(Resetn);break;,但不能写成:case 6,7:printf(Resetn);break;,7、switch语句可以嵌套;但有多层switch语句时,break只能退出本层的switch语句体;,2023/7/28,35,举例:在学生成绩管理中,成绩经常要在百分制与等级制之间进行转换。90分以上为A等,80-89为B等,70-79为C等,60-69分为D等,其余为E等。编制程序,根据输入的百分制,输出对应的等级。,void main()int score;printf(Input score of student:);scanf(%d,2023/7/28,36,void main()int score,temp;printf(Input score of student:);scanf(%d,break;,2023/7/28,37,简单选择界面的编程。从键盘输入整数,输出不同的字符串:输入1,输出Good morning;输入2,输出Good afternoon;输入3,输出Good evening;输入4,输出Good night;输入其它数字,输出Bye-bye。,2023/7/28,38,算法,2.3 循环结构,2.3.1 循环结构的引出,2023/7/28,39,问题2的算法:,算法1:直接写出算式 S1:result=1+2+3+4+5+100,容易实现吗?,算法2:考虑到1+2+3+100可以改写为:(1+2)+3)+100)S1:p1=1+2 S2:p2=p1+3 S3:p3=p2+4 S99:p99=p98+100,结果在p99里。,定义99个变量,容易实现吗?,注意观察:每一步都类似,2023/7/28,40,算法3:S0:p=0,i=1 S1:p=p+i,i=i+1 S2:p=p+i,i=i+1 S3:p=p+i,i=i+1 S99:p=p+i,i=i+1 S100:p=p+i,i=i+1,完全一样的99步,算法4:S0:p=0,i=1(循环初值)S1:p=p+i,i=i+1(循环体)S2:i=100,则返回重新执行步骤S1及S2;否则,算法结束(循环控制)。,循环结构,2023/7/28,41,循环控制结构一般由四部分组成:、进入条件、退出条件、循环体:循环体需要完成的功能(需要重复执行的语句)、循环变量的修正,根据进入条件和退出条件,循环控制结构可以分为三种形式:、while结构:退出条件是进入条件的反条件。即满足 条件时进入,重复执行循环体直到进入的条件不再满足为止。、do-while结构:无条件进入,执行一次循环体后再判断是否满足再进入循环的条件。、for结构:与while结构类似,但结构更紧凑。适用于循环之前循环次数就已经确定的情况。,2023/7/28,42,使用形式:while(表达式)语句;,特点:先判断表达式,后执行语句,while 语句,2023/7/28,43,例:求1+2+3+100,i=1,sum=0,i=100,sum=sum+ii=i+1,假,真,2023/7/28,44,void main(),int i,sum;,i=1;sum=0;,while(i=100)sum=sum+i;i+;,printf(“sum=%dn”,sum);,注意:while起作用的范围,注意:要有改变循环结束条件的语句,2023/7/28,45,void main(),int i,n,sum;,i=1;sum=0;,while(i=n)sum=sum+i;i+;,printf(“sum=%dn”,sum);,计算 1+2+3+n(n为任意正整数),scanf(%d,思考问题:循环结束后循环变量的值是多少?,2023/7/28,46,void main(),int i,n,sum;,i=1;sum=0;,while(i=n)sum=sum+i;i=i+2;,printf(“sum=%dn”,sum);,scanf(%d,计算 1+3+5+7+n(n为奇数),2023/7/28,47,例:输入一个字符,如果是大写字母,转换为小写,如果不是则不转换。输入“0”结束程序。,#include void main()char ch;while(ch=getchar()!=0)ch=(ch=A,2023/7/28,48,2.3.3 do-while 语句,使用形式:do 循环体语句 while(表达式);,特点:先执行循环体语句,后判断表达式,注意:、循环部分为多个语句时,必须用大括号构成复合语句;、循环体中应有使循环趋于结束的语句,2023/7/28,49,例:求1+2+3+100,int i,sum;,i=1;sum=0;,do sum=sum+i;i+;while(i=100);,printf(“%dn”,sum);,void main(),2023/7/28,50,while 和 do-while 循环的比较(?不同之处),main()int sum=0,i;scanf(“%d”,main()int sum=0,i;scanf(“%d”,2023/7/28,51,2.3.4 for 语句,一般形式:for(表达式1;表达式2;表达式3)语句,一般使用格式:for(循环变量赋初值;循环条件表达式;循环变量修正值)循环体;,2023/7/28,52,执行过程:(1)求解表达式1(2)求解表达式2,若其值为真(值为非0),则执行for语句中指定的内嵌语句,然后执行(3)。若为假(值为0),则结束循环,转到(5)。(3)求解表达式3(4)转回执行(2)(5)循环结束,执行for语句下面的一个语句,for(表达式1;表达式2;表达式3)语句,2023/7/28,53,例:求1+2+3+100,void main()int i,sum=0;for(i=1;i=100;i+)sum=sum+i;printf(“%d”,sum);,循环变量赋初值,循环条件,循环变量修正,循环体,2023/7/28,54,例:计算某个班英语成绩的平均分,学生人数和每个学生的成绩由键盘输入。,void main()int i,n;float s,sum,ave;sum=0;for(i=1;i=n;i+)ave=sum/n;printf(“ave is%f”,ave);,scanf(%d,scanf(%d,想想这条语句是否能放到循环体内?,2023/7/28,55,for语句的三个表达式都可以缺省,但两个分号不能缺省;,如果在for语句之前已经给循环变量赋初值,则for语句的循环变量赋初值部分可以省略,但其后得分号不省略;,也可以将循环变量修正值的工作纳入到循环体中去做;,说明:,i=1;for(;i=10;i+)m=m*i;,如:,for(i=1;i=10;)m=m*i;i+;,如:,也可以省略for语句的第一和第三部分;,i=1;for(;i=10;)m=m*i;i+;,如:,for(;),但是注意不能两处同时修正值!,2023/7/28,56,通常不缺省表达式2;有时缺省表达式2,此时不判断循环条件,循环将无终止的执行,即认为表达式2始终为真;在循环体内用if和break控制循环结束。,for(i=1;i+)if(条件)break;sum=sum+i;,如果有多个循环变量赋初值,或多个循环变量值要修正,应在各变量之间用逗号隔开。,for(i=1,j=10;i=j;i+,j-)k=i+j;,如:,循环条件表达式一般是关系表达式或逻辑表达式,但也可以是数值表达式或字符表达式,每次系统判断该表达式的结果不为0,就执行一遍循环体。,for(m=0;(c=getchar()!=!;)m=m+c;,如:,考虑问题:运行程序时如何停止循环?,2023/7/28,57,for、while、dowhile的互相转化,i=1;sum=0;do sum=sum+i;i+;while(i=100);,for(i=1;i=100;i+)sum=sum+i;,i=1;sum=0;while(i=100)sum=sum+i;i+;,2023/7/28,58,输出所有的水仙花数。(水仙花数就是一个三位数,这个数正好等于该数的每一位的立方和。例如:153=1*1*1+5*5*5+3*3*3),void main()for()a=i/100;c=i%10;,2023/7/28,59,补充:循环的嵌套,一个循环体内又包含另一个完整的循环结构,称为循环嵌套。内层的循环中还可以嵌套循环,构成多重循环。,while()while(),for(;)for(;),do do while();while();,while()for(;),for(;)do while();,while()do while();,2023/7/28,60,例:输出如图所示的矩形:,*,void main()printf(*n);printf(*n);printf(*n);printf(*n);,void main()int i,j;i=1;while(i=4),while(j=5)printf(“*”);j+;,j=1;,printf(“n”);i+;,2023/7/28,61,#include void main()int i,j;i=1;while(i=4)for(j=1;j=5;j+)putchar(*);putchar(n);i+;,#include void main()int i,j;for(i=1;i=4;i+)for(j=1;j=5;j+)putchar(*);putchar(n);,例:输出如图所示的矩形:,*,内外层循环的循环控制变量不能重名,2023/7/28,62,例:输出如图所示的三角形:,*,特点:第i行有i个星号,#include void main()int i,j;for(i=1;i=4;i+)for(j=1;j+)putchar(*);putchar(n);,j=i,2023/7/28,63,例:输出如图所示的等腰三角形:,*,特点:一共有4行,第i行有2i-1个星号;第i行的第1个星号前有4-i个空格,#include main()int i,j;for(i=1;i=4;i+)for(j=1;j=4-i;j+)putchar(32);for(j=1;j=2*i-1;j+)putchar(*);putchar(n);,2023/7/28,64,例:输出如图所示的菱形:,*,分析:将图形分为上下两部分分别输出!,2023/7/28,65,*,for(i=1;i=4;i+)for(j=1;j=4-i;j+)putchar();for(k=1;k=2*i-1;k+)putchar(*);putchar(n);,for(i=3;i=1;i-)for(j=1;j=4-i;j+)putchar();for(k=1;k=2*i-1;k+)putchar(*);putchar(n);,2023/7/28,66,几种循环的比较,、C语言中的三种循环结构都由表达式控制执行一个循环体,一般情况下可以相互代替;、用while和do-while循环时,循环变量初始化的操作应在while和do-while语句之前完成;而for语句一般在表达式1中实现循环变量的初始化;、当循环次数及控制条件要在程序运行过程中确定时,选用while或do-while语句;、在初值、增量及控制条件明显,或循环次数已经给定的情况下,选用for语句;,2023/7/28,67,、在循环的执行过程中,应不断的改变循环控制表达式的值,以便逐步形成使它为0的条件,否则将可能出现死循环;,、三种循环可以相互嵌套,形成多重循环,外循环可以包含多个或多重内循环,循环之间可以并列但不能相交,并列的循环控制变量可以同名,但嵌套的循环控制变量不能同名;、不允许用其它的控制语句把程序流程从循环体外转入循环体内,但必要时可以用break、goto等语句把流程从循环体内转到循环体外。,2023/7/28,68,2.4 break和continue语句2.4.1 break语句,1、格式:,break;,2、功能:中止当前循环语句或switch语句的执行,3、说明:、若是多重循环,break只能使流程跳出离break最近的一层;、break只用于switch语句和循环语句。,case 6:case 7:printf(Resetn);break;,2023/7/28,69,例2.14:计算 r=1到 r=10时的圆面积,直到面积大于100为止,#include void main()float r,area;for(r=1;r 100)break;printf(%6.2fn,area);,输出结果:3.14 12.56 28.26 50.24 78.50,2023/7/28,70,continue语句,1、格式:,continue;,2、功能:提前结束本次循环体的执行(不再执行循环体中continue后面的语句),接着进行下一次是否执行循环的判定,3、说明:、continue语句只能用于循环语句中,它是一种具有特殊功能的转移语句;、continue与break不同:continue语句只结束本次循环,而不是终止整个循环的执行;而break语句则结束整个循环,不再判断循环条件是否成立。,2023/7/28,71,例2.15:把10到20之间能被3整除的数输出,#includevoid main()int n;for(n=10;n=20;n+)if(n%3!=0)continue;printf(%d,n);printf(“n%dn”,n),break;,12 15 18 21,10,while()break;.,while()continue;.,2023/7/28,72,经典问题:判断素数,素数是除了1和它自身不能被任一个数整除的数。,算法提示:1、可以让除数从2n1逐个去除该数n,判断是否被其中的任何一个整数整除,如果是,则说明不是素数。如果一直都没有出现过整除现象,则说明该数是素数。,for(i=2;i=n)printf(“%d is sushu!”,n);,2023/7/28,73,判断素数,算法改进1:可以定义一个标志变量,判断起来很方便。,flag0;for(i=2;in;i+)if(n%i=0)flag=1;break;if(flag=0)printf(“%d is sushu!”,n);,2023/7/28,74,判断素数,算法改进2:可以进一步减少循环次数。循环的终止条件可缩小为n/2,或,k=n/2;或 k=for(i=2;i=k+1)printf(“%d is sushu!”,n);,2023/7/28,75,例:打印3100之间的全部素数。,for(m=3;m=100;m+=2),k=sqrt(m);for(i=2;i=k;i+)if(m%i=0)break;,if(i=)printf(%-5d,m);,k+1,?,void main()int i,k,m;,2023/7/28,76,判断n是否素数,补全程序,main()int i,n,flag=0;for(i=2;_;i+)if(_)flag=1;if(_)printf(“是素数n”);,in,n%i=0,flag=0,2023/7/28,77,经典算法一(穷举法):百鸡百钱问题,一只公鸡值5元,一只母鸡值3元,三只小鸡值1元,总共有100元钱要买一百只鸡,问有多少种方案?,#include void main()int x,y,z;printf(*百鸡问题*n);for(x=1;x20;x+)for(y=1;y33;y+)for(z=3;z100;z+=3)if(5*x+3*y+z/3=100,2023/7/28,78,程序使用了三层循环来解决问题,程序结构简单明了。但是我们设计程序不仅要正确无误,还要注意程序的执行效率。一般来说,在循环嵌套中,内层循环执行的次数等于该循环嵌套结构中每一层循环重复次数的乘积。例如,上面的程序中,外层每循环一次,第二层要循环32次,而第三层要循环32*33=1056次。这样程序执行下来,最内层的if语句要执行19*32*33次。所以我们在编写程序时,需要考虑尽可能的减少循环执行的次数,特别是循环的嵌套。,2023/7/28,79,对于“百鸡问题”,由方程组:x+y+z=100,5x+3y+z/3=100可以导出:x=4z/3-100 y=100-x-z这样就只有z一个未知数,如果知道了z就可以求出x值,进而求出y值。因此我们只要将z作为循环变量就可以了。,2023/7/28,80,#include void main()int x,y,z;printf(“*百鸡问题*n”);for(z=3;z100;z+=3)x=4*z/3-100;y=100-x-z;if(5*x+3*y+z/3=100,尽管每次循环执行的语句增多了,但是循环次数只有33次,运行效率大大提高。,2023/7/28,81,从上面的分析可以看到,一个好的算法可以提高程序的执行效率,但是要设计出一个好的算法却要花费很大的精力,且有时提高效率的同时可能会降低程序的可读性。如上例就是如此。如何掌握好程序的易读性和程序的效率之间的关系,因需要不同重点也就不同。如在处理实时问题时,效率应该优先;而程序量不大,计算机速度又非常快的情况下,效率就不是很重要。,2023/7/28,82,猴子第一天摘了若干个桃子,当即吃了一半,还不过瘾,又多吃了一个。第二天又将剩下的桃子吃了一半,又多吃了一个。以后每天都吃掉前一天剩下的一半零一个。到第十天想吃时,只剩下一个桃子了。问第一天共摘了多少桃子?,分析:设循环变量day,day从 9 循环到 1,设x1为前一天桃子数,设x2为第二天桃子数,则x2=x1/2-1,所以 x1=(x2+1)*2 每次循环:x1=(x2+1)*2;x2=x1,经典算法二(逆推法):猴子吃桃问题,2023/7/28,83,猴子吃桃程序,int day,x2,x1;x2=1;for(day=9;day=1;day-)x1=(x2+1)*2;x2=x1;printf(peach are%dn,x1);,2023/7/28,84,2.6 指针程序设计指针,1、指针的含义:变量的地址指针变量就是一类存取其他变量或函数的地址的变量。,说明:(1)系统为每个变量分配一个确定、唯一的地址。(2)存取变量的值时,有两种方式:1)直接访问:通过变量名;2)间接访问:通过变量的地址。(3)变量的地址就是其所占内存空间的首地址。,2023/7/28,85,2、指针变量的定义:基类型*指针变量名=初始值;,变量名前的*表示该变量是一个指针变量,以示与普通变量的区别。,可以是C语言中的任何一种数据类型,是指针变量所指向的对象的类型。,初始值可以省略,例如:int i=65535,*pi=/先定义变量,再赋初值 指针变量、变量、变量地址和变量的值的关系见下图,2023/7/28,86,2023/7/28,87,2.6.2 指针变量的使用,1、指针变量的赋值(1)通过地址运算(,单目运算符,两个指针变量的类型必须相同,NULL是符号常量,和整数0对应。相当于:p=0;或p=0;,2023/7/28,88,除了上述4种情况外,指针变量还可以指向数组、字符串、结构体、函数、文件及调用标准函数(malloc、calloc)等。,2023/7/28,89,2、指针运算符(*)通过指针变量可以间接地存取变量的数据。例如:已知有定义:int x,*p;p=等价,2023/7/28,90,例2.18 由键盘输入一个正整数,求出其最高位数字。请用指针完成本题,#include void main()int i,*p;p=,2023/7/28,91,例2.19 输入两个数,并按从大到小输出。请用指针完成本题。,#include void main(void)int x,y,t;int*p,*q;p=输出*/,2023/7/28,92,#include void main(void)int x,y;int*p,*q,*t;p=输出*/,2023/7/28,93,题目:从键盘输入若干学生的成绩,直到输入-1为止,求其中的最高分并输出。要求用指针变量实现对变量的访问。,