C++实验5 结构体和指针

实验五 结构体和指针

1 实验目的

(1)学习如何使用结构体的指针作为函数的参数,通过传地址的方式,在
被调用函数中修改主调函数中的多个结构体变量的方法。
(2)学习如何把逻辑结构相同的部分抽象为函数,以提高代码的可重用性,
达到提高程序的可维护性的目的。

2 实验内容

2.1 模拟画图功能

(1)问题描述

模拟计算机的画图功能,能够模拟画圆和长方形的功能。程序主要功能如下:
① 提供一个如下的主菜单。


  1. Circle (圆)
  2. Rectangle (长方形)
  3. Exit (退出)

② 不断接受用户的选择(整数),直至用户选择 0 为止。如果用户输入了系
统尚未支持的选择(比如 3),则给出相应的提示信息,并继续选择。
③ 如果用户选择了圆或长方形,则进一步提示用户输入两个点,分别称为
起点和终点,如下图所示。坐标仅考虑正整数的情况。要求终点的坐标
大于起点的坐标,否则给出相关的提示信息并返回主菜单。
在这里插入图片描述

④ 模拟画出圆和长方形。画圆时,要计算 startPoint 和 endPoint 所构成的正
方形的内切圆的圆心和半径。若 startPoint 和 endPoint 所构成的不是正方
形,则给出相关的提示信息并返回主菜单。

(2)问题要求

① 定义一个 Point 结构体,用来表示显示屏上的点;
② 实现以下函数(图 2),使得主程序(图 3)输出图 4 中的结果。
图 2. 需要实现的函数雏形
主程序如图 3 所示。
图 3. 主程序
运行结果如图 4 所示。
在这里插入图片描述
在这里插入图片描述
注意,上述结果未能列出所有可能的执行情况。请认真思考,相关的提示信
息应该分别在由哪些函数中输出?

源代码

#include <iostream>

using namespace std;

struct Point {
	int x; // 横坐标
	int y; // 纵坐标
};

void printPoint(const struct Point * p) {
	cout << "(" << p->x << ", " << p->y << ")";
}

// 得到用户输入的两个点
void getTwoPoints(struct Point *startP, struct Point *endP) {
	cout << "Please input the coordinate (x, y) of the start point: ";
	cin >> (startP->x);
	cin >> (startP->y);

	cout << "Please input the coordinate (x, y) of the end point: ";
	cin >> endP->x;
	cin >> endP->y;
}

// 显示主菜单
void displayMenu() {
	cout << "*******************************\n";
	cout << "    1. Circle (圆)\n";
	cout << "    2. Rectangle (长方形)\n";
	cout << "    0. Exit (退出)\n";
	cout << "*******************************\n";
	cout << "Please select the shape: ";
}

// 根据用户给出的起点和终点,画圆
bool drawCircleAd(struct Point *startP, struct Point *endP) {
	struct Point center; // 圆心坐标
	int radius; // 半径

	if ((endP->x - startP->x) != (endP->y - startP->y)) {
		cout << "Not a circle, please input two points again!\n";
		return false;
	} else {
		center.x = (startP->x + endP->x) / 2; // 计算圆心横坐标
		center.y = (startP->y + endP->y) / 2; // 计算圆心纵坐标
		radius = (endP->x - startP->x) / 2; // 计算半径

		// 模拟画圆
		cout << "Draw a circle at center ";
		printPoint(&center);
		cout << " with radius " << radius << endl;
		return true;
	}
}

// 根据用户给出的起点和终点,画长方形
bool drawRectangleAd(struct Point *startP, struct Point *endP) {
	int width, height;

	width = endP->x - startP->x; // 长
	height = endP->y - startP->y; // 宽

	if (width <= 0 || height <= 0) {
		cout << "Not a rectangle, please input two points again!\n";
		return false;
	}
	// 模拟画长方形
	cout << "Draw a rectangle at topleft ";
	printPoint(startP);
	cout << ", whose width is " << width << " and height is " << height << endl;
	return true;

}

int main() {
	int choice = 1; // 用户选择

	struct Point startP; // 起点
	struct Point endP; // 终点
	bool flag = false;

	while (choice) {
		displayMenu();
		cin >> choice;

		flag = false;
		while (!flag) {
			switch (choice) {
			case 1:
				getTwoPoints(&startP, &endP);
				flag = drawCircleAd(&startP, &endP);
				break;
			case 2:
				getTwoPoints(&startP, &endP);
				flag = drawRectangleAd(&startP, &endP);
				break;
			case 0:
				cout << "Good Bye!\n";
				flag = true;
				break;
			default:
				cout << "Error Input! Please select again!\n";
				flag = true;
				break;
			}
		}
	}

	return 0;
}

// 根据用户给出的起点和终点,画圆
void drawCircle(struct Point *startP, struct Point *endP) {
	struct Point center; // 圆心坐标
	int radius; // 半径

	if ((endP->x - startP->x) != (endP->y - startP->y))
		cout << "Not a circle, Select again\n";
	else {
		center.x = (startP->x + endP->x) >> 1; // 计算圆心横坐标
		center.y = (startP->y + endP->y) >> 1; // 计算圆心纵坐标
		radius = (endP->x - startP->x) >> 1; // 计算半径

		// 模拟画圆
		cout << "Draw a circle at center ";
		printPoint(&center);
		cout << " with radius " << radius << endl;
	}

}

// 根据用户给出的起点和终点,画长方形
void drawRectangle(struct Point *startP, struct Point *endP) {
	int width, height;

	width = endP->x - startP->x; // 长
	height = endP->y - startP->y; // 宽

	// 模拟画长方形
	cout << "Draw a rectangle at topleft ";
	printPoint(startP);
	cout << ", whose width is " << width << " and height is " << height << endl;

}

void ShapesMain() {
	int choice = 1; // 用户选择

	struct Point startP; // 起点
	struct Point endP; // 终点

	while (choice) {
		displayMenu();
		cin >> choice;

		switch (choice) {
		case 1:
			getTwoPoints(&startP, &endP);
			drawCircle(&startP, &endP);
			break;
		case 2:
			getTwoPoints(&startP, &endP);
			drawRectangle(&startP, &endP);
			break;
		case 0:
			cout << "Good Bye!\n";
			break;
		default:
			cout << "Error Input! Please select again!\n";
			break;
		}
	}
}

2.2 计算所得税

(1)问题描述

一个国家计算所得税的规则由如下的不确定多条规则构成:
在这里插入图片描述
其中,n 是规则的条数,由用户输入。对于任意的 , 表示个人收入中在区间 的部分的税率,它是一个整数,代表百分之几。 为税率起征点, 。

(2)问题要求

① 请定义一个结构体,用来存放一条规则。

② 根据用户输入的规则条数,使用结构体的数组存放所有的规则。
③ 定义一个子函数 inputRules(struct Rule rules[], int n),根据用户输入的规则
条数,从键盘得到所有规则,存放至数组。
④ 定义一个子函数计算所得税。
// 参数 income 表示个人收入
double computeTax(struct Rule rules[], int n, int income);
⑤ 在主函数中,一次录入规则后,可以循环计算任意多个人的所得税,直
到输入的收入为-1 为止。
⑥ 请至少测试以下情况

  • 输入规则后,在录入收入时,直接录入-1;
  • 收入为 0;
  • 收入小于 ;
  • 收入等于 的各种情况;
  • 收入大于 ;
  • 收入在 和 之间的情况。

(3)程序运行要求

程序的一次运行结果如下:

请输入规则的条数:3
请输入第 1 条规则:800 3
请输入第 2 条规则:2000 4
请输入第 3 条规则:5000 3

纳税规则如下:
纳税线 税率
800 3
2000 4
5000 3

请输入您的收入:0
您的收入是:0,应缴所得税:0.00 元。

请输入您的收入:800
您的收入是:800,应缴所得税:0.00 元。

请输入您的收入:801
您的收入是:801,应缴所得税:0.03 元。

请输入您的收入:2000
您的收入是:2000,应缴所得税:36.00 元。(2000 – 800)* 3/100

请输入您的收入:1999
您的收入是:1999,应缴所得税:35.97 元。

请输入您的收入:5000
您的收入是:5000,应缴所得税:156.00 元。[(2000 – 800)*3+(5000 –
2000)*4]/100
请输入您的收入:10000
您的收入是:10000,应缴所得税:306.00 元。[(2000 – 800)*3+(5000 –
2000)*4+(10000 – 5000)*3] / 100

请输入您的收入:-1
再见
请按任意键继续…

源代码

#include <iostream>
#include <iomanip>

using namespace std;

struct TaxRule {
	int baseLine; // 纳税线
	int rate; // 税率
};

// 静态全局变量,指向征税规则的指针,仅在本cpp文件内全局有效
static struct TaxRule* taxRules;
// 静态全局变量,征税规则的条数,仅在本cpp文件内全局有效
static int ruleNum = 0;

void setRules(); // 从用户输入获得征税规则
void displayRules(); // 显示征税规则
double compTax(int); // 计算给定收入的所得税

// 从键盘输入纳税规则
void setRules() {
	// 获得规则的条数
	cout << "请输入规则的条数:";
	cin >> ruleNum;

	// 生成指定条数的规则
	taxRules = new struct TaxRule[ruleNum];

	// 获得用户输入的规则
	for (int i = 0; i < ruleNum; i++) {
		cout << "请输入第 " << (i + 1) << " 条规则:";
		cin >> taxRules[i].baseLine >> taxRules[i].rate;
	}
}

// 显示规则
void displayRules() {
	cout << "\n纳税规则如下:\n";
	cout << "纳税线\t税率\n";
	for (int i = 0; i < ruleNum; i++) {
		cout << taxRules[i].baseLine << "\t\t" << taxRules[i].rate << endl;
	}
}

// 计算纳税金额
double compTax(int income) {
	double sum = 0.0;
	int i = 0;

	if (taxRules[0].baseLine > income)
		return 0.0;

	// 逐次检查每一个纳税线,直到检查完说有纳税线或者找到一个比输入大的纳税线。
	// 在此过程中,累加两个相邻纳税线之间的税额。
	for (i = 1; i < ruleNum && taxRules[i].baseLine <= income; i++) {
		//累加计算纳税金额。为了提高速度,税率先不除以100.
		sum = sum + (taxRules[i].baseLine - taxRules[i - 1].baseLine) * taxRules[i - 1].rate;
	}

	// for循环结束时,要么找到了某个大于income的纳税线,
	// 要么所有纳税线都比income小。
	// 不管是哪种情况,都看income超过前一个纳税线多少。
	// 如果所有纳税线都比income小,此时i和ruleNum相等,
	// 我们就可以把最后一个纳税线看作前一个纳税线。
	int remains = income - taxRules[i - 1].baseLine;

	// 将超出部分按前一个纳税线计算纳税金额
	sum = sum + remains * taxRules[i - 1].rate;

	// 最后计算所得的税额除以100
	return sum / 100;
}

/**
 * 计算所得税的主类。
 * 与TaxRule类之间是依赖关系。因为其main方法通过局部变量使用了TaxRule的实例。
 * @author Jianliang Xu
 *
 */
int main() {
	setRules();
	// 显示规则
	displayRules();

	// 存放用户输入的收入金额的局部变量
	int income = 0;

	// 接受用户的输入并计算所得税
	while (true) {
		cout << "\n请输入您的收入:";
		cin >> income;
		if (income == -1) {
			cout << "Good Bye!!" << endl;
			break;
		}
		cout << "您的收入是:" << income << "," << "应缴所得税:" << setprecision(2) << fixed << compTax(income) << "元。" << endl;
	}
	return 0;
}

发布了172 篇原创文章 · 获赞 81 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/weixin_43074474/article/details/104683018
今日推荐