C语言复习资料第7章.docx
《C语言复习资料第7章.docx》由会员分享,可在线阅读,更多相关《C语言复习资料第7章.docx(18页珍藏版)》请在冰豆网上搜索。
C语言复习资料第7章
第7章函数
(这章很重要,概念很多,所以请各个同学要好好记住并加以理解)
一、函数的意义及定义
(1)意义:
1.在设计一个较大的程序时,往往把它分为若干个程序模块,每一个模块包括一个或多个函数,每个函数实现一个特定的功能
2.C程序可由一个主函数和若干个其他函数构成
3.主函数调用其他函数,其他函数也可以互相调用
4.同一个函数可以被一个或多个函数调用任意多次
注意:
在程序设计中要善于利用函数,可以减少重复编写程序段的工作量,同时可以方便地实现模块化的程序设计,还有一个就是老师上课曾经讲过的,一个自定义的函数必需保持通用性(参照例题3的
(2)和(3))
(2)定义:
1.从函数类型看分以下两种:
无参函数和有参函数
无参函数:
一般形式为以下两种(即括号内没有任何参数或者是void)
类型名函数名()
{
函数体
}
类型名函数名(void)
{
函数体
}
有参函数:
一般形式
类型名函数名(形式参数表列)
{
函数体
}
(请自行比对,进行理解,这也是我们经常用的形式,要熟记)
例如:
intmax(intx,inty)
{intz;
z=x>y?
x:
y;
returnz;
}
(PS:
还有一种比较特殊的空函数,有兴趣的可以看书的P174了解一下)
例1:
输出右边效果(典型的无参函数)****************
Howdoyoudo!
****************
#include
intmain()
{voidprintstar();/*对printstar函数声明*/
voidprint_message();/*对print_message函数声明*/
printstar();/*调用printstar函数*/
print_message();/*调用print_message函数*/这里没有返回值
printstar();/*调用printstar函数*/仅仅是执行了函数而已
return0;
}
voidprintstar()/*定义printstar函数*/
{printf("****************\n");}
voidprint_message()/*定义print_message函数*/
{printf("Howdoyoudo!
\n");}
二、※函数的调用和声明
(1)函数调用的一般形式为:
函数名(实参表列)
如果是调用无参函数,则“实参表列”可以没有,但括号不能省略(即括号内什么都没有,就一个括号)(参照上面的例题1)
如果实参表列包含多个实参,则各参数间用逗号隔开(如d=max(a,b,c);)
(若不理解可以对照例题进行理解)
(2)函数的调用方式:
1.函数调用语句
把函数调用单独作为一个语句
如printf_star();
这时不要求函数返回值,只要求函数完成一定的操作(比如排序,printf之类的)
2.函数表达式
函数调用出现在另一个表达式中
如c=max(a,b);这时要求函数带回一个确定的值以参加表达式的运算
(通常伴有>、<、=、==、!
=之类的符号或者是直接进行四则运算,函数之前通常还有一个变量,这可以作为判断依据,如例2)
例2:
判断素数的函数
(1)编写一个判断素数的函数,命名为primeNumber,对参数n进行判断,返回一个表示“是/否”的值。
(2)在主函数中输入一个正整数,调用上述函数进行判断,并输出结果。
(3)在第2题程序正确运行后,对main函数进行修改:
使用primeNumber函数,显示[1000,2000]区间内的素数。
(2)
#include
intmain()
{intprimeNumber(intx),x;
charc;
printf("请输入一个数=");
scanf("%d",&x);
if(x==1)printf("你输入的数不是素数\n");
else
{c=primeNumber(x);
if(c==0)printf("你输入的数不是素数\n");
elseprintf("%d是素数\n",x);}
return0;
}
intprimeNumber(intx)
{
inti,c;
for(i=2;i<=x-1;i++)if(x%i==0)break;
if(ielsec=1;
return(c);
}
(3)
#include
intmain()
{
intprimeNumber(intx),x,c;
printf("1000到2000内的素数\n");
for(x=1000;x<=2000;x++)
{c=primeNumber(x);
if(c==1)printf("%d\t",x);}
printf("\n");
return0;
}
intprimeNumber(intx)
{
inti,c;
for(i=2;i<=x-1;i++)
if(x%i==0)break;
if(ielsec=1;
return(c);
}
3.函数参数(这个较难理解,可以参照例题进行理解)
函数调用作为另一函数调用时的实参
如m=max(a,max(b,c));//求a,b,c三数中最大者
其中max(b,c)是一次函数调用,它的值作为max另一次调用的实参
(有点类似于高中解方程时的整体代换)
(3)函数调用时的数据传递
1.形式参数和实际参数
在调用有参函数时,主函数和被调用函数之间有数据传递关系(“值传递”)
形参和实参:
定义函数时函数名后面的变量名称为“形式参数”(简称“形参”)
主调函数中调用一个函数时,函数名后面参数称为“实际参数”(简称“实参”)
而实参可以是常量、变量或表达式(如上a则可以改成a+5,或者改成一个常量5)
2.实参和形参间的数据传递
在调用函数过程中,系统会把实参的值传递给被调用函数的形参
即是说,形参从实参得到一个值,并在函数调用期间在被调用的函数里参加运算
如图所示:
注意:
如果在执行一个被调用函数时,形参的值发生改变,不会改变主调函数的实参的值
(4)函数的返回值
函数的返回值是通过函数中的return语句获得的。
※但在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致
例如下图(书上P179例7.3)
(5)函数的声明
这个就属于格式问题了,就是必须在使用被调用函数前,对函数进行声明(让主函数知道有这么一个函数存在)。
例题中都有注释。
这就靠看例题进行理解吧。
三、函数的嵌套调用
(1)定义:
调用一个函数的过程中,又可以调用另一个函数
例3(详细的解释在书上P183例题7.5):
#include
intmain()
{intmax4(inta,intb,intc,intd);
inta,b,c,d,max;
printf(“4intergernumbers:
");
scanf("%d%d%d%d",&a,&b,&c,&d);
max=max4(a,b,c,d);
printf("max=%d\n",max);
return0;}
intmax4(inta,intb,intc,intd)
{intmax2(inta,intb);//函数声明
intm;
m=max2(a,b);//a,b中最大者
m=max2(m,c);//a,b,c中最大者
m=max2(m,d);//a,b,c,d中最大者
return(m);
}
intmax2(inta,intb)//比较两数大小
{
if(a>=b)
returna;
else
returnb;
}
(以上例题在max4的函数中声明并调用了※另外一个函数max2来进行计算)
(请注意递归和嵌套的区别,嵌套是调用别的函数进行计算,而递归是本身函数的调用)
四、函数的递归调用
(1)定义:
在调用一个函数的过程中又出现直接或间接地调用该函数本身。
注意与函数嵌套的区别,具体见上。
(经验之谈:
通常在使用递归的时候,函数里面都伴有if的结构来结束递归,并且通常是赋值的语句。
)
(2)例题集:
(递归比较难理解,希望大家能多看下面的经典例题并加以理解)
例4:
(第11-12周实验第3题)
编写求两个正整数最大公约数的函数gcd和求两个正整数最小公倍数的函数lcm。
#include
intmain()
{intgcd(inta,intb);
intlcm(inta,intb);
intc,d,e,f;
printf("输入两个数(用回车隔开)\n");
scanf("%d%d",&c,&d);
if(c==0||d==0)printf("你输入的数有误,请重新输入\n");
else
{e=gcd(c,d);
f=lcm(c,d);
printf("%d和%d的最大公约数为%d\n",c,d,e);
printf("%d和%d的最小公倍数为%d\n",c,d,f);
}return0;
}
(以下有两种算法,大家加以对比参照以了解递归的用法及好处)
普通算法(效率较低):
intgcd(inta,intb)
{
intn,i,t;
if(a>b)n=b;
elsen=a;
for(i=1;i<=n;i++)
{
if(a%i==0&&b%i==0)
t=i;
}
return(t);
}
intlcm(inta,intb)
{
intn,i,t;
if(a>b)n=a;
elsen=b;
for(i=a*b;i>=n;i--)
{
if(i%a==0&&i%b==0)
t=i;
}
return(t);
}
递归算法(辗转求余法):
intgcd(inta,intb)
{
if(a
elseif(b==0)returna;
elsereturngcd(b,a%b);
}
intlcm(inta,intb)
{
returna*b/gcd(a,b);
}
例5:
(第11-12周实验第4题)递归算法求阶乘
在函数中用
递归算法表示
(1)使用如下的阶乘定义,用递归算法编写一个求阶乘的函数fac。
阶乘的递推定义公式:
(2)编写主函数,调用fac求任意3个正整数阶乘的和x!
+y!
+z!
。
#includedoublefac(doublea)
intmain(){doublet=1;
{doublefac(doublea);if(a==0)t=1;
doubleb,c,d,e;else
printf("请输入3个数字(用回车隔开)\n");t=a*fac(a-1);//递归算法
scanf("%lf%lf%lf",&b,&c,&d);returnt;}
if(b<0||c<0||d<0)printf("你输入的数据有误,请重新输入\n");
else
{e=fac(b)+fac(c)+fac(d);
printf("%.0f!
+%.0f!
+%.0f!
=%.0f\n",b,c,d,e);
}return0;
}
(3)编写主函数,调用fac求1!
+2!
+...+10!
。
#include
intmain()
{doublefac(doublea);
doubleb=0;
inti;
for(i=1;i<11;i++)
b=b+fac(i);
printf("1!
+2!
+3!
+4!
+5!
+6!
+7!
+8!
+9!
+10!
=%.0f\n",b);
return0;
}
doublefac(doublea)
{
doublet=0;
if(a==0)t=1;
else
t=a*fac(a-1);//递归算法
returnt;
}
(4)编写主函数,调用fac求组合数
,n≥m。
#include
intmain()
{doublefac(doublea);
doublem,n,e;
printf("请输入m=");
scanf("%lf",&m);
printf("请输入n=");
scanf("%lf",&n);
if(nelse{e=fac(n)/(fac(m)*fac(n-m));
printf("组合数C=%.0f\n",e);}
return0;}
doublefac(doublea)
{
doublet=1;
if(a==0)t=1;
else
t=a*fac(a-1);//递归算法
returnt;
}
(注意:
如果对递归算法有不懂的或者不是太熟悉的可以去找天哥,他这方面很擅长的说)
五、数组作为函数参数
(1)数组元素作函数实参
在用数组元素作函数实参时,把实参的值传给形参,是“值传递”方式。
数值传递的方向是从实参传到形参,单向传递。
具体应用请看例6。
例6:
(书P193例7.9)输入10个数,要求输出其中值最大的元素和该数是第几个数。
#include
intmain()
{intmax(intx,inty);//函数声明
inta[10],m,n,i;
printf("10integernumbers:
\n");
for(i=0;i<10;i++)
scanf("%d",&a[i]);
printf("\n");
for(i=1,m=a[0],n=0;i<10;i++)
{if(max(m,a[i])>m)//若max函数返回的值大于m
{m=max(m,a[i]);//返回值取代原值
n=i;//记下此时的序号,放到n中
}
}
printf("largestnumberis%d\n",m);
printf("%dthnumber.\n",n+1);
}
intmax(intx,inty)
{return(x>y?
x:
y);//返回x和y中的大者
}
(2)数组名作函数参数
跟数组元素作实参时不同的是,数组名作函数实参时,向形参(数组名或者指针变量)传递的是数组首元素的地址。
(可以联系之后的指针进行思考)
直接看例题来理解吧
例7(第11-12周实验第5题):
定义一个函数,在一个数组中查找一个指定的值,找到时返回其下标,找不到则返回-1。
再定义一个主函数,对一个数组的元素赋值,然后输入一个数值,调用上述函数进行查找,并输出结果。
#include
intmain()
{
intzhao(intsz[],intt);
intsz[10]={1,32,34,45,65,100,234,484,620,659},c,d;
printf("请输入你要查找的数字\n");
scanf("%d",&c);
d=zhao(sz,c);//做实参时用数组名
if(d==-1)printf("你所找的数字不存在,请重新输入\n");
elseprintf("你查找的数字的下标为%d\n",d);
return0;
}
intzhao(intsz[],intt)
{
intk=-1,i;
for(i=0;i<10;i++)
if(sz[i]==t)k=i;
return(k);
}
关于字符数组作函数实参的例题
例8(第11-12周实验第6题)编写一个函数统计一个字符串中大写字母、小写字母、数字、空格、其他字符的个数。
主函数输入字符串,调用上述函数进行统计,并输出结果。
#include
intmain()
{
voidfind(charstr[],intn[]);//函数声明
chartext[]={"AABBaabb1234#$%^"};//初始化,也可以自行输入
intn[4]={0};
find(text,n);
printf("字母个数=%d\n数字个数=%d\n空格个数=%d\n其他字符个数=%d\n",n[0],n[1],n[2],n[3]);
return0;
}
voidfind(charstr[],intn[])//不返回具体值的无参函数
{
inti;
for(i=0;i{
if(str[i]>='A'&&str[i]<='Z')n[0]++;
elseif(str[i]>='a'&&str[i]<='z')n[0]++;
elseif(str[i]>='0'&&str[i]<='9')n[1]++;
elseif(str[i]==32)n[2]++;
elsen[3]++;}
}
(3)多维数组名作函数参数
跟一维数组名作函数参数类似,但在对形参数组定义时,可以省略第一维的大小说明。
例9(书P198例7.13)有一个3×4的矩阵,求所有元素中的最大值。
(函数整理完了,有点多,这是因为函数很重要,而大部分都是对之前所学知识进行应用,所以大家也要复习好之前的知识,然后希望大家期末都不挂科Σ(っ°Д°;)っ)