C语言阶段学习三

#include 
#include 

//递归函数
int recursiveFunction(int a); //函数声明

//交换数值1
void ExchangeValue1(int a1, int b1);

//交换数值
void ExchangeValue(int* a1, int* b1);

//指针知识点
void PointerTeaching(void); 

//二维数组与循环嵌套
void TwoDimArrLoopNes(void);

//无参数,无返回值
void fun1(void);

//无参数,有返回值
int fun2(void);

//有参数,无返回值
void fun3(int a);

//有参数,有返回值
int fun4(int a);
//如果函数定义在主函数下方,那么就需要在主函数上方声明函数,不然调用函数失败

int main(void)
{
     
//C语言阶段三知识点测试 ========================================================
		//二维数组与循环嵌套
		//指针
		//自定义函数

//自定义函数 =================================================================
    //函数主要有下面四种类型,注意讲解

	//函数调用
	//TwoDimArrLoopNes();//二维数组与循环嵌套知识点
	//PointerTeaching();//指针知识点

	//函数涉及模块化编程,那就是把一个小功能封装成一个独立的代码段(函数)
	//1、增加代码的复用性(重复使用)
	//2、增加代码的可读性

	//无参数,有返回值
	//int a1 = fun2();
	//printf("a1 = %d\n", a1);

	//有参数,无返回值
	//fun3(1,6); //1,6为实参

	//有参数,有返回值
	//int a2 = fun4(4,5);
	//printf("a1 = %d\n", a2);
	//printf("a1 = %d\n", fun4(4, 5));


//实例===============================================================
	//冒泡排序利用函数实现
	//popo(5); //调用函数,可以给任意个数进行排序,只需要修改实参就行
	//printf("max = %d\n", popo(5));


	//利用函数交换两个数的值
	int a = 12;
	int b = 34;
	printf("a = %d\tb = %d\n", a, b);
	ExchangeValue(&a,&b); //利用指针操作变量a,b的值;a,b的值在主函数内也改变
	//ExchangeValue函数的形参是指针,所以要传递地址
	//ExchangeValue1(a,b);
	//ExchangeValue1函数的形参是整型,所以传递变量
	printf("a = %d\tb = %d\n", a, b);


	//递归函数
	//递归函数就是自己调用自己
	//利用递归函数输出 5 4 3 2 1
	recursiveFunction(5);

	system("pause");
	return 0;
}
//冒泡排序
int popo(int N)
{
     
	// 冒泡排序 
	int iArr[100] = {
      0 }; //声明一个数组,并初始化为0

	//利用循环+scanf函数给数组赋值
	for (int i = 0; i < N; i++)
	{
     
		scanf_s("%d", &iArr[i]);
	}
	//将数进行排序,分析代码,画图讲解
	for (int i = 0; i < N; i++)
	{
     
		for (int j = i + 1; j < N; j++)
		{
     
			if (iArr[i] > iArr[j])
			{
     
				int temp = iArr[i];
				iArr[i] = iArr[j];
				iArr[j] = temp;
			}
		}
	}
	//依次输出数组元素
	printf("从小到大排序为:\n");
	for (int i = 0; i < N; i++)
	{
     
		printf("%d ", iArr[i]);
	}
	putchar('\n');
	//返回最大值
	return iArr[N - 1];

}

//递归函数
int recursiveFunction(int a)
{
     
	if (a == 0)
		return;
	printf("%d\n", a--);
	recursiveFunction(a);

}

//交换数值1
void ExchangeValue1(int a1, int b1)
{
     
	int temp = a1;
	a1 = b1;
	b1 = temp;
	//printf("a = %d\tb = %d\n", a1, b1); 只在自定义函数内部值交换,主函数内不交换
}

//交换数值
void ExchangeValue(int *a1,int *b1)
{
     
	//利用指针操作变量空间的值,值改变
	int temp = *a1;
	*a1 = *b1;
	*b1 = temp;
}

//指针知识点
void PointerTeaching(void)
{
     
	//指针 ========================================================================
	//指针是一种数据类型,就像int和float,int装整型数据,float装浮点型数据,
	//指针装地址型数据,仅此而已
	//指针在C语言中是指向一个内存地址的数据类型。在C语言中,变量是有一个内存地址表示它的存储位置
	//指针可以指向变量所在的地址,从而获取到当前地址所存储的值。

	//了解指针的使用方法
	//形式:类型 + * + 变量名;例如 int* p;
	//int是类型,*表示指针,p为指针的变量名
	int a = 12;
	int* p; //声明一个指针
	p = &a; //让指针指向变量a的地址,所以要加 &
	//也可以声明的时候指向变量地址, 如 int* p = &a;

	//指针变量装哪块地址,就指向哪一块空间
	//比如现在p已经装了a的地址,然后就可以利用p对a的空间进行调用
	//输出a的值
	printf("%d\n", a); //输出 12
	printf("%d\n", *p);//输出12
	// * 内存操作符
	//* + 地址就会调用对应空间内的值
	// 因为p == &a,所以 *p == *&a
	printf("*&a = %d\n", *&a); //输出12
	printf("*p = %d\n", *p); //输出12


	//*的四种作用
	//声明的时候有*,表示指针变量,例如 int * p;
	//*+地址,表示地址操作符,  *p
	//数字*数字,表示乘法,  1*2
	//注释,  /*    */

	//地址问题
	printf("a的地址为:%d\n", &a);
	printf("a的地址为:%d\n", p);
	//因为p指向a的地址,所以p == &a
	printf("p的地址为:%d\n", &p);
	//指针自己有一个地址,&p 就是指针自己的地址

	//指向其他空间
	//之前p是指向a的地址
	int b = 34;
	p = &b; //将指针p指向b的地址
	//将指针p指向b的地址后,就可以利用p对b进行读、写、取地址
	//读
	printf("%d\n", *p);

	//写
	*p = 789;

	//取地址
	//p就是指向空间的地址,&p是p变量自己的地址

	//指针所指向的空间是什么类型,那么*p 就一次操作多大的内存空间
	//b是int类型,那么p一次就操作 4字节的空间
	//指针指向的时候最好指向同类型,不然结果有些问题



	//二级指针
	int a1 = 12;
	int* p1 = &a;
	int** p2 = &p1;
	//一级指针变量的地址,用二级指针来装,同理二级指针地址用三级指针装
	//一个指针指向一个变量,*这个指针,就是那个变量本身
	//*p2 == p1	
	//* *p2 == *p1 == a1
	//输出a1的值
	printf("\n");
	printf("a1 = %d\n", a1); //输出34
	printf("*p1 = %d\n", *p1); //输出34
	printf("**p2 = %d\n", **p2); //输出34

	//一维数组与指针
	int a2[5] = {
      3, 1, 7, 4, 9 };
	int* p3 = &a2[0];
	//p3 = a2; 
	//p3 = &a2[0] == p3 = a2
	//因为a2就是数组的首地址

	//利用指针遍历数组
	//三种输出数组元素的方法
	for (int i = 0; i < 5; i++)
	{
     
		printf("a2 = %d\t*p3+%d = %d\tp3[%d] = %d\n", a2[i], i, *(p3 + i), i, p3[i]);
	}

	//代码分析
	//a2[0] == *(p3+0) == *p == p3[0]
	//a2[1] == *(p3+1) == p3[1])
	//a2[2] == *(p3+2) == p3[2])
	//a2[3] == *(p3+3) == p3[3])
	//a2[4] == *(p3+4) == p3[4])
	//不能使用 p++,因为p++修改了p本身,p+i只是改了偏移量,p本身没有改变
	//p3[i]本质:地址 + [偏移量]


	//指针数组
	int* a4[5];
	//两个关键词
	//第一是数组(变量(a4)的类型,变量(a4)先跟方括号结合)
	//第二是指针(元素类型)

	int b2 = 1;
	int c2 = 2;
	int d2 = 3;
	int e2 = 4;
	int f2 = 5;
	int* a6[5] = {
      &b2, &c2, &d2, &e2, &f2 };//这就是指针数组,数组里面装指针
	//本质:因为指针指向变量的地址,那么就是数组里面装地址
	//所以这种数组这样定义:int* a[5] = {&b, &c, &d, &e, &f};

	//a6[0] == &b2,因为数组内装地址,所以数组第一个元素就是为b2的地址
	//*a6[0] == b2, * + 地址,就是调用相应的值,
	printf("b2地址 = %d\t*a6[0]地址 = %d\n", &b2, a6[0]);
	printf("b2 = %d\t*a6[0] = %d\n", b2, *a6[0]);
	//一步步理解
	//1、数组内装地址,所以数组元素就是地址,例如 a6[0] == &b2
	//2、* + 地址,表示地址操作符,调用对应空间中的值,例如*a6[0] == b2 = 1


	//数组指针
	//顾名思义就是数组类型的指针,也就是一个指针指向一个数组类型

	int a7[5] = {
      11,22,33,44,55 };
	int(*p7)[5] = &a7;
	//(*p7)  p7是一个指针,一定要加这个小括号,否则p7就先跟[ ]结合,就是数组了
	//p7所指向的类型,数组类型

	//p7指向a7,*p7就是a7本身, 所以*p7等价于a7,a7 = &a7[0]
	printf("a7 = %d\t*p7 = %d\n", a7, *p7); //输出首元素的地址
	printf("a7 = %d\t*p7 = %d\n", *a7, **p7); //输出首元素的的值
	printf("a7 = %d\t*p7 = %d\n", a7[4], *(*p7 + 4)); //输出首元素的地址
	//分析
	//*(*p7+4) 输出55
	//原因:*p7是数组首地址,*p7+4是数组第五个元素地址,* + 地址就输出对应元素的值
	//**p7+4 输出15
	//原因:**p7+4  == (*(*p7))+4 ,先求出首元素的值11,然后11+4 = 15
	//**(p7 + 4) 输出未知地址
	//原因:p7 + 4导致指针地址偏移,然后不再是指向数组

	//两个概念的对比
	//int(*p)[5]
	//数组的指针
	//数组的地址
	//就是指针类型是数组

	// int* p[5]
	//指针的数组
	//地址的数组
	//就是数组里面装指针(地址)

	//二维数组与指针  阶段三不讲


}

//二维数组与循环嵌套知识点
void TwoDimArrLoopNes(void)
{
     
	//Two-dimensional array and loop nesting
	//二维数组与循环嵌套 ========================================================
		//1、了解了二维数组的取值
		//2、了解循环嵌套的使用方法
		//3、了解综合使用循环嵌套获取二维数组的值

		//一维数组声明并初始化
	int iArr1[5] = {
      1,2,3,4,5 };
	//一维数组调用
	//printf("%d\n", iArr1[0]);//输出第一个元素 1

	//二维数组的声明并初始化       
	int iArr[2][5] = {
      {
      1,2,3,4,5 },{
      6,7,8,9,10 } };
	//二维数组的调用
	//printf("%d\n", iArr[0][0]); //输出 1
	//printf("%d\n", iArr[1][0]); //输出 6
	//iArr[2][5] 可以理解为两个数组堆叠而成,每个数组元素都为 5
	//[2] 代表数组的个数,[5] 代表每个数组的元素总数
	//声明时[]内的数值代表元素个数,调用时[]内的数值代表下标
	//元素个数从1开始,下标从0开始,注意区别

	//二维数组声明 并部分初始化
	int iArr2[2][5] = {
      {
      1,2,3, },{
      6,7,8,9 } };
	//部分初始化和一维数组一样,对于每个数组,未初始化的元素自动初始化为0

	//内部不加{ }初始化
	int iArr3[2][5] = {
      1,2,3,6,7,8,9 };
	//这样初始化会先将第一个数组依次初始化完,还有值就初始化第二个数组
	//iArr3[0][0] = 1
	//iArr3[0][1] = 2
	//iArr3[0][2] = 3
	//iArr3[0][3] = 6
	//iArr3[0][4] = 7

	//iArr3[1][0] = 8
	//iArr3[1][1] = 9
	//iArr3[1][2] = 0
	//iArr3[1][3] = 0
	//iArr3[1][3] = 0

	//利用循环嵌套输出查看结果,分析原理
	for (int i = 0; i < 2; i++)
	{
     
		for (int j = 0; j < 5; j++)
		{
     
			printf("iArr3[%d][%d] = %d\n", i, j, iArr3[i][j]);
		}
	}
	//代码分析
	//第一个for循环,i是控制不同的数组
	//第二个for循环,j是控制数组中的元素
	//当i = 0时,进入第二个循环,然后将第一个数组的元素全部输出出来
	//第二个循环结束,回到第一个循环,i++,i 变为 1,再次进入第二个循环
	//又输出 i = 1时,第二个数组的全部元素

	//单个元素赋值与输出
	iArr3[0][0] = 999;
	printf("%d\n", iArr3[0][0]); //输出 999

	//二维数组总结
	//二维数组就是多个一维数组堆叠而成,前面的[]控制不同的数组,后面的[]控制数组内的元素
}

//无参数,无返回值
void fun1(void)
{
     
	//需要执行的内容
}

//无参数,有返回值
int fun2(void)
{
     
	int a = 12;
	int b = 12;
	return a+b;
}

//有参数,无返回值
void fun3(int a,int b)
{
     
	//a,b为形参,比如调用函数的时候传入实参,fun3(1,6)
	//那么在fun3函数内,a = 1,b = 6,所以a+b = 7
	printf("a + b = %d\n", a + b);
}

//有参数,有返回值
int fun4(int a,int b)
{
     
	int iNum = 0;
	iNum = a + b;
	return iNum;
	
}

你可能感兴趣的:(语言篇,c语言)