版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
函数是C和C++程序的基本模块,是构成结构化程序的基本单元。在前面的章节中,我
们虽然有了函数的初步概念,但那仅是感性的认识。况且,设计一个复杂的C程序,通常不
仅包含有多个函数,还可能包含多个源文件。于是,我们就面临一些问题:程序中函数要怎
样设计定义,如何调用,函数参数如何传递等。另外,在程序中如何访问各函数和各文件中
定义的变量,变量引用时的作用域规则,数据生存期也是我们要重点解决的问题。本章将根
据以上问题,以多个实例为引导,循序渐进地讨论函数定义、调用,参数传递,嵌套及递归
调用,局部变量和全局变量,变量存储方式,内部函数和外部函数等相关知识。通过本章的
学习,将能够使读者掌握C语言函数的操作应用。
5.1函数定义与调用
在结构化程序设计中,一个较大的程序一般应分为若干个程序模块,每一个模块用来
实现一个特定的功能。而模块一般是通过子程序来实现的。在TurboC中,子程序的作用是
山函数完成的。函数是一个自我包含地完成一定相关功能的执行代码段。我们可以把函数看
成一个“黑盒子”,你只要将数据送进去就能得到结果,而函数内部究竟是如何工作的,外部
程序是不知道的。外部程序所知道的仅限于输入给函数什么以及函数输出什么。先看实例。
【例5.1]简单的C函数定义与调用程序
定义输出一串字符函数:
printMessage()/*定义printMessage()函数*/
printfC'Hello,world!\nn);/*在屏幕上输出字符串Hello,world!*/
定义在一行打印n个的函数:
printStar(intn)/*定义printStar()函数*/
{intent;
for(cnt=0;cnt<n;cnt++)
printf(“*");
printf(n\nn);
在主程序中调用它们:
include<stdio.h>/*把输入输出函数的头文件包含进来*/
main()
intcount;
printf("Pleaseintputstarnumbers(count):");
scanf("%d",&count);
printStar(count);/*调用printStar()函数*/
printMessage();/*调用printMessage()函数*/
printStar(count);/*通用printStar()函数*/
return0;/*退出main()函数,并返回0*/
)
其中,函数printStar()、printMessage。都是用户自定义的函数。在TurboC环境下
编辑好上述程序进行编译后,如果无任何错误,就可以按下Ctrl+F9运行程序。例5.1的运
行结果如下:(代表回车,下同)
Pleaseinputstarnumbers(count):10/
Hello,world!
我们发现,程序的运行结果一闪而过,按下Alt+F5后,才能看到程序的执行结果,并
且,当多次执行卜.述程序时,发现前面执行的结果仍显示出来。对C的用户来讲,这样的显
示方式并不直观。让我们来对这个程序稍加改进,我们只要将上述程序中的main()函数改
为以下形式:
main()
intcount;
clrscr();
printf(MPleaseintputstarnumbers(count):");
scanf(,,%d,,,&count);
printStar(count);/*调用primStar()函数*/
printMessage();/*调用printMessage()函数*/
printStar(count);/*调用printStar()函数*/
getch();
return0;/*退出main()函数,并返回0*/
)
然后在程序的开头部分加上语句:include<conio.h>o因为函数clrscr()及getch()是C
的标准库函数,它们都在头文件conio.h中定义说明。其中函数clrscr()的作用是程序执行时
先清屏;函数getch()的作用等待从键盘上接收一个字符,但该字符并不显示。
5.1.1函数定义
1.函数声明形式
在C中,从用户使用角度把函数分为标准库函数(如printf()、scanf()>clrscr()>getch()
等)和用户自定义函数(如例5.1中的printStar(n)、printMessage());而从函数的定义形式卜.
把函数分为无参函数和有参函数。首先我们看一个简单的例子。
【例5.2】有一分数序列:2/1,3/2,5/3,8/5,13/8,21/13,…。设计一个函数求该数
列前20项的和。项数从主程序输入。设计步骤如下:
#include<stdio.h>
#include<conio.h>
floatindex(intn);/*函数原型声明*/
main()
(
intnumber;
clrscr();
printf(HPleaseinputelementnumbers(number):'*);
scanf("%d”,&number);
printf(HThesumis%9.6f\n",index(number));
getch();
)
floatindex(intnum)/*函数定义*/
(
intent;
floattemp,a=2,b=l,s=0;
for(cnt=l;cnt<=num;cnt++)
(
s=s+a/b;
temp=a;a=a+b;b=temp;/*这部分是程序的关键,请读者猜猜temp的作用*/
)
return(s);
)
程序输出是:
Pleaseinputelementnumbers(number):20/
Thesumis32.660259
山例5.2,我们可以看到,在程序的头部有一条语句:floatindex(iiitn);它的作用是什么
呢?我们看看下面的解释。
TurboC中所有函数与变量一样,在使用之前需要声明(称为函数原型Function
Prototype)o所谓声明是指声明函数是什么类型的函数,一般库函数的声明都包含在相应的头
文件v*.h>中,例如标准输入输出函数包含在stdio.h中,非标准输入输出函数包含在io.h
中,以后在使用库函数时必须先知道该函数包含在什么样的头文件中,在程序的开头用
include<*上>或#而函(1©"*上”声明。只有这样程序在编译、连接时TurboC才知道它是提供的
库函数,否则,将认为是用户自己编写的函数而不能装配。
函数声明的ANSI规定方式如下:
[extern]函数类型函数名([形式参数表]);
其中:函数类型是该函数返回值的数据类型,可以是以前介绍的整型(int)、长整型(long)、
字符型(char)、单浮点型(float)、双浮点型(double)以及无值型(void)、也可以是指针、包括结
构指针。无值型表示函数没有返回值。方括号“口”代表可选。
函数名为TurboC的标识符,括号中的内容为该函数的形式参数说明。可以只有数据类
型而没有形式参数,也可以两者都有。对于经典的函数说明没有参数信息。如:
intputexp(intx,inty,inlz,intcolor,char*p);/*声明一个整型函数*/
char*name(void);/*声明一个字符串指针函数*/
voidstudent(intn,char*str);/*声明一-个不返回值的函数*/
floatcalculate(int,int);/*声明一个浮点型函数*/
值得注意的是:如果一个函数没有声明就被调用,编译程序并不认为出错,而将此函数
默认为整型(int)函数。因此当一个函数返回其它类型,又没有事先声明,编译时将会出错。
2.函数定义形式
函数定义就是确定该函数完成什么功能以及怎么运行,相当于其它语言的一个子程序。
TurboC对函数的定义采用ANSI规定的方式。即:
[extern/static]函数类型函数名。形式参数表])
(
函数体;
}
其中:函数类型和形式参数的数据类型为TurboC的基本数据类型。函数体为TurboC
提供的库函数和语句以及其它用户自定义函数调用语句的组合,并包括在一对花括号“{”和
“}”中。若函数名后面的括号内无形式参数,则称该函数是无参函数(函数名后括号不能省
略),否则称是有参函数。
需要指出的是:一个程序必须有一个主函数main。,其它用户定义的子函数可以任意多
个,这些函数的位置也没有什么限制,可以在main。函数前,也可以在其后。
【例5.3】无参函数的应用实例。
#include<stdio.h>
voidhello_world(void)
(
printf("Hello,world!\n");
)
voidthree_hellos(void)
(
intcounter;
for(counter=1;counter<=3;counter++)
hello_world();/*调用hello_world()函数*/
)
voidmain(void)
{
three_hellos();/*调用函数three_helk>s()*/
)
程序输出是:
Hello,world!
Hello,world!
Hello,world!
提示:当函数无参数时,在形参表中可使用关键字void。尽管这不是必须的,但我们建
议读者这样使用。另外,当函数在主函数main()之前定义时,则不需函数声明。
【例5.4]定义一个函数,求三个数中最大者。要求从键盘输入三个数,调用该函数,
输出最大数。
#include<conio.h>
intmaxmum(int,int,int);/*用户自定义函数声明*/
main()
intnuml,num2,num3,max;
clrscr();
printf(nPleaseinputthreenumbers(numlandnum2andnum3):");
scanf(n%d%d%d",&numl,&num2,&num3);
max=maxmum(numl,num2,num3);/*调用子函数,并将返回值赋给max*/
printfC'Themaxmumvalueis%d\n",max);
getch();
intmaxmum(intx,inty,intz)
{intmax;
max=x>y?x:y;/*求最大值*/
max=max>z?max:z;
return(max);/*返回最大值*/
如果在定义函数时不指定函数类型,系统会隐含指定函数类型为int型。因此maxmum()
函数左端的int可以省略,但是为了程序清晰和安全,建议都加以声明为好。
另外,对形参类型的声明可以放在函数定义的第2行,即可以写成如下形式(以上面
maxmum()函数为例):
intmaxmum(x,y,z)/*指定形参x,y*/
intx,y,z;/*对形参指定类型*/
intmax;/*函数体中的声明部分*/
max=x>y?x:y;
max=max>z?max:z;
retum(max);
}
但我们推荐采用前面那种标准(ANSI)的书写方式,即对函数形参类型的指定放在函数名
后面的括号内。
5.1.2实训定义及使用函数
实训目的
1.熟悉无参函数和有参函数的概念和格式。
2.理解什么是函数原型,怎样声明函数原型。
3.掌握无参函数与有参函数的声明和定义格式。
实训内容
要求:自定义两个函数,分别求给定值的绝对值和平方根。
1.自定义平方根函数sqrt()和求绝对值函数fabs()实现数学计算操作。
(1)启动TurboC系统,进入编辑环境;
(2)定义设计求给定值的绝对值函数fabs(),代码是:
floatfabs(floatx)/*求x的绝对宿*/
(
if(x<0)
{x=-x;}/*如果X是负数则返回其相反数,否则直接返回*/
return(x);
)
(3)定义求平方根函数sqrt(),首先我们分析设计思路:
我们利用Newton迭代法求给定值的绝对值的平方根,下面给出Newton迭代法求
平方根的算法过程:
①设置猜测初值为1;
②如果I猜测值*猜测值-Xl<e,则转到④;(e指的是一个很小的数)
③设置新的猜测值为(X/猜测值+猜测值)/2,返回到②;
④猜测值就是满足要求的X的平方根。
根据算法,我们设计定义的求平方根函数sqrt()的代码是:
floatsqrt(floatx)/*牛顿迭代法求实数x的平方根*/
(
floatEpsilonNum,GuessNum;
EpsilonNum=IE-5;
GuessNum=1.0;
while(fabs(GuessNum*GuessNum-fabs(x))>=EpsilonNum)
(
GuessNum=(fabs(x)ZGuessNum+GuessNum)/2.0;/*调用自定义fabs()*/
)
return(GuessNum);
}
2.调用自定义函数,设计主程序功能界面,其代码如下:
#include<stdio.h>
#include<conio.h>
floatsqrt(float);
floatfabs(tloat);
voidmain()
{floatFloatNum,Result;/*定义输入变量和输出变量*/
charSelectNum;
while(1)/*显示功能菜单*/
(
clrscr();
puts("Pleaseselectfunction:");
puts(n\tl.fabs(X)");
puts("\t2.sqrt(X)u);
puts("\t3.Exit");
SelectNum=getche();
switch(SelectNum)/*根据所选功能菜单,调用标准数学库
(
caseT:/*取x的绝对值*/
printf("\nPleaseinputxforfabs(x):*');
scanf(H%f\&FloatNum);
Result=fabs(FloatNum);
printf("fabs(x)=%l\n",Result);
getch();
break;
case,21:/*求x的平方根*/
printf(H\nPleaseinputxforsqrt(x):");
scanf(H%f1,&FloatNum);
Result=sqrt(fabs(FloatNum));
printf("sqrt(x)=%f\n,',Result);
getch();
break;
case3:
return;
重要提示:在.上机调试程序时,请将上述自定义的两个函数代码加到主函数main()之
前或之后。
3.保存上述设计的代码,编译、调试、连接并运行,记录运行结果。
实训思考
1.对于本实例,为什么程序的首部不能放语句#抽己11(16<math.h>?
2.在程序设计中函数sqrt()中调用函数fabs()的形式称为什么?
3.函数•般为什么都需要原型?在哪些情况下可以不用函数原型?
5.1.3函数调用
1.函数调用形式
当在程序中定义了函数之后,就意味着该函数将会在程序中被执行,但是怎样执行的
呢?先看一个实例。
【例5.5】求两个数阶乘和的函数调用实例。
先设计两个函数:求给定数的阶乘函数factorial。、求两个阶乘和函数sum().
longfactorial(intn)
longrtn=1;
inti;
for(i=l;i<=n;i++)
rtn*=i;
return(rtn);
)
longsum(inta,intb)
(
longcl,c2;
cl=factorial(a);
c2=factorial(b);
retum(cl+c2);
)
然后,我们写一个主函数main。,其代码如下:
#include<stdio.h>
#include<conio.h>
longsum(inta,intb);
longfactorial(intn);
main()
(
intnl,n2;
longResult;
clrscr();
printf("Pleaseinputtwointegernumbers(nlandn2):");
scanf("%d%d",&nh&n2);
Result=sum(nl,n2);
printf(nResult=%Id",Result);
getch();
)
当从键盘上输入a,b的值为3和4后,程序执行结果如下:
Pleaseinputtwointegernumbers(n1andn2):34/
Result=30
通过例5.5,我们可以看到,在主函数main。中使用函数sum(),函数sum()中又使用函
数factorial。。这就是函数的调用。在TurboC中,函数调用时直接使用函数名和实参的方法,
也就是将要赋给被调用函数的参量,按该函数说明的参数形式传递过去,然后进入子函数运
行,运行结束后再按子函数规定的数据类型返回一个值给调用函数。使用TurboC的库函数
就是函数简单调用的方法。值得注意的是:函数不能嵌套定义,函数间可以互相调用,但不
能调用main()函数。
调用函数的一般形式如下:
函数名(实参列表);
其中,实参是有确定值的变量或表达式,各参数间需要用逗号分开。在实参表中,实参
的个数与顺序必须和形参的个数与顺序相同,实参的数据类型必须和对应的形参数据类型相
同。若为无参数调用,则调用时函数名后的括号不能省略。C中函数在程序中的调用可以有
以下几种方式。
2.函数调用方式
首先我们看例5.6,请上机运行程序,并注意执行结果,考虑函数不同的调用方式。
【例5.6]不同函数调用方式实例。
#include<stdio.h>
#include<conio.h>
intmax(int,intent);
main()
(
inta,b,c,result1,result2;
clrscr();
printf("Pleaseinputtwointegernumbers(aandbandc):u);
scanf("%d,%d,%d”,&a,&b);
result1=3*maxmum(a,b,c);
printf("Middleoftwonumbers,maxnumberis:%d\nn,resultl);
result2=maxmum(a,maxmum(b,resultl),c);
printf(nMiddleoftwonumbers,maxnumberis:%d\nn,result2);
printf(MMiddleoftwonumbers,maxnumberis:%d\nn,maxmum(a,b,result2));
getch();
)
intmaxmum(intx,inty,intz)
{intmax;
max=x>y?x:y;/*求最大值*/
max=max>z?max:z;
retum(max);/*返回最大值*/
)
通过观察上述程序段,我们可以看出,C中函数调用按函数在程序中出现位置来分,可
以有以下三种调用方式:
(1)函数语句,即把函数调用当作一条语句。如例中的标准函数clrscr()、getch()o
(2)函数表达式,即函数出现在一个表达式中,要求函数带回一个确定的值以参加表
达式运算。如例中的c=3*maxmum(a,b)o
(3)函数参数,即函数调用作为一个函数的实参。如例中的
result2=maxmum(a,maxmum(b,resultl),c)o实际上,例中的printf("Middleoftwo
numbers,maxnumberis:%d\nn,maxmum(a,b,result2));语句也是把maxmum
(a,b,resul⑵作为printf函数的一个参数。
【例5.7]打印出0至9的平方值
#include<stdio.h>
#include<conio.h>
intsqu(intin);
voidmain()
(
intx,result;
clrscr();
for(x=0;x<=9;x++)
result=squ(x);/*y=x*x*/
printf("Thesquareof%dis%d\n",x,result);
getch();
for(x=0;x<=9;++x)
printf("Thevalueofsqu(%d)is%d\n,,,x,squ(x));
getch();
)
intsqu(intin)
(
intsquare;
square=in*in;
retum(square);
)
这个程序的两个循环都是打印出0到9的平方值。第一个循环中的函数squ()的返回值
由变量result来接收;第二个循环中,函数squ()的返回值直接用做printf函数的参数。
值得提醒的是:不论在什么情况下,只要进行了有参函数的调用,就必须要求实参与形
参的个数相等,类型和参数顺序也一致。但在C的标准中,实参表的求值顺序并不是确定的。
有的系统按自右向左的顺序计算,而有的系统则按自左向右的顺序计算。在大多数情况下,
这个顺序对函数调用没什么影响,但有时我们必须考虑这个问题。请读者分析下面的例5.8,
看看程序输出什么值。我们的TurboC系统采用的是自右向左的计算顺序。
【例5.8]实参表自右向左的求值顺序
#include<stdio.h>
#include<conio.h>
intsum(intx,inty);
main()
(
inta=10,result;
clrscr();
result=sum(a,a=a+5);
printf("Result=%d\n",result);
getch();
)
intsum(intx,inty)
(
return(x+y);
)
执行上述程序后,结果显示:
Result=30
经过分析,可以看出我们所采用的C系统是按自右向左的结合规则运算的,否则木程序
的运行结果应该是:Result=25(按自左向右的结合规则运算)。我们再看一个比较特殊的
函数调用的例子。
【例5.9】•个特殊的函数调用的例子。
#include<stdio.h>
intfunc(inta,intb);
voidmain()
{intk=4,m=l,p;
p=func(k,m);printf(n%d,",p);
p=func(p,p=p+3);printf(H%d,",p);
p=func(printf(M%d,n,p),p);printf("%cT,p);
)
intfunc(inta,intb)
{intm=0,i=2;
i+=m+1;
m=i+a+b;
retum(m);
)
程序输出是:
8,25,25,31(请读者分析该程序。)
通过以上几个实例的学习,我们基本熟悉了函数调用的一般形式。在这里,我们提醒读
者,当函数没有参数时,在形参表中最好使用关键字void。虽然这不是绝对必要的,但是,
对C的编译器检查参数是否正确是大有好处的。例如,假设有如下的函数原型:
voidmyfunction(void);
若用下面的语句调用:
myfunction(myparam);
则系统将会报告错误信息。所以,若函数不返回任何值或函数无任何参数时,我们建议把该
类函数说明为void类型,要不然,系统编译器会理解为该函数是整型的(在前面我们介绍,
当函数名前不加类型说明符时,系统默认为为整型函数),这样容易产生错误。
5.1.4实训|函数调用
实训目的
1.熟悉函数定义格式及应用。
2.掌握函数调用含义与调用格式。
3.重点掌握函数调用的三种方式:作为函数语句、作为函数参数、作为函数表达式。
实训内容
要求:自定义一个检测函数,然后调用函数检测C程序中非语法类、非语义类逻辑错误,
并打Epl相关信息。
1.自定义能够检测蓝char、int型数组、char型数组等类型的排错函数debug()。
(1)启动TurboC系统,进入编辑环境;
(2)自定义函数debug。,其函数原型是:
voiddebug(charlet,charc_array[],intn_arraylJ,num,intopt);
其中:opt是要使用的可选项:其值为1,输出整型数;值为2,输出字符型;
值为3,输出整型数组;值为3,输出字符型数组;其它值为错。代码如下:
voiddebug(charlet,charc_array[],intn_array[],intasize,intnum,intopt)
inti;
switch(opt)
case1:/*整型数*/
clrscr();
printf(MThevalueis%d",num);
break;
case2:/*字符型*/
clrscr();
printf(nTheletteris%cM,let);
break;
case3:/*整型数组*/
clrscr();
puts(HThenumberarraycontains:\n");
for(i=0;i<=asize;++i)
printf(n%dn,n_aiTay[i]);
break;
case4:/*字符型数组*/
clrscr();
puts(nThecharacterarraycontains\n");
for(i=0;i<=asize;++i)
printf("%c”,c_array[i]);
break;
default:
clrscr();
puts(n\nlnvalidoptionselected!0);
break;
I
puts("\nPleasepressanykeytocontinue:");
getch();
)
2.main()函数中定义int、char、int型数组、char型数组,调用debug。函数来检测给定
值是否符合所定义的类型。代码为:
voidmain()
(
inti,j,a[10];
charch,b[10];
for(i=5,j=0;i<15;++i,++j){
a[j]=j;
bgj;
}
ch='a';
debug(0,0,0,0,i,l);/*输出整型i的值*/
debug(ch,0,0,0,0,2);/*输出字符型ch的值*/
debug(0,0,a,10,0,3);/*输出整形数组a中各元素的值*/
debug(0,b,0,10,0,4);/*输出字符型数组b中各元素的值*/
debug(0,0,0,0,0,7);/*错*/
)
重要提示:在上机调试程序时,请将上述自定义的debug。函数代码加到主函数main。
之前或之后。
3.保存上述设计的代码,编译、调试、连接并运行,记录运行结果。
实训思考
1.函数调用的基本格式是什么?
2.函数可以有哪些不同的调用方式?
3.若要进行float、double等类型数据的检查,则程序应如何扩充和修改?
5.1.5函数返回值
在上面各实例定义的函数体的最后有一条return语句。一般使用return语句山被调用函
数向调用函数返回值,该语句有下列用途:
(1)它能立即从所在的函数中退出,返回到调用它的程序中去。
(2)返回一个值给调用它的函数。
有两种方法可以终止子函数运行并返回到调用它的函数中:一是执行到函数的最后一条
语句后返回,这表明一个函数中可以没有return语句;一是执行到语句return时返回。前
者当子函数执行完后仅返回给调用函数一个数值(若函数被定义为void型,则不返回任何
值)。若要返回一个值,就必须用return语句。只需在return语句中指定返回的值即可。
返回语句一般有如下的形式:
return;或return表达式;或return(表达式);
【例5.10]不带返回语句的函数应用
#include<stdio.h>
#include<conio.h>
inttotal(intx9inty);
main()
(
inta,b;
clrscr();
printf(nPleaseinputtwointegernumbers(aandb):");
scanf(M%d,%d",&a,&b);
total(a,b);
getch();
)
inttotal(intx,inty)
(
printf(MThetotalis%dAn",x+y);
)
值得注意的是:表达式的类型必须和该函数的类型一致。对于不返回函数值的函数,函
数的类型指定为void,这时,return语句不能带有表达式。
另外,一个函数可以有一个以上的return语句。程序执行到哪个return语句,哪个return
语句就起作用。请看下面的例子5.11。
【例5.11]多return语句的函数应用
本例子定义的函数作两个浮点数的除法运算。当除数为0时,函数不进行运算,只给出
信息便返回调用它的函数。如果除数不为0,则返回计算结果。
#include<stdio.h>
#include<conio.h>
floatdiv(floatx,floaty);
main()
{
floata,b,DivResult;
clrscr();
printf("Pleaseinputtwofloatnumbers(aandb):");
scanf(n%f,%f,,&a,&b);
DivResult=div(a,b);
printf("Theprogramexecuted'Resultis%f\n",DivResult);
getch();
)
floatdiv(floatx,floaty)
(
if(y==0)
(
printf(nproblemwithparameter!\nn);
return;
)
retum(x/y);
)
5.1.6实训建立和使用函数
实训目的
1.掌握函数原型、函数定义格式与调用格式。
2.重点掌握return语句形式、功能和函数调用时的返回值。
3.掌握字符串的求串长、查找、删除、插入、替换等操作。
4.培养和锻炼解决较复杂C程序设计的能力。
实训内容
要求:自定义相关的字符串操作函数,实现用户从键盘输入源字符串,再输入字符串1
和字符串2。然后调用相应的功能函数,处理在源串中删除字符串1,并用字符串
2来代替字符串1的操作,并将结果显示出来。
1.根据分析要求,我们设计五个自定义函数分别实现求串长、查找、删除、插入、替换。
(1)启动TurboC系统,进入编辑环境;
(2)根据系统需求,自定义相关的函数,设计的函数各代码如下。
①求字符串长度函数原型:length(charstring]]);其实现代码是:
intlength(charstring[])/*求字符串的长度函数*/
{intindex=0;
while(stringfindex]!='\0')
index++;
return(index);
)
②字符串查找函数原型:intfind_string(charstring1[],charstring2[]);其实现
代码是:
intfind_string(charstring1[],charstring2[])/*在string1中查找string2*/
{chartemp;
intindex1=0,index2;
while(string1[index1]!=*\0"){
index2=0;
temp=stringl[indexl+index2];/*卜.面while循环是找子字符串位置*/
while((String2[index2]!=!\01)&&(temp==string2[index2])){
temp=string1[index1+++index2];
)
if(string2[index21==*\0")/*找到*/
return(index1);
index1++;
}
return(-1);/*未找到*/
)
③字符串删除函数原型:remove_string(charstring]],intstart,intcount);其实
现代码是:
remove_string(charstring!J,intstart,intcount)/*删除指定位置上的子串*/
{intlen,index;
chartemp;
index=start+count;
len=length(string);
while(len>index){
temp=string[index];
string[index-count]=temp;
index++;
)
string[index-count]='\0';
)
④字符串插入函数原型:insert_string(charstring1[],charstring2[],intpos);其实
现代码是:
insert_string(charstring1[J,charstring2[],intpos)/*指定位置插入串*/
{intlenl,len2,index;
chartemp;
lenl=length(stringl);
len2=length(string2);
index=lenl;
while(index>=pos){
temp=string1[index];
string1[index+len2]=temp;
index—;
index=0;
while(index<len2){
temp=string2[index];
stringl[pos+index]=temp;
index++;
)
)
⑤字符串替换函数原型:intreplace(charsource[],source,charstring1[],char
string2[]);其实现代码是:
intreplace(charsource[J,source,charstring1[],charstring2[J)
{intstart,count;
if((start=find_string(source,string1))!=-1){
count=length(string1);
remove_string(source,start,count);
replace(source,string1,string2);
insert_string(source,string2,start);
return(1);
)
return(0);
)
2.在主函数中输入源串source、串stringl、串string2,调用自定义函数,并输出结果:
main()
(
charsource[80],string1[80],string2[80];
clrscr();
printf("Source_string:\n");
scanf(u%sn,source);
printf(uStringl:\nn);
scanf(u%s",stringI);
printf(uString2:\nn);
scanf(',%s,,,string2);
if(replace(source,string1,string2))
printf("\n%s\n'source);
else
printf(H\nNotchanged.\nn);
getch();
)
重要提示:在上机调试程序时,请将上述自定义的各个函数代码加到主函数main()
之前或之后。
3.保存上述设计的代码,编译、调试、连接并运行,记录运行结果。
实训思考
1.函数声明与函数定义有何区别?函数原型主要功能是什么?
2.函数定义与函数调用的格式是什么?
3.函数名后括号内的形式参数可以有哪些说明方式,试举例说明?
4.函数的返回值有可以是哪些?return语句的形式有哪些,其功能是什么?
5.在较复杂程序设计中,设计功能相对独立的函数模块有什么优越性?
5.2形参与实参
在调用函数时,大多数情况下,主调函数和被调函数之间有数据传递关系(这就是前面说
到的有参函数)。在定义有参函数时函数名后括弧中的变量名称称为“形式参数”(简称“形
参”),在主调函数中调用一个函数时,此函数名后面括弧中的参数称为''实际参数”(简称“实
参”)。在TurboC语言中调用函数时,参数传递有两种方式:值调用和引用调用。在参数传
递时,可以分为:简单变量作为函数参数传递、数组名作为函数参数传递和指针作为函数参
数传递等多种情况。
5.2.1函数值调用和引用调用
TurboC中调用函数时直接使用函数名和实参的方法,也就是将要赋给被调用函数的参
量,按该函数说明的参数形式传递过去,然后进入子函数运行,运行结束后再按子函数规
定的数据类型返回一个值给调用函数。使用TurboC的库函数就是函数简单调用的方法。
对有参函数来说,只要存在函数调用,就会通过参数和返回值的传递交换信息。信息交
换是在函数调用过程和返回过程中进行的。本节我们要讨论的是在函数调用时,按什么形式
传递参数。
1.值调用
值调用方法是把实参的值拷贝给形参,即调用函数向被调用函数传递的参数是变量本身
值。在内存中,由于形参与实参占用不同的存储单元,这时形参值的变化将不影响实参的值。
到目前为止,我们所举的函数实例中,采用的都是这种值调用。在这里不再赘述。
2.引用调用
return语句可以向调用函数返回值,但这种方法只能返回一个参数,在许多情况下要返
回多个参数,这时用return语句就不能满足要求。TurobC提供了另一种参数传递的方法,
即引用调用,该方法是在调用时把实参的地址拷贝到形参,使用地址去访问实参。此时调用
函数向被调用函数传递的参数不是变量本身,而是变量的地址,当子函数中向相应的地址写
入不同的数值之后,也就改变了调用函数中相应变量(实参)的值(形参值变化影响实参值
变化),从而达到了返回多个变量值的目的。在TurboC中,引用调用是通过指针实现的,在
内存中,形参与实参占用相同的存储单元。
引用调用的函数原型是:
函数类型函数名(参数类型*参数1,参数类型*参数2,•••);
调用时的形式是:
函数名(&参数1,&参数2,…)
【例5.12]函数的引用调用示例。
#include<stdio.h>
#include<conio.h>
voidswap(char*,char*);/*声明指针类型参数*/
main()
{charchl='A',ch2=B;
clrscr();
printf("调用函数swap()之前chi与ch2的值是:);
printf("ch1=%c\tch2=%c\n",ch1,ch2);/*调用swap。前chl,ch2的值*/
swap(&ch1,&ch2);1*引用调用*/
printf("调用函数swap()之后chi与ch2的值是:");
printf(nch1=%c\tch2=%c\n",ch1,ch2);/*调用swap。后chi,ch2的值*/
getch();
)
voidswap(char*x,char*y)
{chartemp;
temp=*x;
*x=*y;
*y=temp;
printf("形参的值:x=%c\ty=%c\nH,*x,*y);
)
执行上述程序,运行结果如下:
调用函数swap()之前chi与ch2的值是:chi=Ach2=B
形参的值:x=By二A
调用函数swap。之后chi与ch2的值是:chl=Bch2=A
在上面例5.12中,函数swap。的参数被声明为指针类型。并且,尽管swap。的操作结果
在main。中输出,但我们仍然定义函数swap。为void类型。执行上述程序,我们会发现字符
变量chi和ch2的值在函数swap。调用前后发生了改变。
【例5.13】
#include<conio.h>
#include<stdio.h>
voidsubfun(int*i,int*j);/*声明子函数*/
intmain()
(
inti,j;
clrscr();
printf("Pleaseinputparamenter(i,j=?):H);
scanf(n%d,%d”,&i,&j);/*从键盘输入2个整数*/
printf("\nlnmainbeforecalling:"/*输出此2数及其乘积*/
*'i=%-4dj=%-4di*j=%-4d\n",i,j,i*j);
subfun(&i,&j);/*以传送地址的方式调用子函数*/
printf(u\nlnmainaftercalling:"/*调用子函数后输出变量值*/
ni=%-4dj=%-4di*j=%-4d\nu,i,j,i*j);
getch();
)
voidsubfun(int*i,int*j)
{
printf("\nlnsubfunaftercalling:"/*子函数中输出变量值*/
ni=%-4dj=%-4di*j=%-4d\n",*i,*j,*i**j);
)
其中:〒*j表示指针i和j所指的两个整型数*i和*j之乘积。程序输出是:
Pleaseinputparamenter(i,j=?):-12,11/
Inmainbeforecalling:i=-12j=lli*j=-132
Insubfunaftercalling:i=-10j=-21i*j=210
Inmainaftercalling:i=-10j=-21i*j=210
注意:由于用户编写的函数•般在对其声明和定义时就规定了形式参数类型,因此调用
这些函数时要求实参必须与子函数中形式参数的数据类型、顺序和数量完全相同,否则在调
用中将会出错,得到意想不到的结果。
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 旅游景区2024年度广告位经营权转让合同
- 2024年度技术转让与授权使用合同3篇
- 瓷砖工程分包方案
- 瓷砖内嵌地脚线施工方案
- 瓷器彩绘中日对比研究报告
- 灯罩制作直播课程设计
- 保单贷款合同模板 2篇
- 二零二四年度设备租赁合同:比亚迪弗迪租赁服务协议
- 滴滴数据运营策略研究报告
- 2024年度技术咨询合同:某咨询公司为某企业提供环保技术咨询的具体条款2篇
- 血管内导管相关感染的预防与治疗指南
- 《幼儿卫生与保育》考试复习题库(含答案)
- 2024中智集团招聘重要岗位高频考题难、易错点模拟试题(共500题)附带答案详解
- 工程部项目培训
- 农产品质量培训
- DB11/1950-2021-公共建筑无障碍设计标准
- (正式版)SHT 3115-2024 石油化工管式炉轻质浇注料衬里工程技术规范
- 小班语言《拔萝卜》课件
- 房屋修缮施工方案
- (高清版)TDT 1041-2013 土地整治工程质量检验与评定规程
- 批次管理全面手册
评论
0/150
提交评论