C语言学习笔记(九)—— 函数、递归和指针

一、函数

1、一个简单的函数示例

函数是完成特定任务的独立程序代码单元。

#include <stdio.h>
void printStar();//声明函数原型,函数原型会指明函数的类型和函数接受的参数。前面的void是函数类型,表明函数没有返回值
#define NUM 20

int main(){//主函数

	printStar();//调用函数

	printf("这里是文字内容区域!\n");

	printStar();//调用函数
	return 0;
}

void printStar(){//定义函数
	for(int count=0;count<NUM;count++){
		printf("*");
	}
	printf("\n");
}

2、带形式参数和实际参数的函数

形式参数是被调函数中的变量,实际函数是主调函数赋给被调函数的具体值,它可以是常量、变量或者表达式的值。

int main(){//主函数
	printRect(3,5);//实际参数,打印三行五列的矩形
	return 0;
}

void printRect(int row,int col){//形式参数
	for(int i=0;i<row;i++){
		for(int j=0;j<col;j++){
			printf("*");
		}
		printf("\n");
	}
} 

3、带return的函数

void example3(){
	int x,y,z;
	while(scanf("%d %d",&x,&y)==2){
		fflush(stdin);//刷新输入流
		printf("参数1是:%d,参数2是:%d\n",x,y);
		z=maxNum(x,y);
		printf("两个参数中的最大值是:%d\n",z);
	}
}

int maxNum(int x,int y){
	int z;
	if(x>y){
		z=x;
	}else{
		z=y;
	}
	return z;
} 

二、递归

1、一个简单的程序演示递归

/**
 * 数值i的值是:1 内存地址是:0061FF10
 * 数值i的值是:2 内存地址是:0061FEF0
 * 数值i的值是:3 内存地址是:0061FED0
 * 数值i的值是:3 内存地址是:0061FED0
 * 数值i的值是:2 内存地址是:0061FEF0
 * 数值i的值是:1 内存地址是:0061FF10
 */
void example4(){
	recursion(1);
}

void recursion(int i){
	printf("数值i的值是:%d 内存地址是:%p\n",i,&i);
	if(i<3){
		recursion(i+1);
	}
	printf("数值i的值是:%d 内存地址是:%p\n",i,&i);
} 

注意:每级递归的变量都属于本级递归私有

2、递归的基本原理

① 每级函数调用都有自己的变量;

② 每次函数调用都会返回一次,当函数执行完毕后,控制权将被传回上一级递归,程序必须按顺序逐级返回递归;

③ 递归函数中位于递归之前的语句,均按被调函数的顺序执行;

④ 递归函数中位于递归之后的语句,均按被调函数相反的顺序执行;

⑤ 递归函数必须包含可以让递归停止的语句。

3、尾递归

递归调用在函数的末尾,正好在return之前,这种递归被称为尾递归,它其实相当于循环。

使用循环和尾递归来演示阶乘,如下:

void example5() {
	int num = 5,j=1; //1*2*3*4*5=120
	//factorial_while(num);
	int result = factorial_recursion(num,j);
	printf("%d的阶乘是:%d", num, result);
}
//使用循环计算阶乘
void factorial_while(int num) {
	int z = 1;
	for (int i = 1; i <= num; i++) {
		z = z * i;
	}
	printf("%d的阶乘是:%d", num, z);
}
//使用递归计算阶乘
int factorial_recursion(int num,int j) {
	int z= 1;
	if (j<num) {
		z = factorial_recursion(num,j+1);
	}
	return z*j;
}

4、递归和倒序计算

void example6(){
	recursion_two(10);
}

//用递归函数打印正整数的二进制表示形式
void recursion_two(int num){
	int z=num%2;//递归函数的第一层级打印最后一位
	if(num/2>0){//当除数为0时的余数是为二进制位的第一位,递归函数的最后层级打印的是二进制数的第一位
		recursion_two(num/2);//把除数当作参数再次传递给递归函数
	}
	printf("%d",z);
}

5、递归之斐波那契数列

数列定义,第1个和第2个数字都是1,后续的两个数字都是前两个数字之和,递归计算数列如下:

void example7(){
	long count = fiboshulie(24);
	printf("%d",count);
}

long fiboshulie(int n){
	if(n>2){
		return fiboshulie(n-1)+fiboshulie(n-2);
	}else{
		return 1;
	}
} 

三、编译多源代码文件的程序

1、头文件(head.h)

头文件中主要是声明函数原型和常量

//在此文件中统一定义函数原型和常量
#define NUM1 2

long fiboshulie1(int n);

2、函数支持文件(second.c)

函数支持文件主要是编写独立的函数代码块,供主函数调用

//此文件主要是编写独立的函数代码块,供主函数调用
#include<stdio.h>
#include"head.h"

long fiboshulie1(int n){
	if(n>NUM1){
		return fiboshulie1(n-1)+fiboshulie1(n-2);
	}else{
		return 1;
	}
}

3、主函数所的文件

#include"head.h" //该指令中的双引号表明被包含的文件位于当前目录中

int main() { //主函数
	example8();
	return 0;
}

void example8(){
	long l = fiboshulie1(24);
	printf("%d",l);
} 

四、查找地址:&运算符

指针,是一个值为内存地址的变量,指针变量的值是地址,如果要创建指针,要先声明指针变量的类型

1、示例程序

void example9(){
	int x = 1,y=2;
	printf("在example9函数中x的内存地址是:%p\n",&x);
	printf("在example9函数中y的内存地址是:%p\n",&y);
	cursor(x);
}

void cursor(int x){//需要注意的是虽然这里使用的x的值一样,但它们的内存地址不一样
	int y = 2;
	printf("在cursor函数中x的内存地址是:%p\n",&x);
	printf("在cursor函数中y的内存地址是:%p\n",&y);
}

/*
 * 内存地址使用十六进制显示,一个十六进制对应4个二进制位
在example9函数中x的内存地址是:0061FF1C
在example9函数中y的内存地址是:0061FF18
在cursor函数中x的内存地址是:0061FF00
在cursor函数中y的内存地址是:0061FEEC
*/

2、声明指针

        声明指针变量时必须指定指针所指向变量的类型,不同的变量类型占用不同的存储空间,一些指针操作要求知道操作对象的大小。示例如下:

void example11(){
	char * ch;//ch是指向char类型变量的指针,*表明变量声明的是一个指针

	int a = 10;
	int *a2 = &a;//声明int类型的指针并将指针指向变量a的内存地址,*是间接运算符,也称为解引用运算符,*与变量名之间的空格可有可无
	int a3 = *a2;//解引用,相当于a3=a
	printf("%d\n",a3);//10
}

3、使用指针交换函数中的变量值

一般交换函数中变量值的方式如下:

void example10(){
	int temp,x=2,y=5;
	temp = x;
	x = y;
	y = temp;
	printf("x的值是:%d,y的值是:%d",x,y);//x的值是:5,y的值是:2
} 

使用指针来交换函数中变量值的方式如下:

void example12() {
	int x = 2, y = 5, temp;
	temp  = *&x;
	*&x = *&y;
	*&y = temp;
	printf("x的值是:%d,y的值是:%d",x,y);//x的值是:5,y的值是:2
}

4、使用指针在函数间进行通信

void example13() {
	int x = 2, y = 5;
	printf("在example13函数中x的值是:%d,y的值是:%d\n", x, y);
	example14(&x, &y); //在函数通信时传递指针变量
	printf("在example13函数中x的值是:%d,y的值是:%d\n", x, y);//通过指针操作改变了调用函数中变量的值,如果不使用指针是无法进行这样操作的
}

void example14(int *x, int *y) { //传递过来时已经使用*进行了解引用操作
	printf("在example14函数中x的值是:%d,y的值是:%d\n", *x, *y);
	int temp;
	temp = *x;
	*x = *y;
	*y = temp;
	printf("在example14函数中x的值是:%d,y的值是:%d\n", *x, *y);
}

/*在example13函数中x的值是:2,y的值是:5
在example14函数中x的值是:2,y的值是:5
在example14函数中x的值是:5,y的值是:2
在example13函数中x的值是:5,y的值是:2*/

猜你喜欢

转载自blog.csdn.net/alexshi5/article/details/80721879