#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;
}