先简单介绍一下C语言函数
c语言函数是用来编译c语言,所在库函数为ctype.h,分为库函数和自定义函数。
从表面上看,函数使用时必须带上括号,有必要的话还要传递参数,函数的执行结果也可以赋值给其他变量。
1.库函数与自定义函数
库函数包括 IO函数 字符串操作函数 字符操作函数 内存操作函数 时间/日期函数 数学函数 其他库函数,库是编程的一个基本概念,可以认为它是一系列函数的集合。而自定义函数则根据自己的需要进行编写,使用的时候必须加上头文件 #include "自定义函数“。
库函数用法
#include<stdio.h>
#include<string.h>
int main()
{
char arr1[] = "bit";
char arr2[20] = "************";
strcpy(arr2, arr1);
printf("%s\n",arr2);
return 0;
}
自定义函数用法
用法格式:
函数类型 函数名(函数参数)
{
函数体;
}
示例如下
int get_max(int x,int y)
{
if (x > y)
return x;
else
return y;
}
int main()
{
int a = 10;
int b = 20;
int max=get_max(a,b);
printf("max=%d\n", max);
return 0;
}
下面举一个自定义函数调用的示范题
//通过函数的调用实现两个数的交换
#include<stdio.h>
void swap(int* pa, int* pb)
{
int tmp = 0;
tmp = *pa;
*pa = *pb;
*pb = tmp;
}
int main()
{
int a = 10;
int b = 20;
printf("a=%d b=%d\n", a, b);
swap(&a, &b);
printf("a=%d b=%d\n", a, b);
return 0;
2.形参与实参
实参:是真实传递给函数的参数,常量、变量、表达式、函数等。无论实参是哪种类型的量,在进行函数调用时,都必须有确定的值,以便把这些值传给形参。
形参:是指函数名后括号内的变量,因为形参只有在函数调用的过程中才实例化(分配内存单元),所以叫形式参数,形参调用完就自动销毁了。
形参实例化之后相当于实参的一份临时拷贝。
下面举些例子包括函数的调用及形参实参的使用
1.判断100-200中的素数有哪些(素数是只有1和它本身的约数)
#include<stdio.h>
int is_prime(int n)
{
int j = 0;
for (j = 2; j < n; j++)
{
if (n % j == 0)
return 0;
}
return 1;
}
int main()
{
int i = 0;
for (i = 100; i <= 200; i++)
{
if (is_prime(i) == 1)
printf("%d ",i);
}
return 0;
}
2.判断1000-2000之间的闰年有哪些
#include<stdio.h>
int is_leap_year(int n)
{
//判断闰年(能被4整除并且不能被100整除的的闰年;能被400整除的是闰年)
if (n % 4 == 0 && n % 100 != 0 || (n % 400 == 0))
return 1;
else
return 0;
}
int main()
{
int year = 0;
for (year = 1000; year <= 2000; year++)
{
if (is_leap_year(year) == 1)
printf("%d ", year);
}
return 0;
}
3.函数的调用实现二分查找
#include<stdio.h>
int binary_search(int arr[], int k,int sz)
{
int left = 0;
int right = sz - 1;
while (left<=right)
{
int mid = (left + right) / 2;
if (arr[mid] < k)
{
left = mid + 1;
}
else if (arr[mid] > k)
{
right = mid - 1;
}
else
{
return mid;
}
}
return -1;
}
int main()
{
int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
int k = 7;
int sz = sizeof(arr) / sizeof(arr[0]);
//传递过去的是数组arr首元素的地址 4bit/4bit=0
int ret = binary_search(arr, k, sz);
if (ret == -1)
{
printf("找不到指定的数字\n");
}
else
{
printf("找到了,下标是: %d\n", ret);
}
return 0;
}
3.函数的嵌套调用和链式访问
函数与函数之间是可以有机组合的,链式访问是把一个函数的返回值作为另一个函数的参数,示例如下
#include<stdio.h>
void new_line()
{
printf("hehe\n");
}
void three_line()
{
int i = 0;
for (i = 0; i < 3; i++)
{
new_line();
}
}
int main()
{
three_line();
return 0;
}
int main()
{
int len = 0;
//1
len = strlen("abc");
printf("%d\n", len);
//2
printf("%d\n", strlen("abc"));
}
4.函数的声明和定义
源文件(定义)+头文件(声明) 把函数声明放在头文件,源文件引用函数,添加自定义头文件 #Include"Add"即可
int Add(int, int);//函数声明
int main()
{
int a = 10;
int b = 20;
int sum = 0;
//函数调用
sum = Add(a, b);
printf("%d\n", sum);
return 0;
}
#include"Add"
int Add(int x, int y)//函数定义
{
int z = x + y;
return z;
}
5.函数的递归
递归:程序调用自身的编程技巧为递归,它通常是把一个大型的复杂问题转化为规模较小的问题来解决,可以减少代码的使用量,递归的能力在于用有限的语句来定义对象的无限集合。
使用递归有两个必要条件:
1)存在限制条件,满足限制条件时,便不再继续 ;
2)每次递归调用之后越来越接近这个限制条件。
例如:输入一个数,按位输出
输入123;
输出1 2 3;
#include<stdio.h>
void print(int n)
{
if (n > 9)
{
print(n / 10);
}
printf("%d ", n%10);
}
int main()
{
unsigned int num = 0;
scanf("%d", &num);
print(num);
return 0;
}
2 .不定义数组,实现对字符串的字符数统计
输入 “world”;(\0)
输出 6
#include<stdio.h>
int my_strlen(char* str)
{
if (*str != '\0')
return 1 + my_strlen(str + 1);
else
return 0;
}
int main()
{
char arr[] = "world";
//int len = strlen(arr);//求字符串长度
//printf("%d\n", len);
//模拟实现了一个strlen函数
int len = my_strlen(arr);//arr是数组,数组传参,传过去的不是整个数组,而是首元素的地址
printf("len=%d\n", len);
return 0;
}
3.利用递归实现n的阶乘
#include<stdio.h>
int Fac(int n)
{
if (n <= 1)
return 1;
else
return n * Fac(n - 1);
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fac(n);
printf("%d\n", ret);
return 0;
}
4.利用递归实现斐波那契数列
#include<stdio.h>
int Fib(int n)
{
if (n <= 2)
return 1;
else
return Fib(n - 1) + Fib(n - 2);
}
int main()
{
int n = 0;
int ret = 0;
scanf("%d", &n);
ret = Fib(n);
printf("ret=%d\n", ret);
return 0;
}
5.利用递归实现汉诺塔问题
#include<stdio.h>
int hanio(int num)
{
if (num == 1)
{
return 1;
}
else
{
return 2 * hanio(num - 1) + 1;
}
}
int main()
{
int num = 0;
scanf("%d", &num);
int ret = hanio(num);
printf("完成%d层的汉诺塔需要移动%d步\n",num,ret);
return 0;
}
6. 利用递归实现青蛙跳跃问题(剑指Offer经典例题)
#include<stdio.h>
int flag(int num)
{
if (num == 1)
return 1;
if (num == 2)
return 2;
else
return flag(num - 1) + flag(num - 2);
}
int main()
{
int num = 0;
int ret = 0;
scanf("%d", &num);
ret = flag(num);
printf("到达%d层有%d种跳跃路线\n", num, ret);
return 0;
}
6.函数的迭代
迭代:利用变量的原值推算出变量的一个新值。
如果递归是自己调用自己的话,迭代就是A不停调用B
大家能使用迭代法就用迭代法,递归法容易造成堆栈的溢出
#include<stdio.h> //函数调用一次,num自增1
void Add(int* p)
{
(*p)++;
}
int main()
{
int num = 0;
Add(&num);
printf("num=%d\n", num);
Add(&num);
printf("num=%d\n", num);
Add(&num);
printf("num=%d\n", num);
return 0;
}
因此,适当的使用迭代和递归思想可以更好的解决相对复杂的问题,减小代码量。