函数的分类
库函数
库函数有这么几大类
- IO 函数
- 字符串操作函数
- 内存操作函数
- 时间/日期函数
- 数学函数
- 其他库函数
有这么多的库函数 ,我们应该如何去学习 这里我推荐几个学习库函数的网站 https://legacy.cplusplus.com/reference/cstring/strerror/?kw=strerror
https://en.cppreference.com/w/
https://zh.cppreference.com/w/首页
自定义函数
ret_type fun_name(para1, * )
{
statement;
}
ret_type 是函数返回类型 fun_name是函数名 括号里面的是函数参数
statement 是函数的语句项
函数的调用
- 传值调用
- 传址调用
void Swap(int x, int y)
{
int tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前 :a =%d b =%d\n", a, b);
Swap(a, b);
printf("交换后 :a =%d b =%d\n", a, b);
return 0;
}
这里你会发现 a 和x b和y的地址不同 x y 确实交换了但是根本不影响a和b 。当函数调用时,实参传递给形参,形参是实参的一份临时拷贝,对形参的修改不影响实参。
void Swap(int* pa, int* pb)
{
int tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
printf("交换前 :a =%d b =%d\n", a, b);
Swap(&a, &b);
printf("交换后 :a =%d b =%d\n", a, b);
return 0;
}
改成传址调用就可以实现了
函数的参数
函数参数分为两种 形参和实参 实参可以是常量 变量 表达式 函数等
形参是函数名后括号里面的变量
函数的嵌套调用
函数与函数之间可以互相调用,函数可以嵌套调用但是不可以嵌套定义
错误示范(嵌套定义)
int main()
{
int Add(int x, int y)
{
return x + y;
}
return 0;
}
正确的函数嵌套调用如下
int test(void)
{
printf("hehe\n");
}
int main()
{
int ret = test();
printf("%d", ret);
return 0;
}
函数的链式访问
把一个函数的返回值作为另一个函数的参数
#include <stdio.h>
int main()
{
printf("%d", printf("%d", printf("%d", 43) ) );
return 0;
}
printf函数的返回值是打印在屏幕上字符的个数
此处首先打印43,两个个数,返回2;则倒数第二个打印2,一个数字,返回1;第一个打印1
函数的声名和定义
#include "add.h"
#include <stdio.h>
int main()
{
int a = 0;
int b = 0;
scanf("%d %d", &a, &b);
int ret = Add(a, b);
printf("%d", ret);
return 0;
}
函数要满足先声明后使用 ,但是在工程中我们把函数定义放在源文件test.c函数声名放在头文件add.h
函数的递归
递归有两个必要条件
- 存在限制条件,当满足这个限制条件时,递归不在继续
- 每次递归调用之后会越来越接近限制条件
举个例子
#include <stdio.h>
void Print(unsigned int n)
{
if (n > 9)
{
Print(n/10);
}
printf("%d ", n % 10);
}
int main()
{
unsigned int num = 0;
scanf("%u", &num);
Print(num);
return 0;
}
斐波那契
方法一 :递归
#include<stdio.h>
int Fib(int n)
{
if (n == 1 || n == 2)
{
return 1;
}
else
return Fib(n - 2) + Fib(n - 1);
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fib(n);
printf("%d", ret);
return 0;
}
假设n=5 具体运算过程如下
代码二:
#include<stdio.h>
int Fib(int n)
{
int a = 1;
int b = 1;
int c = 1;
c = a + b;
while (n > 2)
{
c = a + b;
a = b;
b = c;
n--;
}
return c;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret =Fib(n);
printf("%d", ret);
return 0;
}
这里需要注意一个点:在调试 Fib函数的时候,如果你的参数比较大,那就会报错: stack overflow(栈溢出)
这样的信息。
系统分配给程序的栈空间是有限的,但是如果出现了死循环,或者(死递归),这样有可能导致一
直开辟栈空间,最终产生栈空间耗尽的情况,这样的现象我们称为栈溢出
n 的阶乘
代码一:
#include<stdio.h>
int Fac(int n)
{
if (n <= 2)
{
return n;
}
else
return n * Fac(n - 1);
}
int main()
{
int n = 0;
scanf("%d",&n);
int ret = Fac(n);
printf("%d", ret);
return 0;
}
我们假设n=3 , F(3 )= 3 * F(2) 我们可以用数学归纳法推出 当n大于2时, n的阶乘的公式 n* Fac(n-1)
代码二:
#include<stdio.h>
int Fac(int n)
{
if (n <= 2)
{
return n;
}
int i = 1;
int ret = 1;
for (i = 1; i <= n; i++)
{
ret *= i;
}
return ret;
}
int main()
{
int n = 0;
scanf("%d", &n);
int ret = Fac(n);
printf("%d",ret);
return 0;
}
递归函数DigitSum(n)
要求:输入一个非负整数,返回组成它的数字之和
例如,调用DigitSum(1729),则应该返回1+7+2+9,它的和是19
输入:1729,输出:19
int DigitSum(int n)
{
if (n > 9)
{
return DigitSum (n / 10) + n % 10;
}
else
return n;
}
int main()
{
int n = 0;
scanf("%d", &n);
int sum = DigitSum(n);
printf("%d", sum);
return 0;
}
我们假设n是1234 123是n/10得到的,4是n%10得到的 依次类推。
strlen的实现
- 递归
int my_strlen(char* str)
{
if (*str != '\0')
{
return 1 + my_strlen(str + 1);
}
else
return 0;
}
int main()
{
char arr[] = "bit";
int len = my_strlen(arr);
printf("%d", len);
return 0;
}
- 非递归
int my_strlen(char * str)
{
int count = 0;
while (*str != '\0')
{
str++;
count++;
}
return count;
}
int main()
{
char arr[] = "bit";
int len = my_strlen(arr);
printf("%d", len);
return 0;
}
打印一个整数的每一位
void Print(int num)
{
if (num > 9)
{
Print(num / 10);
}
printf("%d ", num % 10);
}
int main()
{
int num = 0;
scanf("%d", &num);
Print(num);
return 0;
}
如果你觉得这篇文章对你有帮助,不妨动动手指给点赞收藏加转发,给鄃鳕一个大大的关注
你们的每一次支持都将转化为我前进的动力!!!