(九十六)函数和结构

本文涉及的产品
云原生数据库 PolarDB 分布式版,标准版 2核8GB
简介:

结构比字符串/数组简单之处在于,可以把一个结构赋给另一个结构,而字符串、数组不行。

注:例如 struct abc{int a; int b;}这样的结构定义,其中abc为类型名。可以称之为abc结构。

 

函数可以直接返回结构,

但若需要地址的话,需要加上地址运算符&才能得到结构的地址。

 

返回结构的函数头为:

类型名 函数名(传递的参数)

如代码:

#include<iostream>
using namespace std;

struct ab	//定义ab结构
{
	int a;	//ab的两个变量
	int b;
};
ab abc(void);	//ab结构的函数原型,这个结构函数无传递参数

int main()
{
	ab c;	//声明ab结构c,c为使用ab结构的变量名。
	c = abc();	//调用结构函数abc,将返回值赋值给变量c
	cout << c.a << endl;	//打印c的变量a的值
	cout << c.b << endl;	//打印c的变量b的值
	cout << &c << endl;	//打印c的地址
	system("pause");
	return 0;
}

ab abc(void)	//ab结构的函数头,函数名为abc
{
	ab def = { 3,5 };	//初始化def,使用ab结构,赋值分别为3和5
	return ab(def);	//返回def,格式为 定义结构(使用该结构的变量名),或 直接输入def,省略ab和括号也可以
}

输出:


3
5
002FF7C0
请按任意键继续. . .

总结:

①函数头:

格式为:定义的结构(如代码中的ab) 函数名(参数);

不同的结构使用不同的定义的结构。

 

②参数:

可以无参数,也可以按实际需要传递参数。

结构名(如代码中的c)可以直接当参数进行传递,例如以上代码若要传递参数的话,改为:

ab abc(ab,ab)   注:ab是定义的结构

 

③返回值:

格式为:return 使用该结构的变量名;   或   return 定义的结构(使用该结构的变量名)

如代码中的:return def; 或  return ab(def);

二者是等价的。

结构名作为返回值的时候,返回的是这个结构所包含的所有成员变量。

 

④结构在函数中的使用方式:

像使用单体变量那样使用函数,如 函数名.变量名 这样。

只不过结构名作为参数的时候,导入的是这个结构变量的所有成员。

 

以下是以结构作为参数进行传递的代码:

#include<iostream>
#include<string>
#include<ctime>
#include<Windows.h>
using namespace std;

struct shuxing	//shuxing是类型名
{
	string name;
	int str;
};

shuxing heti(shuxing, shuxing);

int main()
{
	cout << "你和你的伙伴遇见一个强大的boss,现在你们需要合体来战胜他!" << endl;
	cout << "请输入你的姓名:";
	shuxing player_1;	//声明使用shuxing的结构player_1
	getline(cin, player_1.name);	//读取一整行,避免因为空格而导致读取的名字不完全
	cout << "系统正在测试你的体格";
	for (int i = 0;i < 5;i++)	//等待0.5*5秒
	{
		cout << ".";
		Sleep(500);
	}
	cout << endl;
	player_1.str = clock() % 100;	//随机一个属性,利用求余,范围为0~99
	cout << "你的体格为:" << player_1.str << endl;
	cout << "————————————" << endl;
	cout << "请输入你的伙伴的姓名:";
	shuxing player_2;
	getline(cin, player_2.name);
	cout << "系统正在测试你的伙伴的体格";
	for (int i = 0;i < 5;i++)
	{
		cout << ".";
		Sleep(500);
	}
	cout << endl;
	player_2.str = clock() % 100;
	cout << "你的伙伴的体格为:" << player_2.str << endl;
	cout << "现在你们俩进行合体ing";
	for (int i = 0;i < 5;i++)
	{
		cout << ".";
		Sleep(500);
	}
	shuxing bigger = heti(player_1, player_2);	//结构bigger为函数调用2个参数后的返回值
	cout << "你们已经合体完毕!\n合体后的名字为:" << bigger.name << endl;
	cout << "合体后的体格为:" << bigger.str << endl;
	cout << "请点击任意键与boss战斗" << endl;
	cin.sync();	//清除输入缓存
	cin.get();	//从而利用读取任意输入来达成等待的目的
	cout << "战斗完毕,你们胜利了!\n游戏结束" << endl;
	system("pause");
	return 0;
}

shuxing heti(shuxing player_1, shuxing player_2)
{
	shuxing sum;	//声明结构sum,计划为两个结构的之和
	sum.str = player_1.str + player_2.str;
	sum.name = player_1.name + "*" + player_2.name;
	return sum;
}

输出:


你和你的伙伴遇见一个强大的boss,现在你们需要合体来战胜他!
请输入你的姓名:wd
系统正在测试你的体格.....
你的体格为:43
————————————
请输入你的伙伴的姓名:dw
系统正在测试你的伙伴的体格.....
你的伙伴的体格为:8
现在你们俩进行合体ing.....你们已经合体完毕!
合体后的名字为:wd*dw
合体后的体格为:51
请点击任意键与boss战斗

战斗完毕,你们胜利了!
游戏结束
请按任意键继续. . .

总结:

string类型可以直接相加;

 

②可以把返回结构的函数,直接赋值给一个已被初始化的结构——因为结构可以赋给另外一个结构(只要他们使用同一个定义的结构);

如把:shuxing bigger = heti(player_1, player_2);

改成:player_1 = heti(player_1, player_2);

 

 

坐标、角度、弧度之间互相转换的代码:

#include<iostream>
#include<cmath>	//数学库,sqrt()是开方,atan2(y,x)可以求坐标x,y和原地之间的弧度值。
#include<Windows.h>

using namespace std;
struct rect	//坐标的结构,使用横坐标x和纵坐标y
{
	double x;
	double y;
};

struct jiaodu
{
	double distance;
	double jiao;
};

struct polar //使用弧度的结构,内容分别为弧度、点距离原点的距离
{
	double distance;	//距离
	double angle;	//弧度
};

rect polar_to_rect(polar);	//弧度转坐标
rect jiaodu_to_rect(jiaodu);	//角度转坐标
polar jiao_to_polar(jiaodu m);	//角度转弧度
jiaodu rect_to_jiaodu(rect);	//坐标转角度

int main()
{
	cout << "这里可以在坐标、角度、弧度之间任意转换和输出转换后的结果。" << endl;
	cout << "请输入你要输入的内容:\n1.坐标\n2.角度和距离\n3.弧度和距离。" << endl;
	char choice;
	cin >> choice;
	rect x_y;	//结构,坐标相关
	polar d_a;	//结构,弧度相关
	jiaodu d_j;	//结构,角度相关
	while (choice!='1'&&choice!='2'&&choice!='3')
	{
		cout << "输入错误,请重新输入:";
		cin.sync();
		cin >> choice;
	}
	switch (choice)
	{
	case'1':cout << "请输入x坐标:";
		cin >> x_y.x;
		cout << "请输入y坐标:";
		cin >> x_y.y;	//获得坐标
		break;
	case'2':cout << "请输入角度(单位:°):";
		cin >> d_j.jiao;
		cout << "请输入距离:";
		cin >> d_j.distance;
		x_y = jiaodu_to_rect(d_j);	//将输入的内容转为坐标
		break;
	case'3':cout << "请输入弧度(单位:rad):";
		cin >> d_a.angle;
		cout << "请输入距离:";
		cin >> d_a.distance;
		x_y = polar_to_rect(d_a);	//将输入的内容转为坐标
		break;
	}
	cout << "计算ing";
	d_j = rect_to_jiaodu(x_y);	//调用函数,将坐标转为角度
	d_a = jiao_to_polar(d_j);	//将角度转为弧度
	for (int i = 0;i < 5;i++)
	{
		cout << ".";
		Sleep(200);
	}
	cin.sync();	//清除输入缓存
	cout << "请选择你想要显示的结果:" << endl;
	cout << "1.全部\n2.x,y坐标\n3.角度和距离\n4.弧度和距离\n-->> ";
	char choice_2;
	cin >> choice_2;
	while (cin)
	{
		switch (choice_2)
		{
		case'1':
		case'2':cout << "x坐标为:" << x_y.x << "  y坐标为:" << x_y.y << endl;
			if (choice_2 != '1')break;
		case'3':cout << "距离为:" << d_j.distance << "  角度为:" << d_j.jiao << "°" << endl;
			if (choice_2 != '1')break;
		case'4':cout << "距离为:" << d_a.distance << "  弧度为:" << d_a.angle << " rad  " << endl;
		default:if (choice_2 == '1')break;cout << "输入错误,请重新输入:";cin >> choice_2;continue;
		}
		break;	//若无意外,则离开循环
	}
	system("pause");
	return 0;
}

rect polar_to_rect(polar p)	//弧度转坐标
{
	rect dian;
	//sin角度=对边/斜边。
	dian.y = sin(p.angle)*p.distance;	//对边(y) = sin角度*斜边。
	dian.x = cos(p.angle)*p.distance;	//临边(x) = sin角度*斜边
	return dian;
}
rect jiaodu_to_rect(jiaodu p)	//角度转坐标
{
	rect dian;
	const double jiao_to_angle = 57.29577951;	//角度/弧度的值大概是这个数
	double hudu = p.jiao/jiao_to_angle;	//角度除以这个值得到弧度
	dian.y = sin(hudu)*p.distance;	//对边(y) = sin弧度*斜边。
	dian.x = cos(hudu)*p.distance;	//临边(x) = sin弧度*斜边
	return dian;
}
polar jiao_to_polar(jiaodu m)	//角度转弧度
{
	polar dian;
	dian.distance = m.distance;	//距离是一样的
	const double jiao_to_angle = 57.29577951;	//角度/弧度的值大概是这个数
	dian.angle = m.jiao / jiao_to_angle;	//角度除以这个数=弧度值
	return dian;		//返回polar结构(弧度)
}
jiaodu rect_to_jiaodu(rect m)	//坐标转角度
{
	jiaodu dian;
	const double jiao_to_angle = 57.29577951;	//角度/弧度的值大概是这个数
	dian.distance = sqrt(m.x*m.x + m.y*m.y);	//利用坐标求距离
	dian.jiao = atan2(m.y, m.x)*jiao_to_angle;	//利用坐标求角度
	return dian;	//返回jiaodu结构(角度)
}

以上函数可以自由选择输入哪个类型的数据,然后决定输出哪个类型的结果(或者输出全部结果)。

 

注意:

①计算时使用的是弧度,而不是角度;

 

②由于码代码时没有理解,所以最后两个函数并非最优化。

应该为坐标转弧度的函数优先,然后再弧度转角度。

而非是代码中的坐标转角度、在角度转弧度。


结构指针、函数:

函数也可以将 结构指针 作为参数,或者返回值。

作为参数时的格式:void 函数名(结构类型*变量名)

作为返回值时:结构类型*函数名(传递的参数)

如代码:

#include<iostream>
#include<string>
using namespace std;

struct shuxing	//结构,属性
{
	string name;
	int str;
	int def;
	int hp;
	int mp;
	int luck;
	int gold;
};
shuxing*wanjia(void);	//返回值是结构地址(指针)
void combat(shuxing*);	//导入数据为指针,无返回值

int main()
{
	shuxing *player_1=wanjia();	//让玩家输入自己的属性
	cout << "现在开始计算你的战斗力..." << endl << endl;
	combat(player_1);	//计算战斗力,并输出
	system("pause");
	return 0;
}

shuxing*wanjia(void)	//返回结构指针,无传递的参数
{
	shuxing *player = new shuxing;
	cout << "这里是战斗力计算器,请输入你的名字:";
	getline(cin, player->name);	//因为是指针,所以需要用->符号
	cout << "请输入攻击力:";
	cin >> player->str;
	cout << "请输入防御力:";
	cin >> player->def;
	cout << "请输入生命值:";
	cin >> player->hp;
	cout << "请输入魔法值:";
	cin >> player->mp;
	cout << "请输入幸运:";
	cin >> player->luck;
	cout << "请输入金钱:";
	cin >> player->gold;
	return player;
}

void combat(shuxing *player)	//参数是结构指针,无返回值
{
	int zhandouli;
	zhandouli = (player->str * 5 + player->def * 2 + player->hp * 1 + player->mp*0.8)*(player->luck / 30 + 1) + player->gold*0.001;
	cout << player->name << "的战斗力为:" << zhandouli << endl;
}

注意:

①当结构的变量通过指针使用时,需要使用运算符“->”或者是“(*指针名).结构变量名”,如player->str;

 

②当传递的参数为指针(结构地址)时,除了使用指针名之外,还可以直接使用“&结构名”作为参数,即在结构名前加上地址运算符“&”;

例如,将

shuxing *player_1=wanjia(); //注意,这里返回的是 结构指针

combat(player_1);

改为:

shuxing player_1=wanjia(); //注意,这里返回的是 结构

combat(&player_1); //结构名前加上地址运算符&

 

就第二个函数combat而言,效果是一样的,只不过前者是传递一个结构指针,后者是传递了一个结构地址。

 


相关实践学习
快速体验PolarDB开源数据库
本实验环境已内置PostgreSQL数据库以及PolarDB开源数据库:PolarDB PostgreSQL版和PolarDB分布式版,支持一键拉起使用,方便各位开发者学习使用。
目录
相关文章
|
数据可视化 C# C++
工业基础类IFC—提取模型结构树
工业基础类IFC—提取模型结构树
工业基础类IFC—提取模型结构树
|
5月前
|
存储 编译器 C语言
C primer plus 学习笔记 第14章 结构和其他数据形式
C primer plus 学习笔记 第14章 结构和其他数据形式
[Eigen中文文档] 编写以特征类型为参数的函数(一)
Eigen使用表达式模板的方式导致每个表达式的类型可能都不同。如果将这样的表达式传递给一个需要Matrix类型参数的函数,则表达式将隐式地被评估为一个临时Matrix,然后再传递给函数。这意味着失去了表达式模板的好处。
139 0
|
存储 编译器
[Eigen中文文档] 编写以特征类型为参数的函数(二)
Eigen使用表达式模板的方式导致每个表达式的类型可能都不同。如果将这样的表达式传递给一个需要Matrix类型参数的函数,则表达式将隐式地被评估为一个临时Matrix,然后再传递给函数。这意味着失去了表达式模板的好处。
82 0
|
存储 数据处理 对象存储
R语言-稀疏矩阵对象格式介绍&重构方法
在单细胞领域,基于稀疏矩阵对于处理 scRNA-seq 表达谱数据这类大型数据是非常必要的,因为构建分析对象的时候稀疏矩阵相比稠密矩阵拥有更高的数据处理效率和速度。本文重点介绍 在R语言平台关于 Matrix包中Sparse Matrix对象的格式, 与Dense Matrix的转换以及重构方法。
487 0
R语言-稀疏矩阵对象格式介绍&重构方法
|
存储 C语言
《C和指针》读书笔记(第十章 结构和联合)(下)
《C和指针》读书笔记(第十章 结构和联合)(下)
|
存储 C语言 C++
《C和指针》读书笔记(第十章 结构和联合)(上)
《C和指针》读书笔记(第十章 结构和联合)(上)
什么是调用结构?西门子S7-1200的调用结构如何使用?
今天我们来介绍一下西门子S7-1200的调用结构。在西门子S7-1200中采用调用结构来描述用户程序中块的调用层级,调用结构提供了几个方面的信息,包括所用的块,对其它块的调用,各块之间的关系,每个块的数据要求以及块的状态等
什么是调用结构?西门子S7-1200的调用结构如何使用?
|
Python
Python经典编程习题100例:第87例:结构体变量传递
Python经典编程习题100例:第87例:结构体变量传递
98 0
|
Go 索引
数组、切片、映射【我的go学习第六课】
数组、切片、映射【我的go学习第六课】
77 0