函数的概念
我们用百度百科搜出来数学中的函数概念
其实在C语言中我们也要引入函数的概念
C语言中函数可以翻译为子程序,C语言中的函数就是一个为了完成某项特定的任务的一小段代码。这段代码是有特殊的写法和调用方法的。
C语言的程序其实是由无数个小的函数组合而成的,也可以将一个大的计算任务可以分解成若干个较小的函数(对应较小的任务)完成。同时一个函数如果能完成某项特定任务的话,这个函数也是可以复用的,也叫复用函数,提升了开发软件的效率。
C语言中我们可以把函数分为:
库函数
自定义函数
我们先来讨论库函数
库函数
标准库和头文件
头文件中有函数的申明,库文件实现函数的定义。对于头文件和库的区别我们可以这样理解:就是头文件提供的是一个函数的声明,并没有这个函数具体代码,而库就是存放这个函数的具体实现代码。
C语⾔标准中规定了C语⾔的各种语法规则,C语⾔并不提供库函数;C语⾔的国际标准ANSI C规定了⼀ 些常⽤的函数的标准,被称为标准库,那不同的编译器⼚商根据ANSI提供的C语⾔标准就给出了⼀系列 函数的实现。这些函数就被称为库函数。
我们前⾯内容中学到的 printf 、 scanf 都是库函数,库函数的也是函数,不过这些函数已经是现 成的,我们只要学会就能直接使⽤了。有了库函数,⼀些常⻅的功能就不需要程序员⾃⼰实现了,⼀ 定程度提升了效率;同时库函数的质量和执⾏效率上都更有保证。各种编译器的标准库中提供了⼀系列的库函数,这些库函数根据功能的划分,都在不同的头⽂件中进 ⾏了声明。
总结:
// 1 c语言规定了语法规则
// 2 c语言本身不提供库函数
// 3 但是c语言规定了,一些库函数的各种信息
// scanf-名字,参数,返回类型,函数的功能
// priintf-
// strlen-
//让 C语言编译器的厂商根据规定实现这些函数
// 函数的实现细节可能有差异
// 但是程序员使用的时候,基本无感
库函数的使用方法
我们用一个简单的sqrt来举例
我们可以在写代码之前看这个文档中包含:
//库函数文档的一般格式
//1.函数原型
//2.函数功能介绍
//3.参数和返回类型说明
//4.代码举例
//5.代码输出
//6.相关知识链接
#include <stdio.h>
#include <math.h>
int main()
{
double a = 16.0;
double r = sqrt(16.0);
printf("%lf", r);
return 0;
}
结果为:
自定义函数
ret_type fun_name(形式参数)
{
}
ret_type 是函数返回类型
fun_name 是函数名
括号中放的是形式参数
{}括起来的是函数体
//自定义函数名是自定义的,根据实际情况起名字
//参数的个数也是根据实际情况而定,可以有0个参数,也可以有多个参数
//函数的返回值 函数可以返回值,也可以不返回值,要根据实际情况而定,函数不返回值时,返回类型写成void
现学现用:我们用自定义来写一个两个数的加法
#include <stdio.h>
//int Add(int x, int y)
//{
// int z;
// z = x + y;
// return z;
//}
//上述的代码可以简写为
int Add(int x, int y)//
{ //函数的定义
return x + y; //
} //
int main()
{
int a, b;
scanf("%d %d", &a, &b);
int c=Add(a, b);//函数调用
printf("%d", c);
return 0;
}
形参和实参
此时我们还用这个代码来研究:
int Add(int x, int y)//
{ //函数的定义
return x + y; //
} //int main()
{
int a, b;
scanf("%d %d", &a, &b);
int c=Add(a, b);//函数调用
printf("%d", c);
return 0;
}
将代码调试起来,走你。
我们在调试的可以观察到,x和y确实得到了a和b的值,但是x和y的地址和a和b的地址是不⼀样的,所 以我们可以理解为形参是实参的⼀份临时拷⻉。
同理,我们还可以定义一个打印1~n的函数来继续研究实参和形参以及他们的关系,这个交给各位来研究。
void Print(int n)
{
if (n < 1)
return;
int i = 0;
for (i = 1; i <= n; i++)
{
printf("%d ", i);
}
}
int main()
{
int m = 0;
scanf("%d", &m);
Print(m);
return 0;
}
小细节
//int test()
//{
// return 3.5;
//}
//
//int main()
//{
// int ret = test();
// printf("%d\n", ret);
// return 0;
//}
如果上述代码int test()不加int,那么他结果还是3,因为默认是函数返回类型int类型
return 语句
函数的返回类型和返回参数
加入有小伙伴想打印一个菜单,我们可以这样搞
void menu(void)
{
printf("**************\n");
printf("*****1.play***\n");
printf("*****0.exit***\n");
}
int main()
{
menu();
return 0;
}
接下来我们看一个问题代码:
void test()
{
printf("hehe\n");
}
int main()
{
test();
test(1);
test(100);
test(100, 200);
return 0;
}
//上述方式有些不合理,函数不需要传参,但传参数了,因此需要改为test(void)
这个上述是不是我们提到过啊,要记住ok吗?
数组做函数参数
#include <stdio.h>
void set_arr(int arr2[],int sz2)
{
int i = 0;
for (i = 0; i < sz2; i++)
{
arr2[i] = -1;
}
}
void print_arr(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
int main()
{
int arr1[] = {1,2,3,4,5,6,7,8,9,10};
int sz1 = sizeof(arr1) / sizeof(arr1[0]);
print_arr(arr1, sz1);//打印数组的所有内容
set_arr(arr1,sz1);//将数组的元素全部设置为-1
print_arr(arr1,sz1);//打印数组的所有内容
return 0;
}
//此时数组名字叫arr,上次博客我们学到了,此时int []就是数组的类型
//要设置数组的所有内容,要遍历数组
//此时开启调试,监视arr1 arr2
//观察到arr1和2的地址一样
小拓展:
//为什么说:C语言中scanf和printf函数的参数个数是不固定的
//知识点:可变参数
//printf("hehe");
//printf("%d %f",100,3.5);
//printf("%s %d %f","abc",10,5.5);//int n=0;
//int m=0;
//scanf("%d",&n);
//scanf("%d %d",&n,&m);
嵌套调用和链式访问
#include <stdio.h>
int is_leap_year(int y)
{
if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0))
return 1;
else
return 0;
}
int get_days_of_month(int y, int m)
{
//31 28 31 30 31 30 31 31 30 31 30 31
// 29
int days[] = {0,31,28,31,30,31,30,31,31,30,31,30,31 };
// 1 2 3 12
int day = days[m];
//闰年的2月是需要特殊调整 -29天
if (is_leap_year(y) && m == 2)
{
day++;
}
return day;
}
int main()
{
int year = 0;
int month = 0;
scanf("%d %d", &year, &month);
int day=get_days_of_month(year, month);
printf("%d\n", day);
return 0;
}
刚才博主那个函数忘了写return day;调试到最后才发现哈哈,各位以后一定要仔细啊
int main()
{
size_t len=strlen("abcdef");
printf("%zd\n", len);
//上述的两行可以合并
printf("%zd\n", strlen("abcdef"));//此时就是链式访问
return 0;
}
我们接下来看一个有意思的:
int main()
{
printf("%d", printf("%d", printf("%d", 43)));
//43 2 1
//printf("%d", printf("%d ", printf("%d ", 43)));
43 3 2
return 0;
}
从Cplusplus网站上可以看到printf的返回值
int main()
{
/*printf("%d", printf("%d", printf("%d", 43)));*/
//43 2 1
printf("%d", printf("%d ", printf("%d ", 43)));
43 3 2
return 0;
}
此时结果为多少呢,为4332为什么呢,有空格哈
//函数的声明和定义
int is_leap_year(int y)
{
if ((y & 4 == 0 && y % 100 != 0) || (y % 400 == 0))
{
return 1;
}
else
return 0;
}
int main()
{
int year = 0;
scanf("%d", &year);
int ret = is_leap_year(year);
if (ret == 1)
printf("闰年\n");
else
printf("不是闰年\n");
}
我们一般都把函数定义写到主函数上。
其他的一些知识:
数组就到这里,下次见,有建议发评论区。