有关函数的嵌套,声明和定义以及递归(粗略了解)

50 阅读5分钟

10.20--10.26

5.0遇见的几个值得记录的代码

1.关于if和else if

#include<stdio.h>
int main()
{
	int year = 0;
	for (year = 1000;year <= 2000;year++)
	{
		//判断year是不是闰年
		if (year % 4 == 0)
		{
			if (year % 100 != 0)
			{
				printf("%d ", year);
			}
		}
		else if (year % 400 == 0)
		{
			printf("%d ", year);
		}
	}
	return 0;
}

elseif的闰年结果.png 像这样,2000和1600等世纪闰年不会被输出,其原因在于当"if"语句执行时,不会继续执行"else if";只有当"if"语句的条件不满足时,才会继续判断"else if"的条件

#include<stdio.h>
int main()
{
	int year = 0;
	for (year = 1000;year <= 2000;year++)
	{
		//判断year是不是闰年
		if (year % 4 == 0)
		{
			if (year % 100 != 0)
			{
				printf("%d ", year);
			}
		}
	    if (year % 400 == 0)
		{
			printf("%d ", year);
		}
	}
	return 0;
}

ifif的闰年结果.png

2.关于bool类型的素数判断代码

#include<stdio.h>
#include<stdbool.h>
#include<math.h>
bool is_prime(int n)
{
	int j = 0;
	for (j = 2;j <= sqrt(n);j++)
	{
		if (n % j == 0)
		{
			return false;
		}
	}

	return true;
}
int main()
{
	int i = 0;
	for (i = 100;i <= 200;i++)
	{
		if (is_prime(i))
		{
			printf("%d ", i);
		}
	}
	return 0;
}

素数结果.png

5.1函数的嵌套

函数可以嵌套调用,但是不能嵌套定义
1.函数调用
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;
}

函数调用.png

2.嵌套定义
int Add(int x,int y)
{
	return x + y;
	int Sub(int x, int y)
	{
		return x - y;
	}
}
int main()
{
	return 0;
} 

函数嵌套的错误结果.png

3.链式访问

把一个函数的返回值作为另外一个函数的参数,前提是函数要有返回类型,如果函数没有返回类型(返回类型是void),则无法实现链式访问

int main()
{
	int len = strlen("abcdef");
	printf("%d\n", len);
	//链式访问
	printf("%d\n", strlen("abcdef"));
	return 0;
}

链式访问.png

main函数有3个参数 :

int main(int argc, char* argv[], char* envp[])
{

	return 0;
}

main函数的三个参数.png

明确的说明,main函数不需要参数 :

#include<stdio.h>
int main(void)
{
	return 0;
}

明确说明main函数没有参数.png

6.1函数的声明和定义

1.函数的声明

I will tell you 在这儿有个啥函数(函数名,函数的返回类型,参数类型)

(其实有假的声明,浪费别人宝贵的3秒钟)

函数声明一般出现在函数的使用之前。要满足先声明后使用

一般要放在头文件中

#include<stdio.h>
//函数的声明
int Add(int x, int y);//只需要参数类型,参数名可以省略
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	//加法
	int sum = Add(a, b);
    printf("%d\n", sum);
	return 0;
}
//函数的定义
int Add(int x, int y)
{
	return x + y;
}

函数的声明与定义.png

2.函数的定义

真真实实滴create这个函数(函数是否真实存在取决于函数定义)

函数的具体实现,交代函数的功能实现

3.a better methood//超级推荐!!!

(1)加法模块

add.h(放声明)

#pragma once//防止头文件被重复包含
//函数的声明
int Add(int x, int y);//只需要参数类型,参数名可以省略

add.c(放实现)

//函数的定义
int Add(int x, int y)
{
	return x + y;
}
(2)包含add的头文件

(其实就是把头文件的内容拷贝过来)

#include<stdio.h>
#include "add.h"//自己写的头文件用双引号
int main()
{
	int a = 0;
	int b = 0;
	scanf("%d %d", &a, &b);
	//加法
	int sum = Add(a, b);
	printf("%d\n", sum);
	return 0;
}

函数的声明与定义法2.png

(3)优点

  • 便于协作

  • 模块化

  • 比如实现一个计算器

    运算方法人员
    加法 add.h和add.cA
    减法 sub.h和sub.cB
    乘法 mul.h和mul.cC
    除法 div.h和div.cD

    (4)分add.h和add.c的好处

    #include <stdio.h>
    #include "add.h"
    //导入静态库
    #pragma comment(lib,"add.lib")
    int main()
    {
    	int a = 0;
    	int b = 0;
    	scanf("%d %d", &a, &b);
    	int sum = Add(a, b);
    	printf("%d\n", sum);
    	return 0;
    }
    

静态库的结果.png

 how to 创建静态库(可以包含多个函数/模块):
 

保存静态库.png

(总结下来就是可以防止别人抄袭自己的代码,仅仅只让别人使用而不能具体实现)

7.1函数递归

1.什么是递归

函数自己调用自己,把大事化小,只需少量的程序就可以描述出解题过程所需要的多次重复计算,大大的减少了程序的代码量,(like 挖井,一层层往下挖,挖到底再一层层往回走)

2.递归的两个必要条件

(1)存在限制条件,当满足这个限制条件的时候,递归便不再继续

(2)每次递归调用之后越来越接近这个限制条件

#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_s("%d", &num);
	print(num);//接受一个整型(无符号),按照顺序打印它的每一位
	return 0;


1234递归的结果.png

#include<stdio.h>
#include <string.h>
//int my_strlen(char str[])//参数部分写出数组的形式
int my_strlen(char* str)//参数部分写出指针的形式
{
	int count = 0;
	while (*str != '\0')
	{
		count++;
		str++;//找下一个字符
	}
	return count;
}
int main()
{
	char arr[] = "abc";//[a b c \0]
	//char*
	int len = my_strlen(arr);
	printf("%d\n", len);
	return 0;
}

abc字符串长度.png

​ 用递归解决不创建变量求字符串长度

//递归求解
//my_strlen("abc");
//1 + my_strlen("bc");
//1 + 1 + my_strlen("c");
//1 + 1 + 1 + my_strlen("");
//1+1+1+0
#include<stdio.h>
int my_strlen( char* str)
{
	if (*str != '\0')
		return 1 + my_strlen(str + 1);
	else
		return 0;

}
	
int main()
{
	char arr[] = "abc";
	int len = my_strlen(arr);
	printf("%d\n", len);
	return 0;

}

不创建变量的求字符串(递归解决)结果.png

3.递归与迭代

(1)n的阶乘

n!=n*(n-1)! /fac(n)=n*fac(n-1)

#include<stdio.h>
//递归的方式
//int fac(int n)
//{
//	if (n <= 1)
//		return 1;
//	else
//		return n * fac(n - 1);
//}
//迭代的方式(循环)——非递归
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_s("%d", &n);
	int ret = fac(n);
	printf("ret = %d\n", ret);
	return 0;
}

迭代实现n的阶乘.png

(2)第n个斐波那契数

斐波那契数列:1 1 2 3 5 8 13 21 34 55 ...第三个数是前两个数的和

Fib(n)=Fib(n-1)+Fib(n-2),n>2 /////当n<=2时,Fib(n)=1

@1.递归

此法效率低下

#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;
	scanf_s("%d", &n);
	int ret = Fib(n);
		printf("%d\n", ret);
	return 0;
}

斐波那契数.png @2.循环

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

循环之斐波那契数.png

(3)利用递归避免出现栈溢出的方法

虽然但是这些方法也不一定有效。。。

1.将递归改成非递归
2.使用static对象(静态库对象)替代nonstatic局部对象(栈对象)