C语言指针详解(3)

前言:

强化数组指针的理解:

        在C语言指针详解(2)-CSDN博客中我们模拟实现了一个二维数组,可能大家对其中的原理还有些模糊,这一章开始之前先梳理一遍。

一维数组的模拟实现:

        再剖析二维数组之前,先来看看一维数组的模拟实现。

int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9};
	int(*a)[9] = &arr;
	int i = 0;
	for (i = 0; i < 9; i++)
	{
		printf("%d ", (*a)[i]);
	}
	return 0;
}

   通过画图理解:

           这里解引用a就可以找到数组的首元素。

二维数组的模拟实现:

void Print_arr2(int (*arr2)[4],int a,int b)
{
	int i = 0;
	for (i = 0; i < a; i++)
	{
		int j = 0;
		for (j = 0; j < b; j++)
		{
			printf("%d", arr2[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };//可以看作是一维数组的数组
	Print_arr2(arr, 3, 4);//这里传进去arr,相当于传进去的是arr首元素的地址,但是arr是一个二维数组,传进去的是第组一维数组

}

当然也可以这样打印我的二维数组:

void Print_arr2(int (*arr2)[4],int a,int b)
{
	int i = 0;
	for (i = 0; i < a; i++)
	{
		int j = 0;
		for (j = 0; j < b; j++)
		{
			printf("%d", (*(arr2+i))[j]);//这里做了改动,如果大家理解这里的话也可以,原理和一维数组的打印类似
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][4] = { 1,2,3,4,5,6,7,8,9,10,11,12 };//可以看作是一维数组的数组
	Print_arr2(arr, 3, 4);//这里传进去arr,相当于传进去的是arr首元素的地址,但是arr是一个二维数组,传进去的是第组一维数组

}

函数指针:

        这里介绍一下函数指针,函数指针可以指向一个函数,当然函数指针里面存的就是整个函数的地址,例如:

        我想实现两个数相加之后得到的数平方。

        可以这样写:

#include<stdio.h>
int Add(int a,int b)
{
	int sum = 0;
	sum = a + b;
	return sum;
}
int app(int a, int b, int (*c)(int a, int b))
{
	return (*c)(a, b) * (*c)(a, b);//调用Add函数
}
int main()
{
	int a = 0;
	int b = 12;
	scanf("%d %d", &a, &b);
	int c = Add(a,b);
	printf("%d\n", c);
	int an = 0;
	an =  app(a, b, Add);//由于我要使用Add函数求和可以把Add函数传进去
	printf("%d\n", an);
	return 0;

}

这里的 int (*c)(int a,int b)就是函数指针。

 解读函数指针int (*c)(int a,int b)

        int 表示函数的返回 类型,*表示是指针,c表示这个指针的变量名,后面的()里面的的是函数的形参。

               函数的地址这里有两种表示方式:

        1、&Add

        2、Add

        我们可以取出函数的地址放进函数指针中。然后需要的时候直接用函数指针找到函数然后调用。

函数指针数组:

        刚刚讲完函数指针后,我们可以把好多个函数指针放在数组中,就有了函数指针数组,里面存的是每个函数的地址。

        当需要时候可以取出,(*arr[0])(int ,int )

        例如:

        

int main()
{
	int a = 0;
	int b = 0;
	Add(a,b);
	Mul(a,b);
	Div(a, b);
	Sub(a, b);
	int (*arr[4])(int ,int ) = {Add,Mul,Div,Sub};//函数指针数组里面存放着函数地址
}

   

    函数指针数组实例(计算器)

        如下是调用函数可以写出一个计算器。

#include<stdio.h>
void mnue()
{
	printf("*******************************************\n");
	printf("********** 1.Add         2.Sub*************\n");
	printf("********** 3.Mul         4.Div*************\n");
	printf("********** 0.exit             *************\n");
	printf("*******************************************\n");
}
int Add(int a ,int b)
{
	return a + b;
}
int Sub(int a, int b)
{
	return a - b;
}
int Mul(int a, int b)
{
	return a * b;
}
int Div(int a, int b)
{
	return a / b;
} 
int main()
{
	int input = 0;
	do
	{
		mnue();
		printf("请选择需要的计算器<<");
		scanf("%d", &input);
		int a = 0;
		int b = 0;
		int c = 0;
		switch (input)
		{
		case 1:
			printf("请输入你要计算的数字:");
			scanf("%d%d", &a, &b);
			c = Add(a,b);
			printf("%d\n", c);
			break;
		case 2:
			printf("请输入你要计算的数字:");
			scanf("%d%d", &a, &b);
			c = Sub(a, b);
			printf("%d\n", c);
			break;
		case 3:
			printf("请输入你要计算的数字:");
			scanf("%d%d", &a, &b);
			c = Mul(a, b);
			printf("%d\n", c);
			break;
		case 4:
			printf("请输入你要计算的数字:");
			scanf("%d%d", &a, &b);
			c = Div(a, b);
			printf("%d\n", c);
			break;
		case 0:
			printf("退出计算器\n");
			break;
		default:
			printf("选择错误,请重新选择\n");
			break;
		}
	} while (input);
	return 0;
}

        这组代码我主要用的是函数的调用,当然如果要把它改成指针取用它该怎么做呢?

我们可以把这些函数的地址放在指针函数数组中!

        函数指针数组模拟实现计算机

#include<stdio.h>
void mnue()
{
	printf("*******************************************\n");
	printf("********** 1.Add         2.Sub*************\n");
	printf("********** 3.Mul         4.Div*************\n");
	printf("********** 0.exit             *************\n");
	printf("*******************************************\n");
}
int Add(int a, int b)
{
	return a + b;
}
int Sub(int a, int b)
{
	return a - b;
}
int Mul(int a, int b)
{
	return a * b;
}
int Div(int a, int b)
{
	return a / b;
}
int main()
{
	int input = 0;
	do
	{
		mnue();
		printf("请选择需要的计算器<<");
		scanf("%d", &input);
		int a = 0;
		int b = 0;
		int c = 0;
		int (*arr[5])(int, int) = { NULL, Add,Sub,Mul,Div };//转移表,函数指针数组
    //由于选择的时候从1开始,所以再数组前面加一个空指针,
		if (input == 0)
		{
			printf("退出计算机\n");
		}
		else if(input<=4&&input>=1)
		{
			printf("请输入你要计算的数字<<");
			scanf("%d%d", &a, &b);
			c = (*arr[input])(a, b);
			printf("%d\n", c);
		}
		else
		{
			printf("选择错误,请重新选择\n");
		}
	} while (input);
	return 0;
}

这样就可以利用函数指针数组。

      函数指针数组,也被叫作是转移表!

使用排序函数qsort

        首先再C语言中,库函数中有qsort这样一个函数,这个函数是干什么的呢,通过查看C plusplus可以看到:

        

分析:


        这个函数的返货类型是void,参数有void* base,size_t num,size_t size,int, compar(const void *,const void *)

        base意思是需要排序的数组的第一个元素的地址。

        num,意思是这个数组中有多少个要排序的成员。

        size,意思是每个元素的大小。

        compar,是个函数,是用作比较两个元素的函数,返回类型是int,需要传进去两个元素的地址,而且这个比较函数需要自己写,因为电脑不知道你是怎么比较的,你得写出来。

        第一个类型的值小于第二个返回-1

        第一个类型的值等于第二个返回0

        蒂耶戈类型的值大于第二个返回1

        大于0降序

        小于0升序

        类型基本上都是void,size_t,原因是你要进行排序,但是不清楚你要排序的元素是什么类型的,有可能是int型,有可能是char类型,也有可能是double,float类型,所以这里传进去的时候类型只能写成void类型。

        使用一下qsort函数看看效果:

        我想要降序,也就是指向元素如果比第二个大就往前排。

#include<stdlib.h>
int compar(const void*p1,const void *p2)
{
	return *(int*)p2 - *(int*)p1;//降序
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	qsort(arr, sz, 4, compar);
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	return 0;
}

   模拟实现qsort函数

           我可以模拟实现qsort函数,我们排序可以用冒泡排序去排序(原函数用的不是冒泡排序)

     写my_qsort函数

                先来熟悉一下冒泡排序:

int main()
{
	int arr[] = {1,2,3,4,5,6,7,8,9,10};
	int sz = sizeof(arr) / sizeof(arr[0]);
	int i = 0;
	for (i = 0; i < sz-1; i++)
	{
		int j = 0;
		for (j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] < arr[j + 1])
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}
	return 0;
}

需要遍历sz-1次,每次需要比较sz-1-i次。

        需要注意事项:

         1、写出来的函数因为为参数类型为size_t(无符号整型),返回类型是void,所以在比较的时候,需要注意强转。

        2、我们需要写出COM()函数,保证和原函数的compar()的写法一样,返回类型就是int,返回正数,负数,还有0三种情况。

        3、还需要写出一个交换的函数,也就是当条件满足时,要进行交换。

代码如下:

void my_qsort(void *base,size_t size,size_t num,int (*com)(void *p1,void *p2))
{
	int i = 0;
	for (i = 0; i < (int)num-1; i++)
	{
		int j = 0;
		for (j = 0; j < (int)num - 1 - i; j++)
		{
			if (COM((char*)base + j * size, (char*)base + (j + 1)*size) <0)
			{
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}

写 int COM(void *p1,void *p2)判断函数:

        代码如下:

int COM(void *f1,void *f2)
{
	return *(int*)f1 - *(int*)f2;
}

写void Swap()交换函数:


        注意事项:

       1、 因为不知道传进去的类型是什么,但是我们可以找到索要交换元素的每个元素的首元素,

        2、找到首元素后,我们可以找到一个最小单位,也就是char*类型的只访问1个字节,不论是什么类型,都可以一个字节一个字节交换!

void Swap(char *tuf1,char *tuf2,int size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *tuf1;
		*tuf1 = *tuf2;
		*tuf2 = tmp;
		tuf1++;
		tuf2++;
	}
}

完整代码:

        

int COM(void *f1,void *f2)
{
	return *(int*)f1 - *(int*)f2;
}
void Swap(char *tuf1,char *tuf2,int size)
{
	int i = 0;
	for (i = 0; i < size; i++)
	{
		char tmp = *tuf1;
		*tuf1 = *tuf2;
		*tuf2 = tmp;
		tuf1++;
		tuf2++;
	}
}
void my_qsort(void *base,size_t size,size_t num,int (*com)(void *p1,void *p2))
{
	int i = 0;
	for (i = 0; i < (int)num-1; i++)
	{
		int j = 0;
		for (j = 0; j < (int)num - 1 - i; j++)
		{
			if (COM((char*)base + j * size, (char*)base + (j + 1)*size) <0)
			{
				Swap((char*)base + j * size, (char*)base + (j + 1) * size, size);
			}
		}
	}
}
void test1(int * arr,int sz)
{
	int i = 0;
	for (i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
}
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	my_qsort(arr, 4, sz, COM);
	test1(arr, sz);
	return 0;
}

  • 47
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: "C语言指针详解.pdf" 是一份详细介绍C语言指针概念和使用的PDF文档。C语言中,指针是一种特殊的变量类型,用于存储其他变量的内存地址。 该PDF文档首先详细介绍了指针的定义和声明。指针的声明需要指定指针变量的类型和名称,并使用星号(*)来表示该变量是一个指针指针变量名的前面加上一个星号,可以获取所指向的变量的值,这被称为"解引用"。 文档还介绍了指针的运算。指针可以进行自增和自减运算,指针之间可以进行相减操作,返回的结果表示它们之间的距离或者偏移量。此外,还可以将指针赋值给另一个指针,或者将指针赋值给一个变量,反之亦然。 除了基本的指针概念,文档还详细介绍了指针的常见应用场景。这包括指针作为函数参数,用于在函数内部对传入的变量进行修改。还有通过指针来实现动态内存分配和释放,以及使用指针实现数据结构(如链表和树)等。 此外,该文档还包含一些常见的指针错误和问题的解决方案。这些错误包括空指针引用、野指针引用以及内存泄漏等。文档指出了这些错误的影响以及如何避免它们。 总的来说,"C语言指针详解.pdf" 是一份详细介绍C语言指针概念、使用和常见问题解决方案的文档,对于学习和理解C语言指针的人们是一份宝贵的资料。 ### 回答2: 《C语言指针详解.pdf》是一本关于C语言指针的详细解析的电子书。在这本书中,作者详细介绍了C语言指针的概念、用途和基本语法。 首先,指针C语言中非常重要的概念,它是一种数据类型,用于存储和操作内存地址。指针可以指向各种数据类型,如整数、字符、数组和结构体等。 在《C语言指针详解.pdf》中,作者详细讲解了指针的声明和初始化,以及如何通过指针来访问和修改变量的值。作者还介绍了指针与数组的关系,以及指针和函数之间的关联。 此外,书中还涵盖了指针的高级应用,如指针的算术运算、指向指针指针指针数组等。作者通过丰富的例子和代码来帮助读者理解这些概念和技巧。 《C语言指针详解.pdf》不仅适合C语言初学者,也适合有一定编程基础的读者。通过阅读此书,读者将能够更深入地理解C语言指针的功能和用法,掌握指针在编程中的灵活运用。 总之,《C语言指针详解.pdf》是一本内容详尽且易于理解的C语言指针教程。读者通过阅读此书,可以提高自己在C语言编程中的指针应用能力,从而更好地实现程序的设计和开发。 ### 回答3: 《C语言指针详解.pdf》是一本介绍C语言指针概念和使用方法的详细手册。C语言中的指针是一种非常重要和特殊的数据类型,它提供了直接访问内存地址的能力,使得C语言具有了更高的灵活性和效率。 这本手册首先会介绍指针的基本概念,包括指针变量的定义和声明、指针的初始化和赋值。它会详细讲解指针和变量之间的关系,以及指针的运算规则和使用方法。读者可以学习到如何通过指针操作变量的值和地址,以及如何利用指针实现函数的参数传递和返回值。 接下来,手册会介绍指针和数组之间的关系。C语言中,数组名本质上是一个指向数组首元素的常量指针,因此可以通过指针来操作数组。手册将详细讲解指针和数组的指针算术运算,以及指针和多维数组的关系。 此外,手册还会介绍指针和字符串之间的关系。C语言中,字符串本质上是以空字符结尾的字符数组,可以通过指针来操作字符串。手册将详细讲解指针和字符串的操作,包括字符串的输入输出、字符串的比较和拷贝。 最后,手册还会介绍指针和结构体之间的关系。C语言中,结构体是用户自定义的复合数据类型,可以通过指针来操作结构体。手册将详细讲解指针和结构体的操作,包括结构体指针的定义和使用,以及结构体指针作为函数参数的传递方式。 总之,《C语言指针详解.pdf》是一本深入浅出的指针教程,对于想更深入理解C语言指针的读者来说,是一本非常实用的参考书。无论是初学者还是有一定基础的读者,都可以从中获得很多宝贵的知识和技巧。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值