网站空间大小 论坛,wordpress 删除重复,国外服装设计网站,查询网站后台登陆地址目录
何为函数
库函数
自定义函数
二分查找数组下标
链式访问 函数的声明
函数定义
递归
正向打印数字
打印字符个数
使用临时变量
递归(不使用临时变量)
n的阶乘
一般形式
递归
斐波那契数
递归
正常做法 何为函数 在计算机科学中#xff0c;子程序是一个…目录
何为函数
库函数
自定义函数
二分查找数组下标
链式访问 函数的声明
函数定义
递归
正向打印数字
打印字符个数
使用临时变量
递归(不使用临时变量)
n的阶乘
一般形式
递归
斐波那契数
递归
正常做法 何为函数 在计算机科学中子程序是一个大型程序中的某部分代码 由一个或多个语句块组 成。它负责完成某项特定任务而且相较于其他代 码具备相对的独立性。 一般会有输入参数并有返回值提供对过程的封装和细节的隐藏。这些代码通常被集成为软 件库。 函数分为库函数和自定义函数
库函数 库函数只提供函数名参数功能返回类型实现则由编译器厂商实现。库函数的使用需要包含对应的头文件。c/c库函数官网:https://cplusplus.com/ 自定义函数 实际很多情况我们不能靠库函数解决所以就诞生了自定义函数我们可以自己实现内部细节和功能。 现在实现一个交换函数
void Swap(int x, int y)
{int z 0;z x;x y;y z;
}
运行结果 为什么没有实现交换功能呢 我们可以看到它们的地址都不一样所以没能实现交换我们称传递的参数为实参接收的参数为形参形参是实参的拷贝形参的建立与销毁只在调用函数的过程发生。所以它的交换只在函数体内。 void Swap(int* x, int* y)
{int z 0;z *x;*x *y;*y z;
}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;
}
我们传递地址这样就可以实现交换功能了。
二分查找数组下标 我们利用一组数据有序的特点这次我们试着用函数的方式封装二分查找这一功能。 找7发现找不到这是为什么呢我们来看函数部分 通过调试发现这里的right始终为0这就是问题所在了在c语言中数组的传参是传递的指针而非整个数组这是因为可以通过首元素地址找到整个下组从而减少了不必要的开销。 完整代码 int binary_search(int *arr, int k,int right)
{int left 0;while (left right){int mid (left right) / 2;if (arr[mid] k){right mid - 1;}else if (arr[mid] k){left mid 1;}else{return mid;//找到了}}return -1;//找不到
}
int main()
{int arr[10] { 1,2,3,4,5,6,7,8,9,10 };int sz sizeof(arr) / sizeof(arr[0]);int k 7;int right sizeof(arr) / sizeof(arr[0]);int ret binary_search(arr, k,sz);if (-1 ret)printf(找不到\n);elseprintf(找到了下标是:%d\n, ret);
}
函数允许嵌套调用不允许嵌套定义。
链式访问 链式访问就是一个函数的返回值作为另一个函数的参数像链条一样串起来。 比如printf函数的返回值是字符的个数: 函数的声明 函数的声明一般是包含在.h文件里用于综合性的工程里。 //函数定义
int Add(int x, int y);
int Add(int, int);
如果我们创建一个add.h的头文件里面写上函数的声明我们可以这样包含达到使用我们自己的“库”的效果。
#include add.h
当然,如果你不小心将函数的定义放在了main函数后你也可以这样使用
int main()
{int Add(int, int);Add(a,b);return 0;
}
int Add(int a, int b)
{//..
}
函数定义 同理我们可以把函数的定义放在.c文件里。 同时要想不让人知道函数的具体实现过程我们可以通过打包静态库的方式隐藏自己的函数文件。
递归 顾名思义递归的核心是大事化小通过一次一次迭代达到最终效果的过程。 正向打印数字
我们知道反向打印4个数可以:
1234%10 4;
1234/10 123;
123%10 3;
那正向怎么做呢在知道我们可以轻松拿到它的末尾数字时我们是不是可以反向思考一下
123 (4)
12 (34)
1 (234)
void Print(unsigned int n)//1
{if (n 9){print(n / 10);}printf(%d , n % 10);
}
void Print(unsigned int x)//2
{if (x 10){printf(%d , x);}else{Print(x / 10);printf(%d , x % 10);}
} 调用了4次函数开辟了4次函数栈帧在打印后返回上一层栈帧并销毁空间。 递归必须有限制条件每次递归会逐渐靠近这个限制条件 打印字符个数
使用临时变量
int my_strlen(char* s)
{int count 0;while (*s ! \0){count;s;}return count;
}
递归(不使用临时变量) 同理例如一个字符串abc拆分成1bc,11c,1110的形式。 int my_strlen(char* str)
{if (*str ! \0)return 1 my_strlen(str 1);elsereturn 0;
}
注意这里最好不要用前置它改变了数组的地址。
n的阶乘 阶乘公式 : n1,1n1,Fac(n-1) * n 一般形式
int Fac(int n)
{int i 0, ret 1;for (i 1;i n; i){ret ret * i;}return ret;
}
递归
int Fac(int n)
{if (n 1){return 1;}elsereturn Fac(n - 1) * n;
}
斐波那契数 1 1 2 3 5 8 13 .... 像这样前两个数加起来等于后一个数的数列叫做斐波那契数列。 递归 公式: n2, n 1 n2, Fib(n-1) Fib(n-2) int Fib(int n)
{if (n 2)return 1;elsereturn Fib(n - 1) Fib(n - 2);
}
测试 测试发现计算一个稍微大点的数据半天计算不出来结果可以得知递归的层次已经很深了就像一张很深的数 一样。 正常做法 在数字超出两个时我们可以用两个变量求和计算第三个变量依次更新达到想要的效果。 int Fib(int n)
{int a 1;int b 1;int c 0;if (n 2){return 1;}if (n 2){while(n2){c a b;a b;b c;n--;}return c;}
}
用这种方法几乎是一瞬间得出了结果不过注意数据太大可能会超出范围。
总之递归的使用需要我们多去总结和感悟并选择最合适的方法 。