笔记整理6: 函数
一个稍复杂的C程序通常由一个主函数和多个子函数构成。main()函数是程序的起始点,而子函数只有被调用的时候才会被采用,二者也因此形成了一个主调函数和被调函数的关系。子函数可以调用其它的子函数,也可以调用其自身。(老师说,辨别其是新手还是老手的第一点即是其程序是否用到了子函数。)
库函数
库函数是C系统定义好的函数,放在标准函数库中,可以供用户直接使用。
常用型:
输入输出函数 #include <stdio.h>
其包含printf,scanf,putchar,getchar等
数学函数 #include <math.h>
其包含sqrt,pow等
字符和字符串处理函数 #include <string.h>
其包含strlen,strcat等
动态储存分配函数 #include <stdlib.h>
其包含malloc,calloc等
具体内容和用法,需要大家去问问度娘了啦
用户自定义函数
定义格式
类型名 函数名 (形参列表)
{
定义变量
语句序列
}
1,类型名
(1)类型名决定了返回值的类型,且是最终决定,无论return后是何类型,都会强制转换成你定义的类型名。
(2)若不定义类型名,则系统自动认为是int型。
2,函数名(自由发挥啦)
3,形参列表
(1)从有无形参,我们分为有参函数和无参函数。无参函数,即只执行,并不会有返回值,可以看出其是机械性的执行某个函数体。而有参函数则比较灵活了,可以因形参的不同而使函数体产生一些改变。
无参函数:
struct student *creat() //这里的creat就是一个无参函数
{
xiao *head,*q1,*q2;
q1=q2=(xiao*)malloc(LEN);
scanf("%d",&q1->num);
scanf("%f",&q1->score);
head=NULL;
n=0;
while(q1->num)
{
n++;
if(1==n)
head=q1;
else
q2->next=q1;
q2=q1;
q1=(xiao*)malloc(LEN);
scanf("%d",&q1->num);
scanf("%f",&q1->score);
}
putchar('\n');
q2->next=NULL;
return head;
}
有参函数:
void print(struct student *head) //这里的print就是一个有参函数
{
struct student *p;
p=head;
while(p)
{
printf("%d\t%f\n",p->num,p->score);
p=p->next;
}
}
使用函数
1,调用函数
『函数名(实参列表)』
调用函数很简单,我们需要输入自己定义的函数名,再加上与自己定义的形参位数符合的实参列表就可以了。
2,声明函数
一般而言我们的子函数要放在main函数的前面,在main函数里调用子函数时,才能有效。但常规的排版方式main函数是要放在前面的,这样只,在调用函数时,编译器会因找不到子函数而报错。所以我们需在main函数前声明一下被调用的函数。
那如何声明函数呢?其实很简单,我们只需要将我们的子函数的头版加一个;再放在main函数前即可
例:
#include <stdio.h>
#include <stdlib.h>
#define LEN sizeof(struct student)
#define NULL 0
struct student *creat();
struct student *del(struct student *head,int num);
struct student *insert(struct student *head,struct student *one);
void print(struct student *head); //以上四行都是声明函数喔
main()
{
}
函数的参数传递
-
传值方式 这个非常重要,认真看
1,实参和形参占有不同的储存单元。所以在被调函数中若改变了形参的值,并不会影响实参的值。实参与形参允许同名,不会混淆。
(这个无论在函数体内,还是在指针与函数结合的题中,都着实让人头疼)
2,实参传递给形参的值是单向的。子函数传值可用return。
3,实参与形参的类型要相同,并且数目要匹配。
4,实参的求值顺序是自右到左。 -
传地址方式
1,实参传递给形参的变量是一个地址(指针)。则子函数可以地址指向的方式修改地址内的值。
(如果是一个数组,则我们可以发现传递地址可以改变多个值,而return只能传递一个值,该函数就结束了。)
2,具体内容后面指针会详解。