版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
小小顶梁柱—函数C语言程序设计第七章本章目录01.函数的定义02.函数的调用03.函数的声明04.变量的作用域05.趣味实例7.1函数的定义将功能封装为独立模块定义函数一般形式类型说明符函数名(形参列表)
{说明部分执行部分}各部分详解“类型说明符”是指函数返回值的类型。函数类型可以省略,当不指明函数类型时,系统默认的是整型。函数名:遵循标识符命名规则,不可省略,用于调用函数形参列表:函数的输入接口,接收外部传递的数据。函数体:包裹在{}中的代码块,实现具体功能,函数内部应有自己的说明语句和执行语句,花括号{}是不可以省略的。函数的参数形式参数(形参)函数定义时括号内声明的变量,仅在函数内部有效(局部变量)。作用是接收调用者传递的数据,作为函数执行的输入。实际参数在函数调用中传递数据的参数称为实际参数,简称实参。代码示例例如:求两个整数的较大者的max函数,在该程序中,子函数中的变量x、y是形参,主函数中的变量a、b是实参。函数参数说明实例函数的参数函数参数说明:1)函数的形参可以有多个,可以相同类型,也可以是不同类型,如intmax(intx,inty)或者intmax(intx,floaty)。相同类型也不可以省略形参前的类型说明,如intmax(intx,y)。2)形参必须是变量,但实参可以是常量、变量和表达式,例如C=max(10,a+b)。3)实参类型必须与形参类型兼容。4)在C语言中,函数进行的是“值传递”,将实参的值传递给形参。这种传递是单向的,即形参的变化并不传递给实参。这是由于形参和实参在内存中分别占用不同的内存单元,形参单元的值改变不会影响到实参单元中的值。函数的参数在函数max()中x、y的值有变化时,在main()函数中实参a和b的值仍然是5和6。因为值的传递是a—>x,b—>y,但不能反向传递,这就是“单向值传递”函数参数传递参数传递示意图函数的返回值函数的返回值--return语句功能:使程序控制从被调用函数返回到调用函数中,同时把返回值带给调用函数。作用:函数与外界交互的重要接口,传递计算结果。return语句书写形式return(表达式);
或return表达式;
或return;使用说明:1)
函数中可有多个return语句,但每次只能有一条被执行。2)若函数类型与return语句中表达式值的类型不一致,按前者为准,此时系统将对数值进行类型转换。3)如果明确表示不需要返回值,可用void型函数,
即定义函数时,类型定义为void型,而且函数中可不必使用return语句。4)
如果函数中没有return语句,并不代表没有返回值,而是返回
一
个不确定的值。实例体验:分析:前面学习的圆面积编程是在主函数中编写的,本例中用子函数编写,其程序段与以前类似,只不过要确定函数名、参数和返回值等内容。例7-1定义一个函数,其功能是已知半径r,求圆的面积。程序代码:floatcirclearea(intr){floatarea;area=3.14*r*r;return(area);}实例体验:问题描述:棋盘上的米粒在一个古老的王国里,国王为了奖励一位聪明的数学家,决定在棋盘上放米粒作为奖励。第1个格子放1粒米,第2个格子放2粒,第3个格子放6粒,第4个格子放24粒…每个格子的米粒数都是前一个格子数的倍数。数学家微笑着对国王说:"陛下,这个奖励看似简单,但随着格子数的增加,米粒数会迅速增长,最终会超出您的想象。"国王不以为然,认为这不过是些小数目。然而,
当数学家计算出第20个格子的米粒数时,国王惊呆了—那是一个天文数字!这就是求解阶乘的故事。下面我们尝试使用函数来解决求阶乘的问题。例7-2求阶乘—函数的优越性。实例体验:程序代码:#include<stdio.h>longfactorial(intn){inti,result=1;for(i=1;i<=n;i++)result*=i;returnresult;}例7-2求阶乘—函数的优越性。main(){intnum1,num2;printf("请输入两个整数:");scanf("%d%d",&num1,&num2);printf("%d!=%ld\n",num1,factorial(num1));printf("%d!=%ld\n",num2,factorial(num2));}7.2函数的调用使用已定义的功能模块函数的调用形式函数的调用形式主函数使用被调函数的功能,称为函数的调用。在C语言中,只有在函数调用时,函数体中定义的功能才会被执行。C语言中函数调用的一般形式为:函数名(类型形参,类型形参,…);对无参函数调用时,则无实际参数表。实际参数表中的参数可以是常数、变量或其他构造类型数据及表达式,各实参之间用逗号分隔。例如:d=max(a,b);或d=max(3,a);或d=max(max(a,b),c)函数的调用形式函数表达式表达式包含函数项时,要求函数必须有返回值,以函数的返回值参与表达式的运算。“z=max(x,y);”是一个赋值表达式,把max的返回值赋予变量z函数语句函数调用的一般形式加上分号即构成函数语句。无论函数是否有返回值,都可用这种方式调用。printf("%d",a);scanf("%d",&b);函数实参函数可以作为另一个函数调用的实际参数出现,这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须有返回值。printf("%d",max(x,y));/*把max()调用的返回值作为printf()函数的实参*/函数调用的语法要求语法规则1)调用函数时,定义和说明的函数名必须与被调用的函数名完全一样;实参的个数、类型和形参的个数、类型一致。2)C语言规定函数必须先定义,后调用,即被调用的函数必须在调用之前加以说明或在调用函数之前定义。3)C语言中的函数定义都是相互平行的、独立的,不允许嵌套定义函数,但允许嵌套调用函数(在调用一个函数的过程中,再调用另一个函数)main(){intmax(intx,inty);inta,b;intc;scanf("%d,%d",&a,&b);c=max(a,b);printf("Maxis%d\n",c);}intmax(intx,inty){intz;z=x>y?x:y;return(z);}
7-3找出两个整数的最大值程序执行流程实例体验:实例体验:问题描述:智能书法评分系统在中华传统文化中,书法是一门极具艺术价值的技艺。随着现代科技的发展,我们可以通过计算机程序来辅助评估书法的质量。假设你正在开发一个“智能书法评分系统”,该系统可以根据用户输入的书法作品的笔画长度、笔画粗细、字形结构等参数,自动计算出书法作品的评分。例7-4传统文化与现代科技的结合—智能书法评分系统。实例体验:程序代码:#include<stdio.h>floatscore(floatlen,floatthi,floatstr)//计算书法评分的函数{return(len*0.4)+(thi*0.3)+(str*0.3);}voidprint(floats)//输出评分和评价的函数{printf("书法作品评分为:%.2f\n",s);if(s>=90){printf("评价:优秀\n");}elseif(s>=70){printf("评价:良好\n");}elseif(s>=60){printf("评价:及格\n");}else{printf("评价:需要改进\n");}}main(){floatlen,thi,str;printf("请输入书法作品的笔画长度评分:");scanf("%f",&len);printf("请输入书法作品的笔画粗细评分:");scanf("%f",&thi);printf("请输入书法作品的字形结构评分:");scanf("%f",&str);floats=score(len,thi,str);//调用函数计算评分print(s);//调用函数输出评分和评价}例7-4传统文化与现代科技的结合—智能书法评分系统。7.3函数的声明告诉编译器函数的存在函数声明的格式在主调函数中调用某函数之前,应对该被调函数进行声明,其作用是使编译系统知道被调函数返回值的类型,以便在主调函数中按此种类型对返回值进行相应的处理。书写格式与说明一般形式:类型说明符被调函数名(类型形参,类型形参,…);1.在函数声明中,参数的名称并不重要,只有参数的类型是必需的,因此下面也是有效的声明:intmax(int,int);2.函数的声明和函数的定义有本质上的不同,主要区别在以下两个方面:1)函数的定义是编写一段程序,应有函数的具体功能语句—函数体;而函数的声明仅是向编译系统的一个说明,不含具体的执行动作。2)在程序中,函数的定义只能有一次,而函数的声明可以有多次。函数声明的位置与作用域函数声明位置:函数内或函数外。intmax(intx,inty);main(){intmax(intx,inty);inta,b;intc;scanf("%d,%d",&a,&b);c=max(a,b);printf("Maxis%d\n",c);}intmax(intx,inty){intz;z=x>y?x:y;return(z);}
小贴士:在下列情况下,无需进行函数声明:1)被调用函数定义出现在主调函数之前,如上例中,将max()函数段写在主函数的前面max()函数就可以不声明。2)若函数返值是int或char型,也可不声明函数,系统自动按int型处理。在所有函数外部声明被调用函数,其后所有函数都可以调用该函数在调用函数内部声明被调用函数,只有调用函数内部才可调用该函数实例体验:程序代码:fun1(inta,intb){intc;a+=a;b+=b;c=fun2(a,b);returnc*c;}fun2(inta,intb){intc;c=a*b%5;returnc;}main(){intx=21,y=12;printf(“fun1(x,y)=%d,”,fun1(x,y));printf(“x=%d,y=%d”,x,y);}例7-6运行下面的程序,观察现象,找出原因并修改程序。7.4变量的作用域变量在何处起作用局部变量核心定义局部变量是在函数内部声明的变量,包括函数的形参。这些变量只在声明它的函数内部使用,在函数外不能使用,即“谁声明谁使用”说明1)形参属于局部变量。2)main()函数中定义的变量只在main()函数中有效,不能因为在main()函数中定义就在整个文件或程序中有效。main()函数也不能使用其他函数中定义的变量。3)不同函数中的同名变量,占有不同内存单元,因此不会相互影响。4)复合语句中定义的变量也属于局部变量,变量的作用域在复合语句内,这种复合语句也称为“分程序”或“程序块”。代码示例(C语言)floatf1(inta){intb,c;…}charf2(intx,inty){inti,j;…}main(){intm,n;…}a、b、c有效x、y、i、j有效m、n有效全局变量核心定义在函数外定义的变量称为全局变量,又称全程变量或外部变量。全局变量的有效范围是从定义的位置直至它所在源程序文件的结束。说明1)全局变量的作用域从定义位置开始,在这个范围内的任何地方都可使用(包括函数中)。2)全局变量可以作用于它所在的整个程序或外部的程序,但需要另外说明,其存储类型也会影响其作用的范围。3)若全局变量与局部变量同名,则全局变量被屏蔽。4)全局变量的使用增加了函数之间传递数据的途径。当函数需返回多个结果时,可通过全局变量实现数据传递。5)应尽量少使用全局变量,因为全局变量在程序执行过程中占用存储单元,若使用过多,很难判断出全局变量的当前值,因此降低程序清晰性,容易出错。实例体验:程序代码:#include<stdio.h>sub(){inta,b;a=6;b=7;printf("sub:a=%d,b=%d\n",a,b);}main(){inta,b;a=3;b=4;sub();printf("main:a=%d,b=%d\n",a,b);printf("main:a=%d,b=%d\n",a,b);}例7-7局部变量示例实例体验:问题描述:古代天文历法与现代气象预测在中国古代天文历法中,如24节气,展现了中华民族在天文观测和气象预测方面的卓越智慧。随着现代科技的发展,我们可以通过计算机程序来模拟和监测节气温度变化,从而更精准地预测天气。请开发一个“节气温度监测系统”,根据用户输入的节气温度数据,判断当前温度是否在正常范围内,并输出相应的提示信息。例7-8古代天文历法与现代气象预测—节气温度监测系统实例体验:程序代码:#include<stdio.h>sub(){inta,b;a=6;b=7;printf("sub:a=%d,b=%d\n",a,b);}main(){inta,b;a=3;b=4;sub();printf("main:a=%d,b=%d\n",a,b);printf("main:a=%d,b=%d\n",a,b);}例7-8
古代天文历法与现代气象预测—节气温度监测系统实例体验:程序代码:#include<stdio.h>floatminTemp,maxTemp;voidtemperature(floattemp){if(temp<minTemp){printf("温度过低,注意保暖\n");}elseif(temp>maxTemp){printf("温度过高,注意防暑\n");
例7-8
古代天文历法与现代气象预测—节气温度监测系统}else{printf("温度正常\n");}}main(){floattemp;printf("请输入正常范围的下限:");scanf("%f",&minTemp);printf("请输入正常范围的上限:");scanf("%f",&maxTemp);printf("请输入当前温度:");scanf("%f",&temp);temperature(temp);}7.5趣味实例—四则运算编程综合运用函数知识趣味实例:四则运算编程实训目的1.掌握函数定义的方法。2.掌握函数实参与形参的关系以及“值传递”的方式。3.了解全局变量、局部变量的使用和区别。实训内容1.基础训练由计算机生成简单的一位数四则运算题,用户给出答案,计算机判断对错,直到用户回答说“不再继续做了”时,结束程序。2.提升训练让用户选择指定加减乘除哪一种运算,以及出一位数还是两位数的运算题,对用户所做算术题的对错次数进行记录,结束程序时给出成绩。结束程序要求同上。实训流程知识准备学会函数的使用编程训练1)内容分析:确定程序的操作确定四则运算中的变量明确四则运算的运算过程2)编程分工。3)编程、上机验证。编程提示四则运算(加、减、乘、除)的核心流程具有高度相似性,可以先编出一种运算的模式,再将其推广到其他运算。分析时,构建出整个程序的结构模型,帮助分析程序的需求及走向。编程时,从分析的结构中先编写底层函数模块,然后再向上编写。本章小结:魅力指挥棒—指针的应用C语言程序设计第八章本章目录01.认识指针02.指针变量的定义及引用03.指针与数组04.趣味实例8.1认识指针理解内存地址与指针的概念指针概念及作用
当在程序中定义了一个变量,对程序进行编译时,系统就会给这个变量分配内存单元。编译系统根据程序中定义的变量类型,分配一定长度的空间。内存区的每一个字节有一个编号,这就是“地址”。由于通过地址能找到所需的变量单元,因此唯一标识变量储存位置的地址,通常称为“指针”。C语言中的地址包括位置信息(内存编号,或称纯地址)
和它所指向的数据的类型信息,或者说它是“带类型的地址”。存储单元的地址和存储单元的内容是两个不同的概念。例如:inti=1,j=2,k=3;//设int变量占2字节指针变量指针变量
用一个变量来存放内存的地址,这个变量就称为指针变量,指针类型丰富多样,但不同类型指针变量所占用的存储单元长度是相同的。在程序中一般是通过变量名来引用变量的值。直接按变量名进行的访问,称为“直接访问”方式。还有一种“间接访问”的方式,即将变量的地址存放在另一变量(指针变量)中,然后通过该指针变量来找到对应变量的地址,从而访问变量。
严格地说,一个指针是一个地址,是一个常量。而一个指针变量却可以被赋予不同的指针值,是变量。但常把指针变量简称为指针。为了避免混淆,我们约定:“指针”是指地址,是常量,“指针变量”是指取值为地址的变量。定义指针的目的是为了通过指针去访问内存单元。例如:将变量x的地址2060存放到另一个变量p中,即p的值为2060,这样通过变量p可以找到变量x的地址,从而找到x的值。存放地址的变量p就是指针变量。可以形象地说,p指向x,变量x与指针变量p的关系如图8-2所示。
8.2指针变量的定义及引用掌握指针变量的基本操作指针变量的定义定义格式类型标识符*指针变量名;例如:int*pointer_1,*pointer_2;//定义了两个int类型的指针变量类型标识符决定指针指向的数据类型,必须与目标变量类型严格一致。星号*指针运算法,表示其后的变量是指针变量,不能省略。指针变量名遵循C语言标识符命名规则,用于存储内存地址。结构说明1)定义指针变量时必须指定其类型。一个变量的指针的含义包括两个方面,一是以存储单元编号表示的纯地址,二是它指向的存储单元的数据类型。2)如何表示指针类型。指向整型数据的指针类型表示为“int*”,读作“指向int类型的指针”或简称“int指针”。3)指针不能指向常量,例如“int*p;p=&50;”是错误的。4)指针的内容不能直接输入,例如“intp;scanf("%d",&p);”是错误的,“int*p,a;p=&a;scanf("%d",p);”是正确的,此处是输入变量a的值。定义指针变量要注意:指针变量的定义示例指针类型指针定义语句里的指针名字去掉,剩下的部分就是这个指针的类型。指针所指向的类型通过指针来访问指针所指向的内存区域时,指针所指向的类型决定了编译器将把那片内存区里的内容当作什么类型来看待。int*ptr;//指针的类型是int*char*ptr;//指针的类型是char*int**ptr;//指针的类型是int**int(*ptr)[3];//指针的类型是int(*)[3]示例int*ptr;//指针所指向的类型是intchar*ptr;//指针所指向的类型是charint**ptr;//指针所指向的类型是int*int(*ptr)[3];//指针所指向的类型是int()[3]指针的引用
在指针的引用中涉及两个运算符"*"和"&","*"是指针运算符,或称为“间接访问”运算符,如*p1表示指针变量p1所指向的变量;"&"称为取地址运算符,如为了让指针p指向变量x,可执行p=&x,此时变量x的地址即存入了指针p中。若要改变x变量的值,也可通过改变*p的值来实现,如执行“*p=47;”,则此时x=47。
指针变量既可以在定义时初始化,也可以在定义后赋初值,不能未赋值就引用指针存取值。指针变量可以如同一般变量一样进行赋值、加减计算。指针的引用取地址运算符`&`作用:获取变量的内存地址格式:&变量名示例:p=&a;(将变量a的地址赋值给指针p)解引用运算符`*`作用:访问指针指向的内存值格式:*指针变量名示例:printf("%d",*p);(输出p指向的值)*p=20;(修改p指向的变量值)指针变量的初始化野指针的危害未初始化的指针值随机,指向内存任意位置。直接使用(如*p=10)可能导致程序崩溃或数据被意外篡改。(补充内容)指针的初始化定义时直接赋值:
inta,*p=&a;先定义后赋值:
inta,*p;p=&a;空指针
NULLNULL通常定义为0,表示指针无效。良好习惯:int*p=NULL;注意:NULL指针不可解引用(*p)。(补充内容)指针的引用说明指针变量中只能用于存储变量的地址,不可将一个整型常量赋给一个指针变量。实例体验例8-1通过指针变量访问变量。#include<stdio.h>main(){inta=7,b=5,c,*pa=&a,*pb;pb=&b;c=*pa+*pb;printf("a=%d,*pa=%d\n",a,*pa);printf("b=%d,*pb=%d\n",b,*pb);printf("%d+%d=%d\n",a,b,c);printf("%d+%d=%d",*pa,*pb,c);}#include<stdio.h>main(){int*p,*pa,*pb,a,b;printf("请输入两个整数:");scanf("%d,%d",&a,&b);pa=&a;pb=&b;if(a<b){p=pa;pa=pb;pb=p;}printf("a=%d,b=%d\n",a,b);printf("从大到小输出两个整数:%d,%d\n",*pa,*pb);}例8-2输入a和b两个整数,按先大后小的顺序输出a和b两个整数,使用指针编写程序。8.3指针与数组利用指针高效操作数组指针与一维数组
数组一旦被定义,其元素将在内存中占用一段连续的存储单元,每个数组元素都占用一个存储单元,它们都有相应的地址。指针变量既然可以指向变量,当然也可以指向数组元素(把某一元素的地址放到一个指针变量中)。所谓数组指针,是指数组的起始地址,数组元素的指针就是数组元素的地址。可以用一个指针变量指向一个数组元素。
数组名代表数组的首地址。比如“int[5]={12,34,56,78,90};”首地址是数组的第1个元素的地址,所以该数组的数据在内存中的存储结构如图
所示。。指针与一维数组指针与一维数组建立关联将数组的首地址放入指针中,就让指针变量指向数组,如:inta[5],*p=a;//指针变量p指向数组a。一维数组的引用——引用各个数组元素的地址
1)通过使用数组名引用。如“inta[6]”2)通过指针引用。如“inta[6],*p=a;p++;”注意:此处数组名a是常量,不能进行自增/自减运算。指针与一维数组一维数组的引用——引用各个数组元素所在的存储单元或存储单元里的值
1)通过对数组名、指针变量的取内容运算符*。上图
中数组的运算:*p=a[0],*(p+1)=a[1],a=a[0],*(a+1)=a[1],依次类推。2)通过指针变量后面跟下标。数组和指针建立关联后,可以把指针带入数组名引用各个数组元素,即p[i]与a[i]代表值相同。小贴士:1)指针变量指向数组元素a[i]的方法是p=&a[i]或p=a+i。2)与数组名的区别,指针变量是一个变量,其值可以改变,数组名是数组的首地址,是地址常量,其值不能变化。例如,若定义“inta[10],*p=a;”,则a++是错误的,p++是允许的。3)未初始化的指针指向不确定的值。4)若有定义“inta[10],*p=a,i;”,则a[i]、*(a+i)、*(p+i)等价。5)注意指针的动态性,a[i]与*(p+i)不总是相等的,例如:inta[10],*p,i=5;p=a+1;上述例子中*(p+i)等价于a[6]。指针与二维数组二维数组定义二维数组定义时的行数和列数分别用两个方括号分开,把二维数组看作是一种特殊的一维数组。指针与二维数组建立关联二维数组的引用:同一维数组。小贴士:设“inta[4][5],*p=a[0],i,j;”。1)a是该二维数组的首地址,即元素a[0][0]的首地址。a+i是行指针,等同于a[i],是第i+1行的首地址,即&a[i][0]。2)a+1与p+1不同,a+1以二维数组的“行长度”为增量,而p+1则以二维数组的“元素长度”为增量,即a+1加1行的增量,p+1加一个元素的增量。3)a[i]+j是a[i][j]的地址,等价于a[i][j]。4)*(a+i)与*a[i]不同,*a[i]表示元素a[i][0]的值,而*(a+i)表示元素a[i][0]的地址。5)表示元素a[i][j]的方法有*(a[i]+j)、*(*(a+i)+j。先定义指针、二维数组,然后将二维数组首地址赋值给指针变量,例如“inta[4][3];int*p;p=a[0];”。通过指针遍历一维数组核心代码实现#include<stdio.h>intmain(){intarr[]={1,2,3,4,5};intp,n=sizeof(arr)/sizeof(arr[0]);//方法一:指针移动遍历(推荐)for(p=arr;p<arr+n;p++){printf("%d",*p);}//方法二:指针下标形式p=arr;for(inti=
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 安检员设备维护保养考核试卷及答案
- DB32/T 4674-2024沿海滩涂中轻度盐碱地青贮玉米栽培技术规程
- 2026年山东烟草专卖局招聘笔试真题及答案
- 《变态心理学》试题和答案
- 2026年山西省北师大版八年级地理第7章综合测试卷
- DB32/T 4964-2024粳稻品种真实性和纯度SSR分子标记检测法
- DB32/T 5177-2025预拌混凝土绿色生产管理技术规程
- 小金属机器人项目可行性研究报告
- 中风病理论渊源及诊治
- 串并联电路电阻特点
- 彩钢瓦屋顶施工方案及安装
- 龙骨灸课件教学课件
- 茶企安全培训课件
- 翻译硕士视译课件
- YDT 5102-2024 通信线路工程技术规范
- 工程测量安全培训课件
- 舞动治疗课件
- 新媒体营销(第三版) 课件全套 林海 项目1-6 新媒体营销认知-新媒体营销数据分析
- 乡村振兴课件模板
- 2024-2025学年上海市浦东新区七年级上英语期中试卷(含答案和音频)
- 业主封阳台安装窗户物业免责协议协议书
评论
0/150
提交评论