函数在编程中的重要性不言而喻,那么本篇就来简述一下函数相关的一些内容。
什么是函数函数(Function),译为方法或函数。主函数通过调用自定义函数或函数库中的函数来实现某种目的,或者得到想要的数据。
主函数主函数(main函数)是C程序的入口函数,程序的执行是从main函数开始,对其他函数的调动也是直接或间接地在main函数中进行。
main函数写法 1.无参无返回值
在C89标准中,这种写法是可以接受的(部分编译器会有警告),并且会将其返回值默认为int。实际上,如果函数没有显式声明返回类型,那么编译器会将返回值默认为int。
写法:
#includemain(){ }
例:
#includemain(){ printf("Hello world!"); }
编译:
运行:
2.无参返回void(能不用就别用!)
这种形式在提问区看到的比较多,而且正常来说C语言的标准语法是不允许void main()的,也不知道这种写法是哪里传出来的,个人从学习开始没见过这用法。
写法:
#includevoid main(){ }
例:
#includevoid main(){ printf("Hello world!"); }
编译:
可以看到报错提示,main函数必须返回int。main函数的返回值用于说明程序的退出状态。如果返回0,则代表程序正常退出;返回其它数字的含义则由系统决定。返回非零代表程序异常退出。如果用void那就查询不到程序的结束状态了。
3.无参返回int
这是常见的一种写法(个人用的也比较多,特别是在测试一些小功能算法时)
写法:
#includeint main(){ }
例:
#includeint main(){ printf("Hello world!"); }
编译:
运行:
可以看到最后提示with return value 0这就代表着程序是正常结束的。
4.参数为命令行参数返回int
这种写法需要命令行参数。
(命令行参数:
argc: 代表启动程序时,命令行参数的个数。C和C++语言规定,可执行程序程序本身的文件名,也算是一个命令行参数,因此,argc的值至少是1.
argv[]:指针数组,其中的每个元素都是一个char* 类型的指针,该指针指向一个字符串,这个字符串里就存放着命令行参数。)
写法:
#includeint main(int argc,char *argv[]){ }
例:
#includeint main(int argc,char *argv[]){ printf("%d %s %s",argc,argv[0],argv[1]); }
编译:
通过dev运行:
可以看到argc的值为1,因为没有传入第二个argv所以argv[1]的值为null
通过控制台(cmd或虚拟机终端)运行:
不传入helloworld时的输出和在dev中运行结果一致,传入第二个参数helloworld后,argc变为2,因为传入了两个参数,argv[0]是调用程序的相对路径,argv[1]值为helloworld。
函数库中的函数
C语言为我们提供了上百个可调用的库函数,例如与字符串有关的 strlen, strcat, strlwr . 或是 printf, scanf, 这些都是c语言为我们提供的。在我们使用某一库函数的时候,需要在程序中嵌入(#include<>) 该函数所需要的头文件。
例:将两个字符串连接为一个
不使用函数库
#include#define MAX 1024 int main(){ char s1[MAX] = "hello"; char s2[MAX] = "world"; char s3[MAX] ; int i,j; printf("连接前:n%sn%sn",s1,s2); for(i=0;s1[i]!='';i++){ s3[i]= s1[i]; } for(j =0;s2[j]!='';j++){ s3[i+j] =s2[j]; } s3[i+j]=''; printf("连接后:%sn",s3); }
运行结果:
使用函数库
#include#include #define MAX 1024 int main(){ char s1[MAX] = "hello"; char s2[MAX] = "world"; char *str1,*str2; str1=s1; str2=s2; strcat(s1,s2); printf("%s",s1); }
运行结果:
可以看到不适用函数库的功能函数自己完成连接功能需要进行两次遍历,并且在最后还需要自己增加结束符'',而使用库中的strcat可以很快的完成字符串的连接,且不需要进行其他 *** 作,减少了代码量和运行时间。
自定义函数要自定义一个函数首先需要确定函数的返回值、函数名、及参数。
定义格式:方法一、 <返回值类型> <函数名>(参数);//函数声明 int main(){} <返回值类型> <函数名>(参数){//功能实现 函数功能实现 } 方法二、 <返回值类型> <函数名>(参数){ 函数功能实现 } int main(){}
法一和法二没有太大区别,都可以使用。唯一要注意的就是如果用方法二定义函数,那么要注意自定义函数必须实现了才能调用!接下去通过几个例子来解释
例1:声明与实现
#includevoid fun(); //去掉声明编译器会报错,提示没有定义fun() void fun1(){ printf("this is fun1"); } int main(){ fun(); } void fun(){ printf("this is fun"); }
可以看到上面的代码中void是函数的返回类型,fun就是函数的名称(注意函数的名称同样要符合C语言的命名规范) ,而函数的功能就是在被输出this is fun
运行结果:
可以看到编译后提示fun未声明,所以用方法一定义函数时千万别忘了声明。
例2:函数的嵌套调用
#includevoid fun1(); void fun2(); void fun3(){ printf("this is fun3n"); fun1(); } int fun(); int main(){ fun1(); fun3(); if(fun()==1) printf("this is mainn"); } void fun1(){ printf("this is fun1n"); fun2(); } void fun2(){ printf("this is fun2n"); } int fun(){ return 1; }
运行结果:
可以看到上图的执行结果,主函数调用fun1,fun1输出内容后内部调用了fun2;fun2输出完毕后返回,然后fun1返回到主函数;主函数调用fun3输出后返回,主函数调用fun得到返回值1后进行输出。但是要注意函数可以嵌套调用但不能嵌套定义!
例3:求a和b的和(函数的返回值与传参)
#includeint sum_return(int a,int b){ return a+b; } void sum_primer(int a,int b,int *c){ *c=a+b; } void sum(int a,int b,int c){ c=a+b; } int main(){ int a = 2,b = 3,c = 0; sum(a,b,c); printf("sum c=%dn",c); sum_primer(a,b,&c); printf("sum_primer c=%dn",c); printf("sum_return d=%d",sum_return(a,b)); }
运行结果:
可以看到使用sum()函数计算时c并不能返回a与b的和,而sum_primer()中c就可以a和b的和,这里要注意值传递不会影响到原来的值,而通过指针进行地址传递后就可以改变c所在的地址中的值,如此就可以实现和值返回(正常情况下大部分求多个值的函数都会通过地址传递来保存值)。而sum_return就是常规的通过return返回值。
例4:求n!(递归函数)
#includeint fun(int n) { if(n==1||n==0) return 1;//如果参数是0或者1返回1 return n*fun(n-1);//否则返回n和下次递归的积 } int main() { int n; printf("请输入n:") ; scanf("%d",&n); printf("%dn",fun(n)); return 0; }
运行结果:
在使用递归函数时,一定要注意递归结束的条件,如果不进行限制那就相当于一个无限嵌套的函数
以上就是对函数内容的部分简述,希望对大家有一些小小的帮助
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)