指针总结(2)

指针:1、指针的总结;

2、 理解指针数组;
3、理解数组指针;
4、理解函数指针;
5、 理解函数指针数组(转移表);
6、 理解指向函数指针数组的指针;
7、 理解回调函数的使用;
8、 练习使用qsort函数排序各种类型的数据;
9、 模仿qsort的功能实现一个通用的冒泡排序;
10、几个指针和数组的相关练习。
2、
   
扩展:数组中存放的元素为指针类型:一级指针(int *arr[10])、二级指针(int **arr[10])...
指针的类型:整型指针(int *arr[10])、字符型指针(char *arr[10])、浮点型指针(float *arr[10])...
观察可知:指针数组的大小始终是:4*元素个数(指针就是地址,均占4字节)

3、

扩展:数组指针,指向数组的指针:该数组的类型可以是整型(int (*p)[10])、字符型(char (*p)[10])、浮点型(float (*p)[10])...
且数组的类型也可为指针类型,此时就是指针数组,则p为 指向指针数组的数组指针(int *(*p)[10])
而将此指针存放在数组中,则p为 指向指针数组的数组指针的指针数组(int *(*p[10])[10])
4、
扩展:函数指针,指向函数的指针,函数的返回值可以是整型(int (*pfun)( ))、字符型(char (*pfun)( ))、浮点型(float (*pfun)( ))...
函数的返回值也可以是指针类型(int * (*pfun)( ))、指针数组类型(int* (*pfun)[10]( ))、
数组指针类型(int (*)(*pfun)[10]( ))、
函数也可以是不同的参数列表,int (*pfun)(int, char)...

5、

扩展:函数指针数组是数组,是存放函数地址的数组,函数可以有参数(int (*parr[10])(int, char)),函数的返回值可以是整型、字符型、也可以是指针(int* (*parr[10])( ))...
应用:转移表的实现(简单计算器)
#include<stdio.h>
#include<assert.h>
#include<Windows.h>

#pragma warning(disable:4996)

//函数指针数组(转移表):简单计算器
int my_add(int a, int b)
{
	return  a + b;
}
int my_sub(int a, int b)
{
	return  a - b;
}
int my_mul(int a, int b)
{
	return  a * b;
}
int my_div(int a, int b)
{
	//assert(b != 0);
	if (!b){
		printf("error num2 by zero!\n");
		return -1;
	}
	return  a / b;
}

void menu()
{
	printf("******************************\n");
	printf("****  1:add        2:sub  ****\n");
	printf("****  3:mul        4:div  ****\n");
	printf("****        0:exit!       ****\n");
	printf("******************************\n");
	printf("please input your chioce!\n");
}

int main()
{
	//定义函数指针数组
	int(*parr[4])(int a, int b) = { my_add, my_sub, my_mul, my_div };
	int choice;
	int a, b;
	do{
		menu();
		scanf("%d", &choice);
		if (choice > 0 && choice <= 4){
			printf("please enter your nums<a, b>:");
			scanf("%d%d", &a, &b);
			printf("the result is: %d\n", parr[choice - 1](a, b));
		}
		else if (choice == 0){
			exit(0);
		}
		else{
			printf("input error! you should enter your choice at interval of [0,4]\n");
		}
	} while (1);

	system("pause");
	return 0;
}
6、
扩展:数组指针:int (*p)[10]; 当指针指向的这个数组是存放函数地址时,则p就是指向函数指针数组的指针(int *(*p)[10])( ))
注意:由于数组元素个数也是数组类型的一部分,所以此刻声明的指针变量中的[10]必须和它指向的函数指针数组的元素个数一致!!!
7、 回调函数
    定义:将一个函数的指针(也就是该函数的地址)作为参数传递给另一个函数,当此函数指针被用来调用其所指向的函数时,此时,该函数指针指向的函数即为回调函数。
    作用:节省函数调用时间。
    应用:使用回调函数,模拟实现qsort(快排)。
8、 练习使用qsort函数排序各种类型的数据:整型(int)、浮点型(double)、字符串(char *)。
认识qsort函数:Performs a quick sort.
    头文件:<stdlib.h>
    函数原型:
void qsort( void *base, size_t num, size_t width, int (__cdecl *compare )(const void *elem1, const void *elem2 ) );  
有四个参数,第一个:要比较的数据(数组);
                    第二个:数据个数;
                    第三个:数据类型大小;
                    第四个:返回值为int型、参数列表为 const void *elem1, const void *elem2 的函数(该函数是自己实现的比较当前要排序的许多元素中的两个元素大小,并且返回1或-1或0(可根据升序降序自己设置)!!!(该函数就为回调函数)
#include<stdio.h>
#include<Windows.h>

int my_int_cmp(const void * num1, const void * num2)
{
	int *x = (int *)num1;
	int *y = (int *)num2;
	if (*x > *y){
		return 1;//升序
	}
	else if (*x < *y){
		return -1;
	}
	else{
		return 0;
	}
}

int my_double_cmp(const void * num1, const void * num2)
{
	double *x = (double *)num1;
	double *y = (double *)num2;
	if (*x > *y){
		return -1;//降序
	}
	else if (*x < *y){
		return 1;
	}
	else{
		return 0;
	}
}

int my_string_cmp(const void * num1, const void * num2)
{
	char **x = (char **)num1;//存放字符串地址的变量x
	char **y = (char **)num2;
	char *p1 = *x;//定义指针变量指向字符串
	char *p2 = *y;

	while (*p1 == *p2 && *p1 != '\0'){
		p1++; 
		p2++;
	}
	if (*p1 != *p2){//说明while循环跳出的原因是第一个条件不满足
		if (*p1 > *p2){
			return -1;//降序
		}
		else{
			return 1;
		}
	}
	else{//执行到这,说明while的第一个条件成立,第二个不成立,说明两个字符串相等
		return 0;
	}
}

int main()
{
	/*int arr1[] = { 1, 3, 2, 4, 1, 7, 6, 3, 8, 9 };
	int size = sizeof(arr1) / sizeof(arr1[0]);
	qsort(arr1, size, sizeof(int), my_int_cmp);*/

	/*double arr2[] = { 1.2, 4.3, 6.6, 2.1, 3.9, 5.8, 9.3, 0.3 };
	int size = sizeof(arr2) / sizeof(arr2[0]);
	qsort(arr2, size, sizeof(double), my_double_cmp);*/

	//字符串排序
	char *arr3[] = { "abcd", "abcde", "abce", "zxcbv", "zxca", "qwsa", "qeas" };
	int size = sizeof(arr3) / sizeof(arr3[0]);
	qsort(arr3, size, sizeof(char *), my_string_cmp);

	system("pause");
	return 0;
}

9、模仿qsort的功能实现一个通用的冒泡排序。

#include<stdio.h>
#include<Windows.h>

int my_int_cmp(const void * num1, const void * num2)
{
	int *x = (int *)num1;
	int *y = (int *)num2;
	if (*x > *y){
		return 1;//升序
	}
	else if (*x < *y){
		return -1;
	}
	else{
		return 0;
	}
}

int my_double_cmp(const void * num1, const void * num2)
{
	double *x = (double *)num1;
	double *y = (double *)num2;
	if (*x > *y){
		return -1;//降序
	}
	else if (*x < *y){
		return 1;
	}
	else{
		return 0;
	}
}

int my_string_cmp(const void * num1, const void * num2)
{
	char **x = (char **)num1;//存放字符串地址的变量x
	char **y = (char **)num2;
	char *p1 = *x;//定义指针变量指向字符串
	char *p2 = *y;

	while (*p1 == *p2 && *p1 != '\0'){
		p1++; 
		p2++;
	}
	if (*p1 != *p2){//说明while循环跳出的原因是第一个条件不满足
		if (*p1 > *p2){
			return -1;//降序
		}
		else{
			return 1;
		}
	}
	else{//执行到这,说明while的第一个条件成立,第二个不成立,说明两个字符串相等
		return 0;
	}
}

void my_swap(const void * num1, const void * num2, int size)
{
	//交换两个元素:按字节交换,交换size(类型大小)次
	char *p1 = (char *)num1;
	char *p2 = (char *)num2;
	int i = 0;
	while (i < size){
		char tmp = *(p1 + i);
		*(p1 + i) = *(p2 + i);
		*(p2 + i) = tmp;
		i++;
	}
}

//模仿qsort的功能实现一个通用的冒泡排序
void my_qsort(void *base, int count, int size, int(*cmp)(const void *, const void *))
{
	for (int i = 0; i < count - 1; i++){
		int flag = 0;//冒泡优化
		for (int j = 0; j < count - 1 - i; j++){
			if (cmp((char *)base + size*j, (char *)base + size*(j + 1)) > 0){
				//base是void*,所以根据字节乘类型大小来确定比较元素的类型
				flag = 1;
				my_swap((char *)base + size*j, (char *)base + size*(j + 1), size);
			}
		}
	}
}

int main()
{

	/*int arr1[] = { 1, 3, 2, 4, 1, 7, 6, 3, 8, 9 };
	int size = sizeof(arr1) / sizeof(arr1[0]);
	my_qsort(arr1, size, sizeof(int), my_int_cmp);*/

	/*double arr2[] = { 1.2, 4.3, 6.6, 2.1, 3.9, 5.8, 9.3, 0.3 };
	int size = sizeof(arr2) / sizeof(arr2[0]);
	my_qsort(arr2, size, sizeof(double), my_double_cmp);*/

	//字符串排序
	char *arr3[] = { "abcd", "abcde", "abce", "zxcbv", "zxca", "qwsa", "qeas" };
	int size = sizeof(arr3) / sizeof(arr3[0]);
	my_qsort(arr3, size, sizeof(char *), my_string_cmp);

	system("pause");
	return 0;
}

10、练习指针与数组
#include<stdio.h>
#include<Windows.h>

void pointArr1()
{
	int a[5] = { 1, 2, 3, 4, 5 };
	int *p = (int *)(&a + 1);//下一个数组的地址,强转为int*则为跳过该数组的下一个地址(int *)
	printf("%d,%d", *(a + 1), *(p - 1));//2,5
}

void pointArr2()
{
	typedef struct
	{
		int num;//4
		char *pname;//4 
		short date;//2
		char ch[2];//1*2
		short year[4];//2*4
	}*p, test;//该结构体的大小:20
	p p1 = (p)malloc(sizeof(test));
	printf("%d\n", p1);//030A95A0
	printf("%d\n", p1 + 0x1);//030A95B4(p1+1实际是加上20)
	printf("%d\n", (unsigned long)p1 + 0x1);//030A95A1(此处p1是类型为无符号长整型变量+1就是+1)
	printf("%d\n", (unsigned int *)p1 + 0x1);//030A95A4(p1的类型为int*,加1就是加4)
}

void pointArr3()
{
	int a[4] = { 1, 2, 3, 4 };
	int *p1 = (int *)(&a + 1);//p1指向元素4后面的一个int大小的空间
	int *p2 = (int *)((int)a + 1);//p2指向从a首元素的第二个字节开始后面一个int大小的空间
	printf("%x,%x", p1[-1], *p2);//4(p1[-1] = *(p1-1)),2000000
}

void pointArr4()
{
	int a[3][2] = { (0, 1), (2, 3), (4, 5) };
	//注意:1、二维数组初始化时,一对{ }代表一个一维数组;
	//2、()代表一个元素,括号中是个逗号表达式,
	//所以数组int a[3][2] = {1, 3, 5}
	int *p;
	p = a[0];
	printf("%d", p[0]);//1(p[0] = *(p + 0))
}

void pointArr5()
{
	int a[5][5];
	int(*p)[4];//数组指针
	p = a;
	printf("%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);//FFFFFFFC(%p:表示无符号数),-4
}

void pointArr6()
{
	int a[2][5] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
	//int a[2][5] = { { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 0 } };
	int *p1 = (int *)(&a + 1);//p1指向数组元素0后的一个int大小的地址空间
	int *p2 = (int *)(*(a + 1));//(a+1):代表数组a的第二个元素;
	//而*(a+1):代表当前指向数组的首元素;强转后,则p2就指向的元素是6的地址
	printf("%d,%d", *(p1 - 1), *(p2 - 1));//0,5
}

void pointArr7()
{
	char *a[] = { "work", "at", "abcd" };//指针数组
	char **pa = a;//指向数组
	pa++;//+1不是加1,实质上是加上每个字符串的大小
	printf("%s\n", *pa);//at
}

void pointArr8()
{
	char *c[] = { "ENTER", "NEW", "POINT", "FIRST" };
	char **cp[] = { c + 3, c + 2, c + 1, c };
	char ***cpp = cp;
	printf("%s\n", **++cpp);//POINT
	printf("%s\n", *--*++cpp + 3);//ER
	printf("%s\n", *cpp[-2] + 3);//ST
	printf("%s\n", cpp[-1][-1] + 1);//EW
}

int main()
{
	//pointArr1();
	//pointArr2();
	//pointArr3();
	//pointArr4();
	//pointArr5();
	//pointArr6();
	//pointArr7();
	pointArr8();

	system("pause");
	return 0;
}

pointArr3()详解
pointArr5()详解
pointArr8()详解
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值