C语言之指针的奥秘(三)

一、字符指针变量

在指针的类型中,有字符指针char*,一般使用:

#include<stdio.h>
int main()
{
	char ch = 'w';
	char* p = &ch;
	*p = 'w';
	return 0;
}

还有一种方式:

#include<stdio.h>
int main()
{
	const char* p = "hello world";
	printf("%s\n", p);
	return 0;
}

 这个代码的本质是把字符串hello world首字符的地址放到p中,即把一个常量字符串的首字符h的地址存放到指针变量p中。

const可去掉,加上const效果更好

 学习一道和字符串相关的题:

#include<stdio.h>
int main()
{
	char str1[] = "hello bit.";
	char str2[] = "hello bit.";
	const char* str3 = "hello bit.";
	const char* str4 = "hello bit.";
	if (str1 == str2)
		printf("str1 and str2 are same\n");
	else
		printf("str1 and str2 are not same\n");

	if (str3 == str4)
		printf("str3 and str4 are same\n");
	else
		printf("str3 and str4 are not same\n");

	return 0;
}

思考一下运行结果是什么呢?

这里str3和str4指向的是同一个常量字符串,指向的都是“”hello bit.的地址。C/C++会把常量字符串存储到单独的一个内存区域,当几个指针指向同一个字符串时,他们会指向同一块内存。但是用相同的常量字符串去初始化不同的数组时就会开辟出不同的内存块。所以str1和str2不同,str3和str4相同。

相同的常量字符串没必要保存多份,因为常量字符串不能被修改,所以大家共用一份是能满足需要的,这样也能节省空间!

二、数组指针变量

1.数组指针变量的概念

整型指针变量:存放的是整型变量的地址,能够指向整型数据的指针。

浮点型指针变量:存放的是浮点型变量的地址,能够指向浮点型数据的指针。

数组指针变量:存放的是数组的地址,能够指向数组的指针变量。

int *p1[10];
int (*p2)[10];

 p1是指针数组,存放指针的数组;

p2是数组指针,p2先和*结合,说明p2是一个指针变量,然后指针指向的是一个大小为10个整型的数组,所以p2是一个指针,指向数组,叫做数组指针

注意:[ ]的优先级要高于*,所以必须加上( )来保证p先和*结合。

2.数组指针变量初始化

 数组指针类型解析:去掉名字就是,剩下的就是数组指针类型,即int (*)[10] 

三、二维数组传参的本质

若有一个二维数组需要传参给一个函数时,过去会这样写:

#include<stdio.h>
void Print(int arr[3][5], int r, int c)
{
	int i = 0;
	for (i = 0; i < r; i++)
	{
		int j = 0;
		for (j = 0; j < c; j++)
		{
			printf("%d ", arr[i][j]);
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
	Print(arr, 3, 5);
	return 0;
}

还有其它写法吗?

二维数组启示可以看作是一维数组的数组,也就是二维数组的每个元素是一个一维数组,那么二维数组的首元素就是第一行,是个一维数组。

根据数组名是数组首元素的地址这个规则,二维数组的数组名就是第一行的地址,是一维数组的地址。由上图可得,第一行的一维数组类型是int [5],所以第一行的地址的类型就是数组指针类型int (*) [5]。

二维数组传参本质上是传递了地址,传递的是第一行这个一维数组的地址。

 若有一个二维数组需要传参给一个函数时,还可以写成指针形式:

#include<stdio.h>
void Print(int(*p)[5], int r, int c)
{
	int i = 0;
	for (i = 0; i < r; i++)
	{
		int j = 0;
		for (j = 0; j < c; j++)
		{
			printf("%d ", *(*(p + i) + j));
		}
		printf("\n");
	}
}
int main()
{
	int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
	Print(arr, 3, 5);
	return 0;
}

二维数组传参,形参的部分可以写成数组,也可以写成指针形式。

四、函数指针变量

1.函数指针变量的创建

函数指针变量是用来存放函数地址的,通过地址能调用函数。

先看一段代码:

我们可以看到运行结果是一样的。我们可以得到:函数是有地址的, 函数名就是函数的地址,也可以通过&函数名的方法获得函数的地址。

如果要将函数的地址存放起来,就要创建函数指针变量:

#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int(*pf1)(int, int) = Add;
	int(*pf2)(int x, int y) = &Add;
	return 0;
}

函数指针类型:int  (*)  (int  x,int  y) 

2.函数指针变量的使用

通过函数指针调用函数指针指向的函数。

#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int main()
{
	int a = Add(2, 3);
	printf("%d\n", a);

	int (*pf)(int, int) = Add;
	int b = (*pf)(2, 3);
	printf("%d\n", b);
	int c = pf(2, 3);
	printf("%d\n", c);
	return 0;
}

五、函数指针数组

把函数的地址存到一个数组中,这个数组就叫函数指针数组。

#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
int main()
{
	int(*pfarr[4])(int, int) = { Add,Sub,Mul,Div };//pfarr是函数指针数组
	int i = 0;
	for (i = 0; i < 4; i++)
	{
		int r = pfarr[i](8, 4);
		printf("%d\n", r);
	}
	return 0;
}

函数指针数组:int  (*pfarr[4])(int,int) ——上面代码

函数指针数组类型:int  (*)( ) 

六、转移表

 函数指针的用途:转移表

计算器的一般实现:

#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
int main()
{
	int x = 0;
	int y = 0;
	int z = 0;
	int input = 1;
	do
	{
		printf("*********************\n");
		printf("**** 1.Add 2.Sub ****\n");
		printf("**** 3.Mul 4.Div ****\n");
		printf("**** 0.exit      ****\n");
		printf("*********************\n");
		printf("请选择:");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			printf("请输入两个数:");
			scanf("%d %d", &x, &y);
			z = Add(x, y);
			printf("%d\n", z);
			break;
		case 2:
			printf("请输入两个数:");
			scanf("%d %d", &x, &y);
			z = Sub(x, y);
			printf("%d\n", z);
			break;
		case 3:
			printf("请输入两个数:");
			scanf("%d %d", &x, &y);
			z = Mul(x, y);
			printf("%d\n", z);
			break;
		case 4:
			printf("请输入两个数:");
			scanf("%d %d", &x, &y);
			z = Div(x, y);
			printf("%d\n", z);
			break;
		case 0:
			printf("退出程序\n");
			break;
		default:
			printf("输入错误\n");
			break;
		}
	} while (input);
	return 0;
}

使用函数指针数组实现:

#include<stdio.h>
int Add(int x, int y)
{
	return x + y;
}
int Sub(int x, int y)
{
	return x - y;
}
int Mul(int x, int y)
{
	return x * y;
}
int Div(int x, int y)
{
	return x / y;
}
int main()
{
	int x = 0;
	int y = 0;
	int z = 0;
	int input = 1;
	int(*pfarr[5])(int, int) = { 0,Add,Sub,Mul,Div };
	do
	{
		printf("*********************\n");
		printf("**** 1.Add 2.Sub ****\n");
		printf("**** 3.Mul 4.Div ****\n");
		printf("**** 0.exit      ****\n");
		printf("*********************\n");
		printf("请选择:");
		scanf("%d", &input);

		if (input >= 1 && input <= 4)
		{
			printf("请输入两个数:");
			scanf("%d %d", &x, &y);
			z = pfarr[input](x, y);
			printf("%d\n", z);
		}
		else if (input == 0)
		{
			printf("退出\n");
		}
		else
		{
			printf("输入错误\n");
		}
	} while (input);
	return 0;
}
  • 14
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
本火锅店点餐系统采用Java语言和Vue技术,框架采用SSM,搭配Mysql数据库,运行在Idea里,采用小程序模式。本火锅店点餐系统提供管理员、用户两种角色的服务。总的功能包括菜品的查询、菜品的购买、餐桌预定和订单管理。本系统可以帮助管理员更新菜品信息和管理订单信息,帮助用户实现在线的点餐方式,并可以实现餐桌预定。本系统采用成熟技术开发可以完成点餐管理的相关工作。 本系统的功能围绕用户、管理员两种权限设计。根据不同权限的不同需求设计出更符合用户要求的功能。本系统中管理员主要负责审核管理用户,发布分享新的菜品,审核用户的订餐信息和餐桌预定信息等,用户可以对需要的菜品进行购买、预定餐桌等。用户可以管理个人资料、查询菜品、在线点餐和预定餐桌、管理订单等,用户的个人资料是由管理员添加用户资料时产生,用户的订单内容由用户在购买菜品时产生,用户预定信息由用户在预定餐桌操作时产生。 本系统的功能设计为管理员、用户两部分。管理员为菜品管理、菜品分类管理、用户管理、订单管理等,用户的功能为查询菜品,在线点餐、预定餐桌、管理个人信息等。 管理员负责用户信息的删除和管理,用户的姓名和手机号都可以由管理员在此功能里看到。管理员可以对菜品的信息进行管理、审核。本功能可以实现菜品的定时更新和审核管理。本功能包括查询餐桌,也可以发布新的餐桌信息。管理员可以查询已预定的餐桌,并进行审核。管理员可以管理公告和系统的轮播图,可以安排活动。管理员可以对个人的资料进行修改和管理,管理员还可以在本功能里修改密码。管理员可以查询用户的订单,并完成菜品的安排。 当用户登录进系统后可以修改自己的资料,可以使自己信息的保持正确性。还可以修改密码。用户可以浏览所有的菜品,可以查看详细的菜品内容,也可以进行菜品的点餐。在本功能里用户可以进行点餐。用户可以浏览没有预定出去的餐桌,选择合适的餐桌可以进行预定。用户可以管理购物车里的菜品。用户可以管理自己的订单,在订单管理界面里也可以进行查询操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值