函数的使用

库函数

🔔 IO函数 input/output printf/scanf getchar/putchar …
🔔 字符串操作函数 strlen strcmp…
🔔 字符操作函数
🔔 内存操作函数 memcpy memset memmove
🔔 时间/日期函数 time
🔔 数学函数 sqrt

😰我们想把整型数组的前五个数用memset设置为1,这是没法实现的

    int arr[10] = { 0 };
	memset(arr, 1, 5*sizeof(int));//设置内存块,以字节为单位进行扩充

memset把每个字节设置为1,一个整型是4个字节,转换为十六进制就很容易看到,前20个字节都变成了1
在这里插入图片描述

自定义函数

🏸 函数的组成:

ret_type fun_name(para1, * )
{
   statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para1   函数参数

函数返回的表达式的值要和返回类型一致,返回类型要和接收这个函数的类型一致,如果不一致强制类型转换

⛹ 写一个交换函数
一般会先想到这么写

void Swap(int x, int y)
{
	int ret =x;
	x = y;
	y = ret;
}

但这是错误的,两个数并没有交换
调试去发现问题
在这里插入图片描述
可以发现swap里的x,y地址不和a,b一样,x,y交换,并不会改变a,b,空间上没有联系
❗️❗️❗️ 形参是实参的一份拷贝,形参的改变不会影响实参

我们可以通过解引用和取地址操作来解决


void Swap(int* pa,int* pb)
{
	int ret = *pa;
	*pa = *pb;
	*pb = ret;

}

不调用函数,函数不会分配空间

printf 函数返回的是打印在屏幕上的字符的个数
如果发生错误,返回负数

	printf("%d", printf("%d", printf("%d", 43)));
	//打印4321

🥉函数必须先声明后定义,要想main函数后面定义函数,必须在main函数前声明

函数递归

函数调用自身的编程技巧叫做递归
通常把一个大问题层层转换为与原问题相似的规模较小的问题

递归的两个必要条件:1.存在限制条件,满足限制条件后,递归不再继续。 2.每次递归调用之后越来越接近这个条件
给定一个数,打印它的每一位,比如:输入1234,打印1 2 3 4 ![在这里插入图片描述](https://img-blog.csdnimg.cn/0d41c9d380994aad8bc81b0778e32ec5.png#pic_center)
void Print(int x)
{
	if (x > 9)//限制条件
	{
		Print(x / 10);//接近这个条件
	}
	printf("%d ", x % 10);
}

int main()
{
	int num = 1234;
	Print(num);
	return 0;
}

如果一个递归无限的走下去,它会出现栈溢出

每一次函数的调用都要在内存中开辟空间

在这里插入图片描述

🥇编写一个函数,不允许创建临时变量,求出字符串长度
首先我们会写出下面这样的代码,创建了count临时变量

int my_strlen(char* ps)
{
	int count = 0;
	while (*ps != '\0')
	{
		count++;
		ps++;
	}
	return count;
}

int main()
{
	char arr[10] = "abcdef";
	//arr是首元素地址,类型是char*
	int len = my_strlen(arr);
	printf("%d", len);
	return 0;
}

<font color=red size=3用递归解决
在这里插入图片描述

int my_strlen(char* ps)
{
	if (*ps != '\0')
	{
		return my_strlen(ps + 1)+1;//b的地址就是ps+1
		//不能使用ps++,因为是后置++,先使用后++,作为参数没有意义了
	}
	return 0;//第一个字符是'\0'就不用算了,直接为0
}

指针变量+1:指针+1就是指向下一个元素的地址,指针类型不同,跳过的字节数量也就不同

//字符指针+1 -> 向后跳一个字节
//char* p; p+1 -> 向后跳一个字节
//整型指针+1 -> 向后跳四个字节
//int* p; p+1 ->向后跳四个字节
斐波那契数列
1 1 2 3 5 8 13 21 34 55 ......

当数字个数n>2时,前两个数字的和等于第三个数字
当数字个数n<=2时,前两个数字都为1

通过递归来实现

int fib(int n)
{
	if (n <= 2)
	{
		return 1;
	}
	else
	{
		return fib(n - 1) + fib(n - 2);
	}
}

但是当我们想求第40个斐波那契数时,第三个斐波那契数被重复计算了三千多万遍,效率太低了 ,所以不适合用递归
在这里插入图片描述
建议用循环


int fib(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;
	while (n > 2)
		//n要控制好
		//n=3时,a+b赋给c一次,n为4,赋给c两次,以此类推
	{
		c = a + b;//前两个数之和等于第三个
		a = b;
		b = c;
		n--;
	}
	return c;
}
getchar 和 putchar

getchar 是函数,从键盘读取字符;而scanf什么类型的都可以读取
getchar 是读取字符
为什么返回类型是int??
1.getchar 返回的是字符,实质上就是返回字符的ASCII码值
2.EOF — end of file 也就是 -1
👼getchar 和 scanf 读取信息的时候,会看缓冲区里有没有数据,没有数据才会从键盘读取,scanf读取数据的时候,读到空格就不再读了

逆序字符串
把"abcdef"逆序

循环方法:

void my_reverse1(char* ps,int len)
{
	char* left = ps;//指向第一个元素
	char* right = ps + len -1;//指向最后一个元素
	while (left < right)
	{
		char tmp = *left;
		*left = *right;
		*right = tmp;
		left++;
		right--;
	}
}

递归实现:

在这里插入图片描述

void my_reverse(char* str)
{
	int len = strlen(str);
	char tmp = str[0];
	str[0] = str[len - 1];
	str[len - 1] = '\0';
	if (strlen(str+1) > 2)
	{
		my_reverse(str + 1);
	}
	str[len - 1] = str[0];

}

递归实现n的k次方

int Pow(int n, int k)
{
	if (k > 0)
	{
		return n * Pow(n, k - 1);
	}
	else if (k == 0)
	{
		return 1.0;
	}
	else
	{
		return 1.0 / Pow(n, -k);
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值