在这里插入图片描述

变量

静态变量

  1. static是存储类型关键字
  2. static修饰的变量,存储在静态区,是独立于所在函数而存在
  3. 局部变量的生命周期会睡着所在的函数开始而开始,函数的结束而终止。
    而静态变量,不隶属与任何一个函数,也不属于主函数
  4. 静态变量的生命周期:在编译阶段内分配内存空间,到整个程序结束而结束
  5. 静态变量分为:静态局部变量和静态全局变量
    • 静态局部变量:定义在函数体内的静态变量,虽然在该函数内定义出来的,但是并不隶属于该函数,生命周期与该函数无关,但是整个程序中只能被所在函数调用。
    • 静态全局变量:定义在函数体外的全局变量,该变量只能被当前文件使用,其他权限无权使用

函数

函数与数组的结合

思考

  1. 如何完整的表示一个数组?
    答:需要给定第一个元素的地址,以及数组中元素的个数
  2. 如何讲一个数组完整的从主调函数传递到被调函数中?
    答:只需要将该数组的起始地址和元素个数传入即可

数组作为函数参数传递

  1. 数组名只是一个地址,作为参数是地址传递
  2. 由于传输的是整个数组,那么被调函数中,找到的是主程序中该函数的位置
  3. 主调函数和被调函数使用的是同一个数组,背调函数对其改变,主调函数一起改变

字符数组存储字符串作为函数参数

  1. 字符串的结束标识是\0,所以,如果像函数中传递的是一个字符串时,就无需传递数组长度,因为数组不一定被使用完
#include <stdio.h>

void input(int arr[], int len)
{
	for (int i = 0; i < len; i++)
	{
		printf("请输入第%d个学生的成绩:", i+1);
		scanf("%d",&arr[i]);
	}
}

void maxamin(int arr[], int len)
{
	int maxi = 0;
	int mini = 0;
	for (int i = 0; i < len; i++)
	{
		if (arr[i] > arr[maxi])
		{
			maxi = i;
		}
		if (arr[i] < arr[mini])
		{
			mini = i;
		}
	}
	printf("最大值为%d\n", arr[maxi]);
	printf("最小值为%d\n", arr[mini]);
}

void output(int arr[], int len)
{
	printf("该数组的元素分别为:\n");
	for (int i = 0; i < len; i++)
	{
		printf("%d ", arr[i]);
	}
	putchar(10);
}

void Sort(int arr[], int len)
{
	//遍历数组
	for (int i = 0; i < len-1; i++)
	{
		//重置最大值下标
		int maxi = i;

		//遍历后面的元素
		for (int j = i+1; j < len; j++)
		{
			//更新最大值下标
			if (arr[maxi] < arr[j])
			{
				maxi = j;
			}
		}
		//判断是不是他本身
		if (maxi != i)
		{
			int temp = arr[i];
			arr[i] = arr[maxi];
			arr[maxi] = temp;
		}
	}
	printf("排序成功!\n");
}

int main(int argc, const char *argv[])
{
	int score[10] = {0};
	int len = sizeof(score)/sizeof(score[0]);

	input(score, len);
	maxamin(score, len);
	output(score, len);
	Sort(score, len);
	output(score, len);
	return 0;
}

值传递和地址传递

值传递

  1. 当函数的实参是一个普通变量或者是一个表达式的值是,形式参数对应的类型和实际参数对应的类型一致时,此时为值传递
  2. 在值传递过程中,形式参数变量的空间与实际参数变量的空间属于完全不同的空间
  3. 形式参数的改变并不会影响到实际参数
  4. 传递方式:常量、普通变量、表达式结果

例如

#include <stdio.h>

//交换函数
void swap(int a, int b) 		//此处为值传递并不影响主调函数中的数据
{
	int temp = a;
	a = b;
	b = temp;
	printf("swap:  a = %d, b = %d\n",a,b);
}

int main(int argc, const char *argv[])
{
	int num = 520;
	int key = 1314;

	swap(num, key);
	printf("main:  num = %d, key = %d\n", num, key);

	return 0;
}

地址传递

  1. 当主调函数传递的是某个变量的地址时,形参使用能接收地址的容器进行接收。并且在被调函数中,对地址中的数据进行更改时,此时为地址传递
  2. 形式参数:数组名、指针名
    实际参数:数组名、变量地址
  3. 当进行地址传递是,形参数据和实参数据属于同一个内存空间,因此形参如果改变了其内容,实参也会读取到该内容的改变

函数递归

  1. 函数体直接或者间接调用自己本身时,就是函数递归。
  2. 如果没有结束的方式的话,函数无限制的调用自己将会出现段错误,原因是系统将会为每一个函数开辟内存空间,最终导致内存爆满。
  3. 格式
//直接递归调用
void fun()
{
	fun();
}
//简介递归调用
void hun()
{
	fun();
}

void fun()
{
	hun();
}

  1. 递归分类:
    • 普通递归函数:包括递归出口和递归表达式的递归(执行到一定程度时,会自己结束)
    • 死递归:没有递归出口的递归函数
  2. 递归条件:
    • 递归出口:当递归函数执行到该处后,会自动返回
    • 递归表达式:能够进行更小规模的同等问题的函数自我调用
  3. 递归思想:逐层分解问题到最小单元,在逐层合并解决大问题

练习

  1. 写一个函数,求给定数据的阶乘
#include <stdio.h>

int fun(int n)
{
	//0的阶乘为1 	递归出口
	if (n == 0)
	{
		return 1;
	}else
	{
		//n*!(n-1) 递归求n-1的阶乘
		return n*fun(n-1);
	}
}

int main(int argc, const char *argv[])
{
	int n = 5;
	int ret = 0;
	//调用函数递归求解n的阶乘 
	ret = fun(n);
	printf("ret = %d\n", ret);

	return 0;
}
  1. 给定一个幂的底数和指数,求该幂的值
#include <stdio.h>

int fun(int a, int b)
{
	//任何数的0次幂为1	递归出口
	if (b == 0)
	{
		return 1;
	}else
	{	//递归乘以他本身,以求得结果
		return a*fun(a, b-1);
	}
}

int main(int argc, const char *argv[])
{
	int a, b, res;
	printf("请输入所求幂的底数和指数:");
	scanf("%d%d", &a, &b);
	res = fun(a, b);
	printf("%d的%d次方为:%d\n", a, b, res);
	return 0;
}

  1. 提示输入一个数,使用递归的方式输出该数的每一位
#include <stdio.h>

void fun(int a)
{
	//小于等于10直接模10得到个位
	if (a<10)
	{
		printf("%d ",a);
	}else
	{
		//递归除以10,不断去掉个位,直到最高位落到个位后输出
		fun(a/10);
		printf("%d ",a%10);
	}

}

int main(int argc, const char *argv[])
{
	int a;
	printf("请输入一个数:");
	scanf("%d", &a);
	fun(a);
	putchar(10);
	return 0;
}

  1. 提示并输入斐波那契数列的项数,输出该项数对应的数值
#include <stdio.h>

int fun(int a)
{
		//第一位和第二位的值为1
		if (a == 1 || a == 2)
		{
			return 1;
		}else
		{
			//从第三位开始,其值为前两项之和
			return fun(a-2)+fun(a-1);
		}

}

int main(int argc, const char *argv[])
{
	int a, res;
	printf("请输入要查询的项数:");
	scanf("%d", &a);
	res = fun(a);
	printf("%d\n", res);

	return 0;
}
  1. 老汉赶鸭子问题:
    一个老汉,赶着一群鸭子到每个村售卖,每经过一个村庄,卖出剩余鸭子的一半多一只。经过7个村庄后还剩一只,问最开始有多少只
#include <stdio.h>

int fun(int a)
{
	//最后老汉只剩下一只鸭子
	if (a == 0)
	{
		return 1;
	}else
	{	
		//递归回推上一次卖鸭子时鸭子的个数
		return ((fun(a-1)+1)*2);
	}
}

int main(int argc, const char *argv[])
{
	//7为老汉经过的村庄
	int a = 7,res;
	res = fun(a);
	printf("%d\n",res);
	return 0;
}

作业

  1. 仿照strcpy原理,手动实现 myStrcpy函数
#include <stdio.h>

void myStrcpy(char str1[], char str2[])
{
	//遍历原字符串
	for (int i = 0; str1[i] != '\0'; i++)
	{
		//依次赋值给目标字符串元素
		str2[i] = str1[i];
	}
}

int main(int argc, const char *argv[])
{
	//定义源字符串以及目标字符串
	char str1[128] = "";
	char str2[128] = "";
	
	//输入原字符串
	printf("请输入一个字符串:");
	gets(str1);
	//自定义拷贝函数
	myStrcpy(str1,str2);
	//输出目标字符串
	printf("%s\n", str2);

 
	return 0;
}

在这里插入图片描述
2. 仿照strcmp原理,手动实现myStrcmp函数

#include <stdio.h>

int myStrcmp(char str1[], char str2[])
{
	//遍历字符数组
	for (int i = 0; str1[i] != 0; i++)
	{
		//如果当前str1的字符大于str2的字符就返回整数
		if (str1[i] > str2[i])
		{
			return 1;
		}
		//如果当前str1的字符小于str2的字符就返回整数
		if (str1[i] < str2[i])
		{
			return -1;
		}
	}
	//若全部比较完之后没有出现上面的情况就说明两个字符数组的内容一致,返回0
	return 0;
}

int main(int argc, const char *argv[])
{
	char str1[128] = "";
	char str2[128] = "";
	printf("请输入字符串1:");
	gets(str1);
	printf("请输入字符串2:");
	gets(str2);
	if (!myStrcmp(str1, str2))
	{
		printf("两个字符串相同\n");
	}else
	{
		printf("两个字符串不相同\n");
	}

	return 0;
}

在这里插入图片描述
3. 仿照strcat原理,手动实现myStrcat

#include <stdio.h>

void myStrcat(char str1[], char str2[])
{
	int flag = 0;
	//定位到字符串1的末尾
	for (int i = 0; str1[i] != 0; i++)
	{
		flag++;
	}
	//将字符串2拼接到字符串1之后
	for (int i = 0; str2[i] != 0; i++)
	{
		str1[i+flag] = str2[i];
	}
}

int main(int argc, const char *argv[])
{
	char str1[128] = "";
	char str2[128] = "";
	printf("请输入字符串1:");
	gets(str1);
	printf("请输入字符串2:");
	gets(str2);
	myStrcat(str1, str2);
	printf("%s\n", str1);
	return 0;
}

在这里插入图片描述
4. 手动实现myStratio函数:当字符串只包含数字字符时,将其转化为整形并返回,其他情况返回0

#include <stdio.h>

int myStratio(char str[])
{
	//记录字符串长度
	int count = 0;

	//用于存储返回值的结果
	int sum = 0;

	//遍历字符串检测是否有非数字字符
	for (int i = 0; str[i] != 0; i++)
	{
		if (str[i] < '0' || str[i] > '9')
		{
			return 0;
		}
		count++;
	}
	//从后面往前遍历字符数组
	for (int i = count-1; i >= 0; i--)
	{
		//将当前的数字字符转化为整数
		int temp = str[i] - '0';
		
		//每往前推一位就要多乘一次10
		for (int j = count-i-1; j > 0; j--)
		{
			temp *= 10;
		}
		//将当前的计算结果加入求和中
		sum += temp;
	}
	//返回最后的结果
	return sum;
}

int main(int argc, const char *argv[])
{
	int res = 0;
	char str[128] = "";
	printf("请输入字符串:");
	gets(str);
	res = myStratio(str);
	printf("%d\n", res);
	return 0;
}

在这里插入图片描述

  1. 主程序中提供两个整形数组,分别初始化如下: int arr[] = {2,3,7,6,8,9,4,5,1}; int brr[] = {3,4,10,6,20,1};
    定义函数传递这两个数组,并传递一个新数组
    函数体内完成求出这两个数组的交集放入新数组中,并在主程序中输出新数组中的数据
#include <stdio.h>

int overlap(int arr[], int lena,int brr[],int lenb, int res[])
{

	int flag = 0;
	//遍历数组a
	for (int i = 0; i < lena; i++)
	{
		//遍历数组b
		for (int j = 0; j < lenb; j++)
		{
			//若相等,将该元素赋值给结果数组
			if (arr[i] == brr[j])
			{
				res[flag] = arr[i];
				flag++;
			}
		}
	}
	//返回交集元素的个数
	return flag;
}

int main(int argc, const char *argv[])
{
	int arr[] = {2, 3, 7, 6, 8, 9, 4, 5, 1};
	int brr[] = {3, 4, 10, 6, 20, 1};
	int lena = sizeof(arr)/sizeof(arr[0]);
	int lenb = sizeof(brr)/sizeof(brr[0]);
	int res[20] = {0};
	int lenr;
	lenr = overlap(arr,lena,brr,lenb,res);

	for (int i = 0; i < lenr; i++)
	{
		printf("%d ", res[i]);
	}
	putchar(10);

	return 0;
}

在这里插入图片描述

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部