清华谭浩强C语言课件第8章函数.ppt
第8章 函 数,8.1 概述,C语言是通过函数来实现模块化程序设计的。一个较大的程序应分为若干程序模块,每个模块实现一个特定的功能,这个模块称为子程序。C的子程序是通过函数实现的,函数是C语言程序的基本单位。,函数的构成,源程序是由函数组成的。函数是源程序的基本模块,通过对函数模块的调用实现特定的功 能。实用程序往往包括一个主函数main()和 若干其他函数。其中主函数main()是必须的,它是所有函数的执行起点。由主函数调用其它函数,其它函数也可以互相调用,同一函数可以被一个或多个函数调用任意多次。调用示意图如下:,程序的全部工作都是由各式各样的函数完成的,所以也把语言称为函数式语言。,程序开发中使用函数的优点,1)使用函数可以控制任务的规模2)使用函数可以控制变量的作用范围3)使用函数,程序的开发可以由多人分工协作 4)使用函数,可以重新利用已有的、调式好的、成熟的程序模块 5)函数模块相对独立,功能单一,可混合编写也 可独立编写调试。,函数的一些说明,1)一个C程序由多个程序模块组成,每个模块作为一个源程序文件,多个源程序文件组成一个C程序,这样便于分别编写分别编译,提高调试效率,一个源程序文件可为多个C程序共用。2)一个源程序文件由一个或多个函数及其相关内容(如数据定义等)组成,一个源程序文件是一个基本的编译单位。3)C程序的执行从主函数main()开始(称为主调函数),可以调用其它函数(称为被调用函数),调用流程返回main(),最后函数在main()中结束。4)所有函数都是平行的,在定义时候是分别进行的,相互独立,无从属关系,不可嵌套定义。函数间可相互调用,但不能调用主函数,主函数只能由系统调用。,函数的分类,1.从用户使用的角度 1)标准函数(库函数),由系统提供,用户不必自定义可直接使用,注意:不同C编译系统提供的库函数可能有些不同 2)用户自定义函数,用来解决用户专门需要。2.从函数的形式 1)无参函数。在调用函数时,main不向被调用函数传递数据,只用来执行一组操作。2)有参函数,主调函数在调用被调用函数时,通过参数向其传递数据,一般情况下,执行被调用函数时,得到一个函数值,供主调函数使用。,8.2 函数定义的一般形式,函数应当先定义,后调用(1)无参函数的一般形式 函数类型 函数名()说明语句部分;可执行语句部分;无参函数一般不需要返回函数值,函数类型void类型(空类型),2)有参函数的一般形式 函数类型 函数名(形参表列)说明语句部分;可执行语句部分;,例:int max(x,y)int x,y;/形式参数说明/int z;/函数体中的说明部分/z=xy?x:y;return(z);,3“空函数”类型说明符 函数名()“空函数”什么操作也不做。其作用是在此处留一函数的位置,以便将来扩充功能之用。函数名也在将来换取实际的函数名。,函数定义的一些说明,1.函数头(首部):说明了函数类型、函数名称及参数。(1)函数类型:函数返回值的数据类型,可以是基本数据类型也可以是构造类型。如果省略默认为int,如果不返回值,定义为void类型。(2)函数名:给函数取的名字,以后用这个名字调用。函数名由用户命名,命名规则同标识符。(3)函数名后面是参数表,无参函数没有参数传递,但“()”号不能省略,这是格式的规定。参数表说明参数的类型和形式参数的名称,各个形式参数用“,”分隔。,2.函数体:函数首部下用一对括起来的部分。如果函数体内有多个,最外层是函数体的范围。函数体一般包括声明部分、执行部分两部分。1)声明部分:在这部分定义本函数所使用的变量和进行有关声明(如函数声明)。2)执行部分:程序段,由若干条语句组成(可以在其中调用其它函数)。,例:输入三个整数,求三个整数中的最大值不使用函数(除main外)main()int n1,n2,n3,nmax;scanf(“%d%d%d”,使用函数int max(int,int,int);/*函数声明*/main()int n1,n2,n3,nmax;scanf(“%d%d%d”,像调用库函数一样调用,函数定义,8.3 函数参数和函数的值,8.3.1 形式参数与实际参数 在调用函数时,大多情况下,主调与被调函数间有数据传递关系,这就是有参函数。在定义函数时,函数名后面括号中的变量名称为“形式参数”,在主调函数中调用一个函数时,函数名后面括号中的参数(可以是表达式)称为“实际参数”。发生函数调用时,调用函数把实参的值复制一份,传送给被调用函数的形参,从而实现调用函数向被调用函数的数据传送。,例 从键盘输入两个数,输出其中较大的一个。main()int a,b,c;scanf(“%d,%d”,说明:1)形参变量在被调用前不占用存储单元;在被调用结束 后,形参所占存储单元亦被释放。因此,形参只有在该函数内有效。调用结束,返回调用函数后,则不能再使用该形参变量。2)实参可以是常量、变量、表达式、函数等。无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值,以便把这些值传送给形参。因此,应预先用赋值、输入等办法,使实参获得确定的值。3)实参对形参的数据传送是单向的,即只能把实参的值传送给形参,而不能把形参的值反向地传送给实参。4)实参和形参占用不同的内存单元,即使同名也互不影响5)在被定义函数中,必须指定形参的类型。实参和形参的类型应相同或赋值相容。,main()int a=3,b=5;void swap(int,int);swap(a,b);printf(“a=%d,b=%dn”,a,b);void swap(int x,int y)int temp;temp=x;x=y;y=temp;printf(“x=%d,y=%d n”,x,y);是按值传递的按址传递放在指针里面讲。,8.3.2 函数的返回值,通常,希望通过函数调用使主调函数得到一个确定的值,这就是函数的返回值。说明如下:1)函数的返回值是通过return语句获得的。当不需返回函数值时,可省去return语句。2)return语句的后面可以有括号,也可以没有。如:return z;return(z);3)return语句的后面可以是变量,也可以是表达式。如:return(x y?x:y);,4)return语句返回值的类型应与该函数的类型一 致。否 则以函数类型为准。5)若函数中没有return语句,则该函数被调用后也会带 回不确定的值。为了明确表示不需要函数返回值,可 以用“void”定义函数为“无类型”。凡不需要返回值的函数,一般均定义为“void”类型。6)一个函数可以有一个以上的return语句,执行到哪个return语句,哪个return语句起作用。,8.4 函数的调用,在程序中,是通过对函数的调用来执行函数体的,其过程与其它语言的子程序调用相似。语言中,函数调用的一般形式为:函数名(实际参数表)说明:1)对于无参函数,尽管没有“实参表”,但也不得省略括号。2)“实参表”中的参数之间用逗号分开。3)实参与形参之间的个数及类型必须一一对应。4)对实参求值的顺序是自左至右还是自右至左,视具体的系统而定。Turbo C 和 MS C 是按自右至左的顺序求值。见P162 例8.4,8.4.2 函数调用的方式,按照函数在程序中出现的位置,可以有以下三种调用方式:1)函数语句:C语言中的函数可以只进行某些操作而不返回函数值,这时的函数调用可作为一条独立的语句。如 printf(“C pragram”)gets(s);2)函数表达式:函数作为表达式的一项,出现在表达式中,以函数返回值参与表达式的运算。这种方式要求函数是有返回值的。如:c=2 max(a,b);3)函数参数:函数作为另一个函数调用的实际参数出现。这种情况是把该函数的返回值作为实参进行传送,因此要求该函数必须是有返回值的。如:m=max(max(a,b),c);,8.4.3 对被调用函数的声明和函数原型,对被调用函数的声明在一个函数被另一个函数调用时,须具备以下条件:1)被调用的函数已存在2)如果被调函数为库函数,则应在文件开头 用“#include”命令声明相应的“头文 件”。如:#include“stdio.h”#include“math.h”3)如果被调函数为自定义函数且其定义在主调函数定义之后,则应在主调函数中说明其类型(即对被调用函数进行声明)。,函数声明的作用是把函数名、函数参数的个数和参数类型等信息通知编译系统,以便在调用时,编译系统能正确识别函数并检查调用是否合法。函数声明又称函数原型。格式如下:函数类型 函数名(参数类型1,参数类型2,参数类型n);函数类型 函数名(参数类型1,参数名1,参数类型2,参数名2,参数类型n,参数名n);如果不声明,系统无法在调用时对函数调用的正确性进行检查,容易出错。,注意:函数的定义和声明不是一回事。定义是对函数功能的确立,包括指定函数名、函数值类型、形参及其类型、函数体等,它是一个完整的、独立的的函数单位。而函数的声明则是把函数的名字、函数类型以及形参的类型、个数和顺序等通知编译系统以便在调用时进行对照检查。如:main()double new_style(int,double);/*函数声明*/Double new_style(int a,double x)/*函数定义*/,说明:1)类型标识符 被调函数名();这种声明形式也是合法的,但不提倡。2)如果被调函数为自定义函数且其定义在主调函数定义之前,则在主调函数中可不必说明其类型。因为编译程序已知道其类型。3)如果被调函数的值是整型或字符型,可不必声明类型,系统自动按整型说明。,4)如果在所有被调函数定义之前、在文件的开头、在函数的外部已对被调函数作了类型说明,则在各主调函数中可不必说明其类型。见P166例。,char letter();float f();int i();main(),/主调函数中不必说明它所调用的函数的类型/,8.5 函数的嵌套调用,函数不允许嵌套定义,但是允许嵌套调用。函数的嵌套调用是指,在执行被调用函数时,被调用函数又调用了其它函数。这与其它语言的子程序嵌套调用的情形是类似的,其关系可表示如下图:,例:用弦截法求方程的根。x35x2+16x80=0,(1)取两个不同点x1、x2,如果f(x1)和f(x2)符号相反,则(x1,x2)区间内必有一个根。如果f(x1)与f(x2)同符号,则应改变x1、x2,直到f(x1)、f(x2)异号为止。注意x1、x2的值不应差太大,以保证(x1,x2)区间只有一根。,方法如下:,(2)连接f(x1)和f(x2)两点,此线(即弦)交x轴于x.,x点坐标可用下式求出:,再从x求出f(x)。,3)若f(x)与f(x1)同符号,则根必在(x,x2)区间内,此时将x作为新的x1。如果f(x)与f(x2)同符号,则表示根在(x1,x2)区间内,将x作为新的x2.,4)重复步骤(2)和(3),直到|f(x)|为止,为一个很小的数,例如106。此时认为f(x)0.,根据上述思路画出n-s流程图,见下图,root函数,程序由若干个函数构成,#include math.h float f(x)/*定义f函数,以实现f(x)=x35x2+16x80*/float x;float y;y=(x5.0)*x+16.0)*x80.0;return(y);,float xpoint(x1,x2)/*定义xpoint函数,求出弦与x轴交点。*/float x1,x2;float y;y=(x18f(x2)x2*f(x1)/(f(x2)f(x1);return(y);,float root(x1,x2);/*定义root函数,求近似根。*/float x1,x2;int i;float x,y,y1;y1=f(x1);dox=xpoint(x1,x2);,y=f(x);if(y*y10)/*f(x)与f(x1)同符号。*/y1=y;x1=x;else x2=x;while(fabs(y)=0.0001);return(x);,main()/*主函数*/float x1,x2,f1,f2,x;do printf(input x1,x2:n);scanf(%f,%f,while(f1*f2=0);x=root(x1,x2);printf(A root of equation is%8.4f,x);,运行情况如下:input x1,x2:2,6A root of equation is 5.000,8.6 函数的递归调用,在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。C语言的特点之一就在于允许函数的递归调用。,显然:上述例子会无限递归(无限执行)。所以,在递归调用时都有条件限制。,即:条件成立,调用递归,否则结束。,例8.7 有5人排成一队,从最后一人开始,其年龄均比 前面的人大2岁,而最前面的人年龄是10岁,问 最后一人的年龄是多少岁?,main(),age(5),age(4)+2,age(n)n=5,age(3)+2,age(n)n=4,age(2)+2,age(n)n=3,age(1)+2,age(n)n=2,age(1),age(n)n=1,age(1)=10,age(2)=12,age(3)=14,age(4)=16,age(5)=18,输出age(5),age(n)int n;int c;if(n=1)c=10;else c=age(n1)+2;return(c);,main()printf(“%dn”,age(5);,运行结果:18,例8.8 用递归方法求n!,1.从数学上定义,2.程序 float fac(n)int n;float f;if(n0)printf(input error!n);else if(n=0 n=1)f=1;else f=nfac(n 1);return(f);,main()int n;float y;printf(input a integer!)scanf(%d,3.执行过程:设输入n5,可简化表示为:,当变成机器代码时,将其拉成直线(线性程序代码)。,例:P118汉诺塔(Hanoi)问题,问题:将A塔上n个盘子移至C(借助于B)。移动时,保证三个塔始终是大盘在下,小盘在上。,必须用递归方式解决,分析见P175,1)先将A塔n 1个盘子借助于C移至B上,2)将A上剩下的一个移至C上.,3)将B上n 1个盘子借助于A移至C上.,可以看到:1)、3)为同一问题,都为n 1个盘子借助于一个空塔移至另一塔上。,程序如下:void move(getone,putone)char getone,putone;printf(%c%cn,getone,putone);void hanoi(n,one,two,three)/*将n个盘从one借助two,移动three*/char one,two,three;,int n;if(n=1)move(one,three);else hanoi(n1,one,three,two);move(one,three);hanoi(n1,two,one,three);,main()int m;printf(input the number of disdes:);scanf(%d,运行情况如下:input the number of disdes:3 The step to moving 3 diskes:A C A B C B A C B A B C A C,两个函数:move(getone,putone)表示从getone 塔移一个盘子至putone塔,hanoi(n,one,two,three)表示n个盘子从one塔借助于two塔(空)移至three塔。调用时塔用字符常量A,B,C 表示。,8.7 数组作为函数参数,分为两种情况:,1.数组元素作为实参,2.数组名同时为形、实参,一、数组元素作为实参,由于数组元素与相同类型的简单变量地位完全一样;因此,数组元素作函数参数也和简单变量一样,也是值的单向传递,例:设有两个同样大小的一维数组,a10,b10将相应元素比较,统计a中大于b中对应元素的个数,小于的个数,相等时的个数。,程序如下:main()int lange(int x,int y)int a10,b10,i,n=0,m=0,k=0;printf(enter array a:n);,for(i=0;i10;I+)scanf(5,d,else if(large(ai,bi)=0)m=m+1;else k=k+1;printf(aibi%d timesnai=bi%d timesnaik)printf(array a is larger than array bn);else if(nk)printf(array a is smaller than array bn);else printf(array a is equal to array bn);,int large(x,y)int x,y;int flag;if(xy)flag=1;else if(xy)flag=1;else flag=0;return(flag);,运行情况如下:enter array a:1 3 5 7 9 8 6 4 2 0,enter array b:5 3 8 9 1 3 5 6 0 4 aibi 4 times ai=bi 1 times aibi 5 times array a is smaller than array b,二、数组名作实、形参,特点:直接用数组名作参数时,则为地址传送(不是值传送),即实参数组的首地址传递给形参数组首地址。所以,实参、形参数组共享相同的内存单元。,1.形参数组可不指定大小,也可用另一参数作大小,以确定使用实数组的元素个数。,2.形参、实参数组必须类型一致。,3.多维数组方式一样,仅第一维大小的说明可省略,例1.有一个一维数组score,内放10个学生成绩,求平均成绩。,程序如下:,float average(array)float array10;int i;float aver,sum=array 0;for(i=1;i10;i+)sum=sum+arrayi;aver=sum/10;,return(aver);main()float score 10,aver;int i;printf(input 10 score:n);for(i=0;i10;i+)scanf(%f,aver=average(score);printf(average score is%5.2f,aver);,运行情况如下:input 10 scores:100 56 78 98.5 76 87 99 67.5 75 97 average score is 83.40,程序2.float average(array,n)int n;float array;int i;float aver,sum=array0;for(i=1;in;i+)sum=sum+arrayi;aver=sun/n;return(aver);,main()static float score_15=98.5,97,91.5,60,55static float score _2 10=67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5printf(“the average of class A is%6.2fn”,average(score_1,5);printf(“the average of class B is%6.2fn”,average(score_2,10);,运行结果如下:the average of class A is 80.40 the average of class B is 78.20,8.8 局部变量和全局变量,8.8.1 局部变量概念:是指在一定范围内有效的变量。C语言中,在以下各位置定义的变量均属于局部变量。在函数体内定义的变量,在本函数范围内有效,作用域局限于函数体内。在复合语句内定义的变量,在本复合语句范围内有效,作用域局限于复合语句内。有参函数的形式参数也是局部变量,只在其所在的函数范围内有效。,关于局部变量的作用域还要说明以下几点:1主函数main()中定义的内部变量,也只能在主函数中使用,其它函数不能使用。同时,主函数中也不能使用其它函数中定义的内部变量。因为主函数也是一个函数,与其它函数是平行关系。这一点是与其它语言不同的,应予以注意。2允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。,例如:int f1(int a)/*函数f1*/int b,c;/*a,b,c作用域:仅限于函数f1()中*/int f2(int x)/*函数f2*/int y,z;/*x,y,z作用域:仅限于函数f2()中.x,y,z换为a,b,c也可以*/main()int m,n;/*m,n作用域:仅限于函数main()中*/,8.8.2 全局变量全局变量:在函数之外定义的变量。(所有函数前,各个函数之间,所有函数后)全局变量作用域:从定义全局变量的位置起到本源程序结束为止。全局变量可被作用域内的所有函数直接引用。,#include“stdio.h”int a=3,b=5;/*在函数体外定义的变量*/Main()void fun();printf(“a=%d,b=%d n”,a,b);fun();printf(“a=%d,b=%d n”,a,b);void fun(void)int c;c=a;a=b;b=c;,说明:,1.全局变量增加了函数间数据联系的渠道。由于同一文件中的所 有函数都能引用全局变量的值,当需要从一个函数中带回多个 值时,就能克服函数调用只能返回一个值的局限性。不成文约 定:全局变量名首字母大写。见P185例8.15,2.如无必要,不要使用全局变量。因为全局变量既降低程序的清 晰性和函数的通用性,且又在程序的全部执行过程中都占用存 储空间。,3.在文件开头定义的外部变量才可在整个文件范围内使用,若在 定义点之前的函数需引用外部变量,则可用关键字“extern”作“外部变量说明”。,注意:外部变量定义和外部变量说明并不是同一回事。外部变量的定义只能有一次,它的位置在所有函数之外。而同一程序中的外部变量说明可以有多次,它的位置在函数之内(哪个函数要用就在哪个函数中说明)。系统根据外部变量的定义(而不是根据外部变量的说明)分配存储单元。对外部变量的初始化只能在“定义”时进行,“extern”只是申明该变量是一个已在外部定义过的变量而已。,4.如果在同一源文件中,外部变量与局部变量同名,则在局部变 量的作用范围内,外部变量不起作用。“屏蔽作用”。见P187例 8.16,外部变量的定义与说明。int vs(int xl,int xw)extern int xh;/*外部变量xh的说明*/int v;v=xl*xw*xh;/*直接使用外部变量xh的值*/return v;main()extern int xw,xh;/*外部变量的说明*/int xl=5;/*内部变量的定义*/printf(xl=%d,xw=%d,xh=%dnv=%d,xl,xw,xh,vs(xl,xw);int xl=3,xw=4,xh=5;/*外部变量xl、xw、xh的定义*/,8.9 变量的存储类别(生存期、生命期),变量的存储方式变量从空间上分为局部变量、全局变量。从变量存在的时间的长短(即变量生存期)来划分,变量还可以分为:动态存储变量、静态存储变量。变量的存储方式决定了变量的生存期。,如果全局变量用static修饰,并不是说是静态的,而是说,只对本模块有效。,静态存储变量:存放于静态存储区,在程序整个运行过程中,始终占据固定的内存单元。,动态存储变量:存放于动态存储区,根据程序的运行状态(如:函数调用)而临时分配的单元,且单元并不固定。,每个变量或函数都有两个属性:数据类型和数据存储类别,8.9.2 auto变量auto型存储方式是C语言默认的局部变量的存储方式,也是局部变量最常使用的存储方式。自动变量属于局部变量的范畴,作用域限于定义它的函数或复合语句内。自动变量所在的函数或复合语句执行时,系统动态为相应的自动变量分配存储单元,当自动变量所在的函数或复合语句执行结束后,自动变量失效,它所在的存储单元被系统释放,所以原来的自动变量的值不能保留下来。若对同一函数再次调用时,系统会对相应的自动变量重新分配存储单元。定义格式:auto 类型说明 变量名;auto为自动存储类别关键词,可以省略,缺省时系统默认auto.,8.9.3 用static声明局部变量 静态局部变量的定义格式:static 类型说明 变量名=初始化值;static是静态存储方式关键词,不能省略。静态局部变量的存储空间是在程序编译时由系统分配的,且在程序运行的整个期间都固定不变。该类变量在其函数调用结束后仍然可以保留变量值。下次调用该函数,静态局部变量中仍保留上次调用结束时的值。静态局部变量的初值是在程序编译时一次性赋予的,在程序运行期间不再赋初值,以后若改变了值,保留最后一次改变后的值,直到程序运行结束。,例:求n!,int fac(n)int n;static int f=1;f=fn;return(f);main()int i;for(i=1;i=5;i+)printf(%d!=%dn,i,fac(i);,运行结果为:1!1 2!2 3!6 4!24 5!120,每一次调用fac(i),打印一个i!,同时保留这个i!的值以便下次再乘(i+1)。,8.9.4 register 变量register 变量一般分配register 给相应变量。寄存器比内存操作要快很多,所以可以将一些需要反复操作的局部变量存放在寄存器中。定义格式:register 类型说明 变量名,8.9.5 用extern声明全局变量全局变量作用域:从定义全局变量的位置起到本源程序结束为止。在引用全局变量时如果使用“extern”声明全局变量,可以扩大全局变量的作用域。在文件内声明,全局变量从声明处开始作用。在别的文件声明,作用域扩展到别的文件。,8.9.6 用static 声明全局变量1.全局变量全部是静态存储的 因为全局变量全部是静态存储,所以没有必要为说明全局变量是静态存储而使用关键词static。2.全局变量的static定义 全局变量的static定义,不是说明“此全局变量要用静态方式存储”(全局变量天生全部是静态存储),而是说,这个全局变量只在本源程序模块有效(文件作用域)。一个C语言程序可能是由多个源文件构成、在某个源文件中定义的全局变量可以使用“extern”声明,扩大到其它源文件。也可以使用static声明只在本源程序模块使用。,变量的声明和定义广义上讲,声明包括“定义性声明”(建立存储空间,即指名数据类型),简称定义。还包括“引用型声明”如extern a,不建立存储空间。狭义上的声明为后者,8.10 内部函数和外部函数,函数本身在一个文件中为全局的。即一个文件中定义的函数可被该文件的所有其它函数引用。根据函数能否被其他源文件调用,函数分为内部函数与外部函数。,8.10.1 内部函数类似于全局变量的作用域,函数定义时也可以用static修饰。使用static修饰的函数是内部函数。static 函数类型 函数名(形参表)内部函数:只能被本源文件(模块)中的各个函数所调用,不能为其它模块中函数所调用的函数。“static”的含义不是指存储方式,而是指对函数的作用域仅局限于本文件。使用内部函数的好处是:不同的人编写不同的函数时,不用担心自己定义的函数,是否会与其它文件中的函数同名,因为同名也没有关系。,8.10.2 外部函数外部函数:能被任何源文件(模块)中的任何函数所调用的函数 extern 函数类型 函数名(形参表)说明:外部函数定义,extern关键词可以省略。如果省略,默认是外部函数。外部函数可以在其它模块中被调用。如果需要在某个模块中调用它,可以模块中某个位置声明extern 函数类型 函数名(形参表);就可以了。,例:有一个字符串,内有若干个字符,程序将字符串中该字符删除去。用外部函数实现。,file1.c(文件1)main()extern enter_string(),delete_string(),print_string();/*说明本文件要用到其它文件中的函数*/char c;static char str80;enter_string(str);scanf(%c,delete_string(str,c);print_string(str);,file2.c(文件2)#include stdio.h extern enter_string(str)/*定义外部函数enter_string*/char str80;gets(str);/*读入字符串str*/,file3.c(文件3)extern delete_string(str,ch)/*定义外部函数delete_string*/char str,ch;int i,j;for(i=j=0;stri!=0;i+)if(stri!=ch)strj+=stri;stri=0;,file4.c(文件4)extern print_string(str)/*定义外部函数print_string*/char str;printf(%s,str);,运行情况如下:abcdefgc(输入str)c(输入要删去的字符)abdefg(输出已删去指定字符的字符串),编译:分别编译file1.obj,file2.obj,file3.obj,file4.obj,连接 link file1+file2+file3+file4,主函数,或者在 main()中#include file2.c#include file3.c#include file4.c,编译时,将上述三个文件中的函数插在file1.c前面。,