c++基础之智能婚恋系统

文章目录

    • 设计思路
    • 成果展示
    • 代码相关设计
    • 小结

设计思路

例如:

1.项目总体需求分析:根据用户信息实现类似相亲网站上的男女匹配功能

2.项目功能设计:

        用户参数设计:本项目男生设计三个参数——姓名,年龄,薪资

                                女生设计三个参数——姓名,年龄,颜值

        信息导入功能:

                a.首次使用,则用户通过控制台输入存储男女信息(用户也可直接创建txt文件进行信息录入,保证文件的名字一致即可)

                b.二次使用,直接读取txt文件中的信息进行操作

        自动匹配功能:系统根据男女信息参数进行匹配,并打印出全部配对结果,筛选出 彼此满意的异性信息

成果展示

        所有会员信息展示

        全部配对的结果

                       

        

         最满意的配对情况

        

代码相关设计

    类的设计

  • 根据用户分为男人和女人分别设计男人类Boy和女人类Girl
  • 男人类女人类有共同的特性,因此根据继承的思想设计父类Single
  • 系统整体的运行需要控制,设计一个控制类Database,进行信息的导入和全匹配以及最优匹配
  • 整体设计思想:先将整体的接口和模块设计出来,然后再设计具体细节,不足之处进行补充

父类:Single.h

#pragma once
#include <iostream>
#include <vector>
using namespace std;

//boy和girl的父类
//男孩和女孩的共有属性 姓名和年龄

class Single {
public:
	Single(string name, int age); //构造函数

	string getName()const; //获取姓名
	int getAge()const;//获取年龄

	virtual int trait()const = 0; //虚函数  特性

protected:
	string name;
	int age;
};

Single.c

#include "Single.h"

Single::Single(string name = "", int age = 0)
	: name(name), age(age) {}

string Single::getName()const {
	return name;
}
int Single::getAge()const {
	return age;
}

男孩类:Boy.h 

#pragma once
#include <iostream>
#include <vector>
#include "Single.h"
using namespace std;
class Girl;

class Boy :public Single {  //继承父类
public:
	Boy(string name, int age, int salary); //构造函数

	int trait()const {   //男孩子特性返回薪水
		return salary;
	}
	bool satisfied(const Girl& girl)const;  //男孩子对女孩子是否满意

	bool operator>(const Boy& boy)const; 

	static void inputBoys(vector<Boy>& boys);//控制台中转至容器,容器中转至文件

	friend ostream& operator<<(ostream& os, const Boy& boy);//友元函数
private:
	int salary;
};
ostream& operator<<(ostream& os, const Boy& boy);

Boy.c

#include "Boy.h"
#include <sstream>
#include <iomanip>
#include "Girl.h"
#define SALARY_COEFFICIENT 0.006  //薪水系数 110000 对应的女孩子颜值是60

//构造函数
Boy::Boy(string name = "", int age = 0, int salary = 0)
	:Single(name, age), salary(salary) {}//若二者合一,则定义新变量时是否需要带括号??必须带括号,因为不存在默认构造函数!

//是否满意
bool Boy::satisfied(const Girl& girl)const  
{
	int satisfiedFaceScore = salary * SALARY_COEFFICIENT;   //计算男孩子满意的颜值
	if (salary * SALARY_COEFFICIENT > 100) satisfiedFaceScore = 100; //bug处理,颜值太高定义为100
	if (girl.trait() >= satisfiedFaceScore) return true; //如果女孩子的特性(颜值) 大于等于 男孩子的满意度,则返回满意
	return false;//否则,不满意
}


bool Boy::operator>(const Boy& boy)const //判断薪水高低  
{
	return salary > boy.salary;
}

void Boy::inputBoys(vector<Boy>& boys) //输入男孩子的信息
{
	int n = 1;
	while (1) {
		string name;
		int age;
		int salary;

		cout << "请输入第" << n << "位小哥哥的姓名(输入0结束):";
		cin >> name;//需要另外定义形参,最后一并通过vector名.push_back存入,push_back意为推到最后面,每次加入的都位于最后,像排队一样
		if (name == "0") break;
		cout << "年龄:";
		cin >> age;
		cout << "月薪:";
		cin >> salary;

		boys.push_back(Boy(name, age, salary));//可不通过类型调用带参构造函数
		n++;
	}
}
//cout << 重载和比较 < 重载   
ostream& operator<<(ostream& os, const Boy& boy) {//直接打印,无需返回stringstream.str()的函数中转
	os << "男 姓名:" << setw(9) << left << boy.name
		<< " 年龄:" << setw(4) << boy.age
		<< "月薪:" << boy.salary << endl;
	return os;
}

女孩类 Girl.h

#pragma once
#include <iostream>
#include <vector> //Vector容器
#include "Single.h"
using namespace std;
class Boy;

class Girl :public Single {
public:
	Girl(string name = "", int age = 0, int faceScore = 0);

	int trait()const {
		return faceScore;
	}
	bool satisfied(const Boy& boy)const;
	bool operator>(const Girl& girl)const;
	friend ostream& operator<<(ostream& os, const Girl& girl);

	static void inputGirls(vector<Girl>& girls);

private:
	int faceScore;//颜值
};
ostream& operator<<(ostream& os, const Girl& girl);

Girl.c

#include "Girl.h"
#include <sstream>
#include <iomanip>
#define FACESCORE_COEFFICIENT 100
#include "Boy.h"
Girl::Girl(string name, int age, int faceScore)
	:Single(name, age), faceScore(faceScore) {}

bool Girl::satisfied(const Boy& boy)const
{
	if (boy.trait() >= faceScore * FACESCORE_COEFFICIENT) return true;//因为有boy的方法,所以要包括boy的头文件
	return false;
}

bool Girl::operator>(const Girl& girl)const
{
	return faceScore > girl.faceScore;  //判断颜值高低
}

void Girl::inputGirls(vector<Girl>& girls)
{
	int n = 1;
	while (1) {
		string name;
		int age;
		int faceScore;

		cout << "请输入第" << n << "位小姐姐的姓名(输入0结束):";
		cin >> name;//需要另外定义形参,最后一并通过vector名.push_back存入
		if (name == "0") break; //结束跳出循环
		cout << "年龄:";
		cin >> age;
		cout << "颜值:";
		cin >> faceScore;

		girls.push_back(Girl(name, age, faceScore));//可不通过类型调用带参构造函数

		n++;
	}
}
ostream& operator<<(ostream& os, const Girl& girl) {    //重写<<
	os << "女 姓名:" << setw(9) << left << girl.name//left=setiosflags(ios::left)  //左对齐 设置输出宽度
		<< " 年龄:" << setw(4) << girl.age
		<< "颜值:" << girl.faceScore << endl;
	return os;
}

 控制类Database.h

#pragma once
#include "Boy.h"
#include "Girl.h"

/*
功能:
加载用户信息load()
实现自动配对automatch()
打印配对信息print()
数据:
男信息
女信息
*/

class Database
{
public:
	Database();

	//加载用户信息
	void load(bool input = false) {  
		loadBoys(input);
		loadGirls(input);
	}
	void print() const;//打印boys和allGirls中所有男女信息
	void allMatch() const;  //匹配

	void allBestMatch() const;
	
private:
	vector<Boy> boys;//vector每次用之前需要初始化为0吗?
	vector<Girl>allGirls;
	vector<Boy> newBoys;
	vector<Girl> newGirls;

	void loadBoys(bool input);//将文件中加载至vector
	void loadGirls(bool input);

	void saveBoys(const vector<Boy>& boys);//将vector中存入文件
	void saveGirls(const vector<Girl>& allGirls);

	void automatchBoy(const vector<Boy>& boys, const vector<Girl>& allGirls) const;
	void automatchGirl(const vector<Boy>& boys, const vector<Girl>& allGirls) const;

	void bestMatchBoy(const vector<Boy>& boys, const vector<Girl>& allGirls) const;
	void bestMatchGirl(const vector<Boy>& boys, const vector<Girl>& allGirls) const;
};

Database.c

#include <fstream>
#include <string>
#include "Database.h"
#define BOY_FILE "boys.txt"
#define GIRL_FILE "girls.txt"
#define BOY_INPUT_INFO 3	//男士输入数据数目(姓名,年龄,月薪)
#define GIRL_INPUT_INFO 3	//女士输入数据数目(姓名,年龄,颜值)
string line(100, '-');

Database::Database()
{
}
void Database::allMatch() const {
	cout << line << endl;
	cout << "全部单身男女自动配对结果:" << endl;
	automatchBoy(boys, allGirls);
	cout << line << endl;
	automatchGirl(boys, allGirls);
	cout << line << endl;
}
void Database::allBestMatch() const
{
	cout << line << endl;
	cout << "全部单身男女最佳配对结果:" << endl;
	bestMatchBoy(boys, allGirls);
	cout << line << endl;
	bestMatchGirl(boys, allGirls);
	cout << line << endl;
}



void Database::bestMatchBoy(const vector<Boy>& boys, const vector<Girl>& allGirls) const {
	for (unsigned int b = 0; b < boys.size(); b++) {
		cout << boys[b] << " 的最佳配对女士为:" << endl;
		const Girl* bestGirl = NULL;
		for (unsigned int g = 0; g < allGirls.size(); g++) {
			if (boys[b].satisfied(allGirls[g]) == true &&
				allGirls[g].satisfied(boys[b]) == true) {//注意调用的是否是函数以及函数是否含参以及含参顺序
				//cout << boys[b].getName() << "<-->" << allGirls[g].getName() << endl;如果只打印姓名,可能有重名,无法确定实际是哪位
				//因为database与Boy和Girl类不存在继承关系,所以只能通过对象调用public方法
				if (!bestGirl) {
					bestGirl = &allGirls[g];
				}
				else if (allGirls[g] > *bestGirl) {
					bestGirl = &allGirls[g];
				}
			}
		}
		if (bestGirl) {
			cout << *bestGirl;
		}
		else {
			cout << "配对失败!" << endl;
		}
		cout << endl;//一位男士的所有配对结束后空一行
	}
}
void Database::bestMatchGirl(const vector<Boy>& boys, const vector<Girl>& allGirls) const {
	for (unsigned int g = 0; g < allGirls.size(); g++) {
		cout << allGirls[g] << " 的最佳配对男士为:" << endl;
		const Boy* bestBoy = NULL;
		for (unsigned int b = 0; b < boys.size(); b++) {
			if (boys[b].satisfied(allGirls[g]) == true &&
				allGirls[g].satisfied(boys[b]) == true) {//注意调用的是否是函数以及函数是否含参以及含参顺序
				//cout << boys[b].getName() << "<-->" << allGirls[g].getName() << endl;如果只打印姓名,可能有重名,无法确定实际是哪位
				//因为database与Boy和Girl类不存在继承关系,所以只能通过对象调用public方法
				if (!bestBoy) {
					bestBoy = &boys[b];
				}
				else if (boys[b] > *bestBoy) {//TO DO <运算符重载
					bestBoy = &boys[b];
				}
			}
		}
		if (bestBoy) {
			cout << *bestBoy;
		}
		else {
			cout << "配对失败!" << endl;
		}
		cout << endl;//一位女士的所有配对结束后空一行
	}
}

void Database::automatchBoy(const vector<Boy>& boys, const vector<Girl>& allGirls)const
{
	//遍历两两配对
	for (unsigned int b = 0; b < boys.size(); b++) {
		cout << boys[b] << " 的配对女士有:" << endl;
		for (unsigned int g = 0; g < allGirls.size(); g++) {
			if (boys[b].satisfied(allGirls[g])
				&& allGirls[g].satisfied(boys[b])) {//注意调用的是否是函数以及函数是否含参以及含参顺序
				//cout << boys[b].getName() << "<-->" << allGirls[g].getName() << endl;如果只打印姓名,可能有重名,无法确定实际是哪位
				//因为database与Boy和Girl类不存在继承关系,所以只能通过对象调用public方法
				cout << allGirls[g];
			}
		}
		cout << endl;//一位男士的所有配对结束后空一行
	}
}
void Database::automatchGirl(const vector<Boy>& boys, const vector<Girl>& allGirls)const
{
	//遍历两两配对
	for (unsigned int g = 0; g < allGirls.size(); g++) {
		cout << allGirls[g] << " 的配对男士有:" << endl;
		for (unsigned int b = 0; b < boys.size(); b++) {
			if (boys[b].satisfied(allGirls[g])
				&& allGirls[g].satisfied(boys[b])) {//注意调用的是否是函数以及函数是否含参以及含参顺序
				//cout << boys[b].getName() << "<-->" << allGirls[g].getName() << endl;如果只打印姓名,可能有重名,无法确定实际是哪位
				//因为database与Boy和Girl类不存在继承关系,所以只能通过对象调用public方法
				cout << boys[b];
			}
		}
		cout << endl;//一位成女士的所有配对结束后空一行
	}
}
void Database::print()const
{
	string line(100, '-');//记得在初始化时这样写

	cout << "男士信息:" << endl;
	for (unsigned int i = 0; i < boys.size(); i++) {
		cout << boys[i];
	}

	cout << "女士信息:" << endl;
	for (unsigned int i = 0; i < allGirls.size(); i++) {
		cout << allGirls[i];
	}

	cout << line << endl;
}

void Database::loadBoys(bool input)
{
	//打开读文件
	ifstream boyfile;
	boyfile.open(BOY_FILE);
	if (!boyfile.is_open()) {
		//还没有此文件名的文件,需要用户输入,作为基础信息,存入vector->vector.vector中已有,不需要再从文件中读取
		Boy::inputBoys(this->newBoys);

		//将vector中的基础信息以description中的格式写入新建的文件,并结束加载
		saveBoys(newBoys);
		boyfile.close();
		return;
	}
	if (input) {
		Boy::inputBoys(this->newBoys);
		saveBoys(newBoys);
	}
	while (1) {

		//将读文件信息解析??为啥要解析嘞??已经存好了的啊,,是为了显示出来吗,要显示出来可以直接按存入的vector显示吗?不能
		//因为vector掉电即失,需写入文件中转
		//sscanf读取字符串会自动跳过回车符
		//根据写的格式读取文件
		/*ret << "男 姓名:" << setw(9) << left << name
			<< " 年龄:" << setw(4) << age
			<< "月薪:" << salary << endl;*/
		string line;
		getline(boyfile, line);
		if (boyfile.eof()) {
			break;
		}

		char name[32] = "";
		int age, salary;
		int ret = sscanf_s(line.c_str(), "男 姓名:%s 年龄:%d 月薪:%d", name, sizeof(name), &age, &salary);
		if (ret < BOY_INPUT_INFO) {
			cerr << "男士信息写入有误!" << endl;
			exit(1);//视项目需求:break/exit
		}

		//并加载至vector以供后续配对
		boys.push_back(Boy(name, age, salary));//string存入时最后记得加\0结束符,因为读取的时候要用char型读取,可以不加,因为格式里面专门加了空格隔开

	}
	boyfile.close();

}
//inputGirls:控制台->vector
//saveGirls:vector->文件
void Database::loadGirls(bool input)
{
	ifstream girlfile;
	girlfile.open(GIRL_FILE);

	// 还没有此文件,需要用户输入基础信息
	if (!girlfile.is_open()) {
		Girl::inputGirls(this->newGirls);
		//将输入的基础信息以description中的格式保存至文件尾部
		saveGirls(newGirls);
		girlfile.close();
		return;
	}
	// 用户希望输入新信息
	if (input) {
		Girl::inputGirls(this->newGirls);
		//将输入的基础信息以description中的格式保存至文件尾部
		saveGirls(newGirls);
	}

	while (1) {

		//将读文件信息解析??为啥要解析嘞??已经存好了的啊,,是为了显示出来吗,要显示出来可以直接按存入的vector显示吗?不能
		//因为vector掉电即失,需写入文件中转
		//sscanf读取字符串会自动跳过回车符
		//根据写的格式读取文件
		/*	ret << "女 姓名:" << setw(9) << left << name
				<< " 年龄:" << setw(4) << age
				<< "颜值:" << faceScore << endl;*/
		string line;
		getline(girlfile, line);
		if (girlfile.eof()) {
			break;
		}

		char name[32] = "";
		int age, faceScore;
		int ret = sscanf_s(line.c_str(), "女 姓名:%s 年龄:%d 颜值:%d", name, sizeof(name), &age, &faceScore);
		if (ret < GIRL_INPUT_INFO) {
			cerr << "女士信息写入有误!" << endl;
			exit(1);//视项目需求:break/exit
		}

		//并加载至vector以供后续配对
		allGirls.push_back(Girl(name, age, faceScore));//string存入时最后记得加\0结束符,因为读取的时候要用char型读取,可以不加,因为格式里面专门加了空格隔开

	}
	girlfile.close();

}

void Database::saveBoys(const vector<Boy>& boys)
{
	ofstream boyfile;
	boyfile.open(BOY_FILE, ios::app);//尾部附加
	if (!boyfile.is_open()) {
		cerr << "写入:男士文件打开失败!" << endl;
		exit(1);//exit还是break按项目需求
	}

	for (unsigned int i = 0; i < boys.size(); i++) {
		boyfile << boys[i];
	}

	boyfile.close();
}

void Database::saveGirls(const vector<Girl>& allGirls)
{
	ofstream girlfile;
	girlfile.open(GIRL_FILE, ios::app);
	if (!girlfile.is_open()) {
		cerr << "写入:女士文件打开失败!" << endl;
		exit(-1);
	}

	for (unsigned int i = 0; i < allGirls.size(); i++) {
		girlfile << allGirls[i];
	}

	girlfile.close();
}

主函数 main.c

#include <iostream>
#include"Boy.h"
#include"Girl.h"
#include<vector>
#include "Database.h"

using namespace std;


int main() {
	Database database;
	database.load();
	database.print();
	database.allMatch();
	database.allBestMatch();


	return 0;
}

小结

本项目是C++的入门项目,主要的基于面向对象的思想,运用了C++的继承、重载,容器,友元函数等知识,初学者可以多加练习。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值