初级C语言 函数

函数
用于解决特定问题的代码

分类

  1. 库函数
  2. 自定义函数

库函数
为提高程序效率,减少繁琐重复的代码

自定义函数

返回类型 函数名(形参)
{
语句项;
}

函数的声明和定义

声明:交代函数的名称,形参,返回类型。

定义:交代函数的功能。

用函数比较两个数的大小

#include<stdio.h>
int Max(int x, int y)
{
	if (x > y)
		return x;
	else
		return y;
}
int main()
{
	int a = 10;
	int b = 20;
	int max = Max(a, b);
	printf("max=%d\n", max);
	return 0;
}

函数的两种调用方式

  1. 传值调用常用于不改变实参
  2. 传址调用常用于改变实参

传值VS传址

利用函数交换两个数植

传值调用
当实参传递给形参时,形参相当于实参的一份临时拷贝
对形参的修改不影响实参

#include<stdio.h>
void Swap(int x, int y)
{
	int i = x;
	x = y;
	y = i;
}
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;
}

在这里插入图片描述
传址调用

#include<stdio.h>
void Swap(int*pa, int*pb)
{
	int i = *pa;
	*pa = *pb;
	*pb = i;
}
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;
}

在这里插入图片描述
总结:
函数的参数:实参,形参。
实参:真实传给函数的参数;形参:自定义函数名括号内的变量,形式上的参数。
传值:对形参的修改不影响实参。
传址:将变量的地址传给函数,能够建立函数与外部变量真正的联系。

在有序数组中查找某一数字

#include<stdio.h>
int Search(int arr[], int k)
{
	int left = 0;
	int sz = sizeof(arr) / sizeof(arr[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 ret = Search(arr, k);
	if (ret == -1)
	{
		printf("没找到");
	}
	else
	{
		printf("找到啦,下标为%d", ret);
	}
	return 0;
}

易错点:数组arr是以首元素地址的形式被传递过去的,是以指针的形式被接收的。所以Int sz 的值并不是数组元素的个数。
在这里插入图片描述

#include<stdio.h>
int 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]);
	int ret = Search(arr, k, sz);
	if (ret == -1)
	{
		printf("没找到");
	}
	else
	{
		printf("找到啦,下标为%d", ret);
	}
	return 0;
}

在这里插入图片描述
函数的嵌套调用和链式访问

嵌套调用
函数之间互相调用
函数可以嵌套调用,但是不能嵌套定义

链式访问
把一个函数的返回值作为另一个函数的参数

#include<stdio.h>
int main()
{
	printf("%d", printf("%d", printf("%d", 43)));
	//printf函数的返回值
	//打印的字符个数,作为函数的返回值
	//printf("%d", printf("%d", 2));
	//printf("%d", 1);
	// 43  2   1
	return 0;
}

在这里插入图片描述

函数递归
简称:函数调用自身。主要思想,把大事化小
两个条件
1,存在限制条件。
2,每次递归之后,越来越接近限制条件。

题目:接受一个整型无符号数,按顺序打印每一位。
使用递归

分析
第一步 Print(678)
第二步 Print(67) 8
第三步 Print(6) 7 8

#include<stdio.h>
void Print(int n)
{
	if (n > 9)
	{
		Print(n / 10);
	}
	printf("%d ", n % 10);
}
int main()
{
	unsigned int i = 0;
	scanf("%d", &i);
	Print(i);
	return 0;
}

在这里插入图片描述
计算一个数的每位之和

分析
Digitsum(123)
Digitsum(12)+3
Digit(1)+2+3

#include<stdio.h>
int Digitsum(int i)
{
	if (i > 9)
	{
		return Digitsum(i / 10) + i % 10;
	}
	return i;
}
int main()
{
	int i = 0;
	scanf("%d", &i);
	int sum = Digitsum(i);
	printf("%d\n", sum);
	return 0;
}

在这里插入图片描述
实现n的k次方
在这里插入图片描述

#include<stdio.h>
double Pow(int n, int k)
{
	if (k > 0)
	{
		return n * Pow(n, k - 1);
	}
	else if (k == 0)
	{
		return 1;
	}
	else
	{
		return 1.0 / Pow(n, -k);
	}
}
int main()
{
	int n = 0;
	int k = 0;
	scanf("%d%d", &n, &k);
	double ret = Pow(n, k);
	printf("%lf\n", ret);
	return 0;
}

在这里插入图片描述

编写代码求字符串长度
方法一
利用库函数 strlen() #include< string >(头文件)

#include<stdio.h>
#include<string>
int main()
{
	char arr[] = "crush";
	int len = strlen(arr);
	printf("%d\n", len);
	return 0;
}

方法二
创建临时变量

#include<stdio.h>
int Count_lenght(char*arr)
{
	int count = 0;
	while (*arr != '\0')
	{
		count++;
		arr++;
	}
	return count;
}
int main()
{
	char arr[] = "crush";
	int len = Count_lenght(arr);
	printf("%d\n", len);
	return 0;
}

方法三
函数递归

#include<stdio.h>
int Count_lenght(char* arr)
{
	if (*arr != '\0')
		return 1 + Count_lenght(arr + 1);
	else
		return 0;
}
int main()
{
	char arr[] = "crush";
	int len = Count_lenght(arr);
	printf("%d\n", len);
	return 0;
}

递归与迭代(循环)

求n的阶乘
递归

#include<stdio.h>
int Fac(int i)
{
	if (i < 2)
		return 1;
	else
		return i * Fac(i - 1);

}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = Fac(n);
	printf("%d\n", ret);
	return 0;
}

在这里插入图片描述

迭代(循环)

#include<stdio.h>
int Fac(int n)
{
	int i = 0;
	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\n", ret);
	return 0;
}

在这里插入图片描述

求第n个斐波那契数

函数递归

#include<stdio.h>
int Fb(int i)
{
	if (i > 2)
		return Fb(i - 1) + Fb(i - 2);
	else
		return 1;
}
int main()
{
	int n = 0;
	int ret = 0;
	scanf("%d", &n);
	ret = Fb(n);
	printf("%d", ret);
	return 0;
}

该函数的缺点是重复多次计算,不适用于计算较大的斐波那契数。

改进如下
迭代(循环)

#include<stdio.h>
int Fb(int n)
{
	int a = 1;
	int b = 1;
	int c = 1;
	while (n > 2)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = Fb(n);
	printf("ret = %d\n", ret);
	return 0;
}

字符串逆序
迭代

#include<stdio.h>
int my_strlen(char* str)
{
	if ('\0' != *str)
	{
		return 1 + my_strlen(str + 1);
	}
	return 0;
}
void Reverse(char ch[])
{
	int left = 0;
	int right = my_strlen(ch) - 1;

	while (left < right)
	{
		char tmp = ch[left];
		ch[left] = ch[right];
		ch[right] = tmp;
		left++;
		right--;
	}
}
int main()
{
	char ch[] = "crush";
	printf("%s\n", ch);
	Reverse(ch);
	printf("%s\n", ch);
	return 0;
}

在这里插入图片描述

递归 1

#include<stdio.h>
int my_strlen(char* str)
{
	if ('\0' != *str)
	{
		return 1 + my_strlen(str + 1);
	}
	return 0;
}

void Reverse(char* str)
{
	//1.先保存第一个字符
	char tmp = *str;
	int len = my_strlen(str);

	//2.将最后一个字符存放在第一个字符的位置
	*str = *(str + len - 1);

	//3.将最后一个字符设置为\0,以便字符串长度的计算
	*(str + len - 1) = '\0';

	//4.进行中间字符串的逆序(除去第一个和最后一个字符)
	if (my_strlen(str + 1) > 1)
	{
		Reverse(str + 1);
	}

	//5.将第一个字符存放在最后一个字符的位置
	*(str + len - 1) = tmp;
}

int main()
{
	char ch[] = "crush";
	printf("%s\n", ch);
	Reverse(ch);
	printf("%s\n", ch);
	return 0;
}

在这里插入图片描述

递归 2

#include<stdio.h>
int my_strlen(char* str)
{
	if ('\0' != *str)
	{
		return 1 + my_strlen(str + 1);
	}
	return 0;
}


void Reverse(char ch[], int left, int right)
{
	if (left < right)
	{
		char tmp = ch[left];
		ch[left] = ch[right];
		ch[right] = tmp;
		Reverse(ch, left + 1, right - 1);
	}
}



int main()
{
	char ch[] = "crush";
	printf("%s\n", ch);
	int left = 0;
	int right = my_strlen(ch) - 1;
	Reverse(ch,left,right);
	printf("%s\n", ch);
	return 0;
}

在这里插入图片描述

总结,函数递归与迭代的选择。
只要不出现错误,哪个都行。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值