C/C++ 基于设计模式,利用多态实现同学通讯录系统

如何挖掘代码中的要点并展开 ?

2020-0908
通常学习C++我们都会学习一些设计模式,
最早我想利用设计模式对此通讯录进行改写,以便增强可维护性和满足开闭原则
被老师拒绝了,毕竟此代码量不高,1000行以内 确实没必要。
此项目其实最能挖掘的点应该是 “动态数组” ,STL库其实有这一概念,不过我就不多说了。

2020-0806
这并不是一个完整的项目,个人感觉还需要QT界面等等。

main.cpp

#include <iostream>
#include "Contact.h"
using namespace std;

int main(void)
{
	funcClass user;
	int choice = 0; 
	while (true)	
	{
		user.funcMenu();
		cout << "请输入您的选择:\n";
		cin >> choice;
		switch (choice)
		{
		case 0:						// 0.退出通讯录
			user.funcExit();
			break;
		case 1:						// 1.添加联系人
			user.addContacts();
			break;
		case 2:						// 2.删除联系人
			user.DelContacts();
			break;
		case 3:						// 3.修改联系人
			user.modContacts();
			break;
		case 4:						// 4.查找联系人
			user.findContacts();
			break;
		case 5:						// 5.显示联系人
			user.showContacts();
			break;
		case 6:						// 6.排序联系人
			user.sortContacts();
		case 7:						// 7.清空联系人
			user.cleanFile();
			break;
		default:
			system("cls");
			break;
		}
	}
	return 0;
}

Contact.h

#pragma once //防止头文件重复

#include <iostream>
#include <string>

using namespace std;

class Contacts
{
public:
	virtual void showInfo() = 0;//显示联系人信息

	string name;			//同学姓名
	string addr;			//家庭住址
	string phone;			//联系电话
	string workfor;			//工作单位
};

class newContacts :public Contacts
{
public:
	//构造函数 传入的信息,需传四个
	newContacts(string name, string addr, string phone, string workfor);

	void showInfo();		//重写 显示个人信息(不加virtual也可以)
};

// 功能实现类
class funcClass
{
public:
	funcClass();

	int m_num;				//记录通讯录人数
	Contacts** m_cttArray;	//通讯录 数组指针
	bool m_fileIsEmpty;		//判断文件是否为空 标志

	void funcMenu();		// 展示功能菜单函数	
	
	void funcExit();		// 退出通讯录系统
	
	void addContacts();		// 添加联系人
	
	void fileSave();		//文件保存
	
	int getNum();			//统计文件中人数
	
	void init();			//初始化
	
	void showContacts();	//显示联系人

	void DelContacts();		//删除联系人

	int IsExit(string name);//判断联系人是否存在 存在返回在数组中的位置,不存在返回-1

	void modContacts();		//修改联系人信息

	void findContacts();	//按已有信息查找 

	void sortContacts();	//按照姓名排序

	void cleanFile();		//清空文件

	~funcClass();
};

Contact.cpp

#include <iostream>
#include <fstream>
#include <cstring>
#include "Contact.h"
using namespace std;

#define FILENAME "phone.txt"

//构造函数 传入的信息,需传四个
newContacts::newContacts(string name, string addr, string phone, string workfor)
{
	this->name = name;
	this->addr = addr;
	this->phone = phone;
	this->workfor = workfor;
}
// 显示个人信息
void newContacts::showInfo()
{
	cout << "同学姓名:" << this->name
		<< "\t家庭住址:" << this->addr
		<< "\t联系电话:" << this->phone
		<< "\t工作单位:" << this->workfor << endl;
}

funcClass::funcClass()
{
	//1.文件不存在
	ifstream fi;
	fi.open(FILENAME, ios::in); //读文件

	if (!fi.is_open())
	{	//初始化属性
		//初始化记录人数
		this->m_num = 0;
		//初始化数组指针
		this->m_cttArray = nullptr;
		//初始化文件是否为空
		this->m_fileIsEmpty = true;
		fi.close();
		return;
	}
	//2.文件存在但数据为空
	char ch;
	fi >> ch;
	if (fi.eof())
	{
		//初始化记录人数
		this->m_num = 0;
		//初始化数组指针
		this->m_cttArray = nullptr;
		//初始化文件是否为空
		this->m_fileIsEmpty = true;
		fi.close();
		return;
	}
	//3.当文件存在,且保存联系人数据
	int num = this->getNum();
	this->m_num = num;

	//开辟空间
	this->m_cttArray = new Contacts * [this->m_num];
	//将文件中的数据,存到数组中
	this->init();
}

// 展示功能菜单函数
void funcClass::funcMenu()
{
	cout << "0.退出通讯录\n";
	cout << "1.添加联系人\n";
	cout << "2.删除联系人\n";
	cout << "3.修改联系人\n";
	cout << "4.查找联系人\n";
	cout << "5.显示联系人\n";
	cout << "6.排序联系人\n";
	cout << "7.清空联系人\n";
}
// 退出通讯录系统
void funcClass::funcExit()
{
	cout << "欢迎下次使用!\n";
	system("pause");	// 按键退出
	exit(0);			// 退出程序
}
void funcClass::addContacts()
{
	cout << "请输入添加联系人数量:\n";

	int addNum = 0; //保存用户的输入数量
	cin >> addNum;
	if (addNum > 0)
	{
		//添加
		//计算添加新空间大小
		int newSize = this->m_num + addNum; //新空间人数 = 原来记录人数+新增人数
		
		//开辟新空间
		Contacts ** newSpace = new Contacts* [newSize];

		//将原来空间下的数据,拷贝到新空间下
		if (this->m_cttArray != nullptr)
		{
			for (int i = 0; i < this->m_num; i++)
			{
				newSpace[i] = this->m_cttArray[i];
			}
		}
		//批量添加新数据
		for (int i = 0; i < addNum; i++)
		{
			string name; //同学姓名
			string addr; //家庭住址
			string phone; //联系电话
			string workfor; //工作单位
			
			cout << "请输入第" << i + 1 << "个同学的姓名" << endl;
			cin >> name;
			cout << "请输入第" << i + 1 << "个同学的家庭住址" << endl;
			cin >> addr;
			cout << "请输入第" << i + 1 << "个同学的联系电话" << endl;
			cin >> phone;
			cout << "请输入第" << i + 1 << "个同学的工作单位" << endl;
			cin >> workfor;

			Contacts* contact = new newContacts(name, addr, phone, workfor);
	
			//创建联系人,保存到数组中
			newSpace[this->m_num + i] = contact;

		}
		//释放原有空间
		delete[]this->m_cttArray;

		//更改新空间指向
		this->m_cttArray = newSpace;

		//更新 通讯录人数
		this->m_num = newSize;

		//更新 部位空标识符
		this->m_fileIsEmpty = false;
		//提示添加成功
		cout << "成功添加" << addNum << "名新的同学" << endl;

		//保存数据到文件中
		this->fileSave();
	}
	else
	{
		cout << "您的输入有误,请重新输入\n";
	}
	//按任意键后 清屏回到上级目录
	system("pause");
	system("cls");

}

// 文件保存
void funcClass::fileSave()
{
	ofstream fo;
	fo.open(FILENAME, ios::out);//用输出的方式打开文件 -- 写文件

	//将每个人的数据写入到文件中
	for (int i = 0; i < this->m_num; i++)
	{
		fo << this->m_cttArray[i]->name << " "
			<< this->m_cttArray[i]->addr << " "
			<< this->m_cttArray[i]->phone << " "
			<< this->m_cttArray[i]->workfor << endl;
	}

	// 关闭文件
	fo.close();
}

//统计文件中人数:
int funcClass::getNum()
{
	ifstream fi;
	fi.open(FILENAME, ios::in);//打开文件 读

	string name;
	string addr;
	string phone;
	string workfor;

	int num = 0;
	while (fi >> name && fi >> addr && fi >> phone && fi >> workfor)
	{
		//统计人数变量
		num++;
	}
	return num;
}

// 初始化
void funcClass::init()
{
	ifstream fi;
	fi.open(FILENAME, ios::in);
	
	string name;
	string addr;
	string phone;
	string workfor;

	int index = 0;
	while (fi >> name && fi >> addr && fi >> phone && fi >> workfor)
	{
		Contacts* contact = new newContacts(name, addr, phone, workfor);
		this->m_cttArray[index] = contact;
		index++;
	}
	//关闭文件
	fi.close();
}
// 显示通讯录信息
void funcClass::showContacts()
{
	//判断文件是否为空
	if (this->m_fileIsEmpty)
	{
		cout << "文件不存在或记录为空!" << endl;
	}
	else
	{
		for (int i = 0; i < m_num; i++)
		{
			//利用多态调用程序接口
			this->m_cttArray[i]->showInfo();
		}
	}
	//按任意键后清屏
	system("pause");
	system("cls");
}

//删除联系人
void funcClass::DelContacts()
{
	if (this->m_fileIsEmpty)
	{
		cout << "文件不存在或记录为空!" << endl;
	}
	else
	{
		//按照联系人姓名删除
		cout << "请输入想要删除联系人姓名: " << endl;
		string name;
		cin >> name;

		int index = this->IsExit(name);
		if (index != -1)//说明联系人存在,并且要删除index位置的联系人
		{
			//数据前移
			for (int i = index; i < this->m_num - 1; i++)
			{
				this->m_cttArray[i] = this->m_cttArray[i + 1];
			}
			this->m_num--;//更新数组中记录人员个数
			this->fileSave();
			cout << "删除成功!" << endl;
		}
		else
		{
			cout << "删除失败,未找到该联系人" << endl;
		}
	}
	//按任意键 清屏
	system("pause");
	system("cls");
}

//判断联系人是否存在 存在返回在数组中的位置,不存在返回-1
int funcClass::IsExit(string name)
{
	int index = -1;
	for (int i = 0; i < this->m_num; i++)
	{
		if (this->m_cttArray[i]->name == name)
		{
			//找到该联系人
			index = i;
			break;
		}
	}

	return index;
}
//修改联系人信息
void funcClass::modContacts()
{
	if (this->m_fileIsEmpty)
	{
		cout << "文件不存在或记录为空!" << endl;
	}
	else
	{
		cout << "请输入修改联系人的姓名: " << endl;
		string name;
		cin >> name;

		int ret = this->IsExit(name);
		if (ret != -1)
		{
			//查找到 姓名存在 的 联系人
			delete this->m_cttArray[ret];
			string newName = nullptr;//新的同学姓名
			string newAddr = nullptr;//新的家庭住址
			string newPhone = nullptr;//新的联系电话
			string newWorkfor = nullptr;//新的工作单位

			cout << "查找到姓名为 " << name << " 的联系人,请输入新的姓名: " << endl;
			cin >> newName;

			cout << "请输入新的家庭地址:" << endl;
			cin >> newAddr;

			cout << "请输入新的联系电话:" << endl;
			cin >> newPhone;

			cout << "请输入新的工作单位:" << endl;
			cin >> newWorkfor;
			
			Contacts* contact = new newContacts(newName, newAddr, newPhone, newWorkfor);
			
			//更新数据 到数组中
			this->m_cttArray[ret] = contact;
			cout << "修改成功!" << endl;

			//保存文件中
			this->fileSave();
		}
		else
		{
			cout << "查无此人,修改失败!" << endl;
		}
	}

	system("pause");
	system("cls");
}

//查找联系人
void funcClass::findContacts()
{
	if (this->m_fileIsEmpty)
	{
		cout << "文件不存在或记录为空!" << endl;
	}
	else
	{
		cout << "请输入查找的方式:" << endl;
		cout << "1.按同学姓名查找 " << endl;
		cout << "2.按家庭住址查找 " << endl;
		cout << "3.按联系电话查找 " << endl;
		cout << "4.按工作单位查找 " << endl;
		int select = 0;
		cin >> select;
		if (select == 1)
		{
			string newName;
			cout << "请输入查找的同学姓名:" << endl;
			cin >> newName;

			//加入判断是否查到的标志
			bool flag = false; //默认未找到该联系人

			for (int i = 0; i < m_num; i++)
			{
				if (this->m_cttArray[i]->name == newName)
				{
					cout << "查找成功,姓名为 " << newName << " 的同学信息如下:" << endl;
					
					flag = true;

					//调用显示信息接口
					this->m_cttArray[i]->showInfo();
				}
			}
			if (flag == false)
			{
				cout << "查找失败,查无此人!" << endl;
			}
		}
		else if (select == 2)
		{
			string newAddr;
			cout << "请输入查找的家庭住址:" << endl;
			cin >> newAddr;

			//加入判断是否查到的标志
			bool flag = false; //默认未找到该联系人

			for (int i = 0; i < m_num; i++)
			{
				if (this->m_cttArray[i]->addr == newAddr)
				{
					cout << "查找成功,家庭住址为 " << newAddr << " 的同学信息如下:" << endl;

					flag = true;

					//调用显示信息接口
					this->m_cttArray[i]->showInfo();
				}
			}
			if (flag == false)
			{
				cout << "查找失败,查无此人!" << endl;
			}
		}
		else if (select == 3)
		{
			string newPhone;
			cout << "请输入查找的联系电话:" << endl;
			cin >> newPhone;

			//加入判断是否查到的标志
			bool flag = false; //默认未找到该联系人

			for (int i = 0; i < m_num; i++)
			{
				if (this->m_cttArray[i]->phone == newPhone)
				{
					cout << "查找成功,联系电话为 " << newPhone << " 的同学信息如下:" << endl;

					flag = true;

					//调用显示信息接口
					this->m_cttArray[i]->showInfo();
				}
			}
			if (flag == false)
			{
				cout << "查找失败,查无此人!" << endl;
			}
		}
		else if (select == 4)
		{
			string newWorkfor;
			cout << "请输入查找的工作单位:" << endl;
			cin >> newWorkfor;

			//加入判断是否查到的标志
			bool flag = false; //默认未找到该联系人

			for (int i = 0; i < m_num; i++)
			{
				if (this->m_cttArray[i]->workfor == newWorkfor)
				{
					cout << "查找成功,工作单位为 " << newWorkfor << " 的同学信息如下:" << endl;

					flag = true;

					//调用显示信息接口
					this->m_cttArray[i]->showInfo();
				}
			}
			if (flag == false)
			{
				cout << "查找失败,查无此人!" << endl;
			}	
		}
		else
		{
			cout << "输入选项有误!" << endl;
		}
	}
	//按任意键清屏
	system("pause");
	system("cls");
}
//按照姓名排序 算法:选择排序(比较好理解的一种排序)
void funcClass::sortContacts()
{
	if (this->m_fileIsEmpty)
	{
		cout << "文件不存在或记录为空!" << endl;
		//按任意键清屏
		system("pause");
		system("cls");
	}
	else
	{
		cout << "请选择排序方式:" << endl;
		cout << "1.按同学姓名进行升序" << endl;
		cout << "2.按同学姓名进行降序" << endl;

		int select = 0;
		cin >> select;
		for (int i = 0; i < m_num; i++)
		{
			int minOrMax = i; //声明最小值 或 最大值 下标
			for (int j = i + 1; j < this->m_num; j++)
			{
				if (select == 1)//升序
				{
					if (this->m_cttArray[minOrMax]->name > this->m_cttArray[j]->name)
					{
						minOrMax = j;
					}
				}
				else  //降序
				{
					if (this->m_cttArray[minOrMax]->name < this->m_cttArray[j]->name)
					{
						minOrMax = j;
					}
				}
			}
			//判断一开始认定 最小值或最大值 是不是 计算的最小值或最大值,如果不是 交换
			if (i != minOrMax)
			{
				Contacts* newContact = this->m_cttArray[i];
				this->m_cttArray[i] = this->m_cttArray[minOrMax];
				this->m_cttArray[minOrMax] = newContact;
			}
		}
		cout << "排序成功!排序后的结果为:" << endl;
		this->fileSave(); //排序后结果保存到文件中
		this->showContacts(); //展示
	}
}
//清空文件
void funcClass::cleanFile()
{
	if (this->m_fileIsEmpty)
	{
		cout << "文件不存在或记录为空!" << endl;
	}
	else
	{
		cout << "确定清空?" << endl;
		cout << "1.确定" << endl;
		cout << "2.返回" << endl;

		int select = 0;
		cin >> select;

		if (select == 1)
		{
			//清空文件
			ofstream fo(FILENAME, ios::trunc);//删除文件后重新创建
			fo.close();

			if (this->m_cttArray != nullptr)
			{
				//删除堆区的 每个 联系人 对象
				for (int i = 0; i < this->m_num; i++)
				{
					delete this->m_cttArray[i];
					this->m_cttArray[i] = nullptr;
				}
				delete[] this->m_cttArray;
				this->m_cttArray = nullptr;
				this->m_num = 0;
				this->m_fileIsEmpty = true;
			}
			cout << "清空成功!" << endl;
		}
	}
	//按任意键清屏
	system("pause");
	system("cls");
}
// 析构函数
funcClass::~funcClass()
{
	if (this->m_cttArray != nullptr)
	{
		for (int i = 0; i < this->m_num; i++)
		{
			if (this->m_cttArray[i] != nullptr)
			{
				delete this->m_cttArray[i];
			}
		}
		delete[] this->m_cttArray;
		this->m_cttArray = nullptr;
	}
}

以前写的 C 实现

  • 如下代码是单链表粗糙实现增删改查。

之前用双向链表写过通讯录了,想着单链表写一下,花了点时间敲了敲。
现在回过头来看,还是不予置评吧。
不过没打算删,放这当黑历史。
还是要继续补基础知识。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node
{
	char name[100];
	char addr[100];
	char phone[100];
	struct Node* next;
}*Pnode;

typedef struct List
{
	Pnode head;//头指针
	Pnode tail;//尾指针
}*Plist;

//初始化链表
Plist createList()
{
	Plist plist = (Plist)malloc(sizeof(struct List));
	if (plist == NULL)
	{
		printf("申请plist空间失败\n");
		return NULL;
	}
	plist->head = (Pnode)malloc(sizeof(struct Node));
	if (plist->head == NULL)
	{
		printf("申请plist->head空间失败\n");
		free(plist);
		return NULL;
	}
	plist->tail = (Pnode)malloc(sizeof(struct Node));
	if (plist->head == NULL)
	{
		printf("申请plist->tail空间失败\n");
		free(plist);
		return NULL;
	}
	plist->tail = NULL;
	plist->head = NULL;
	return plist;
}
//1.添加联系人 功能    //尾插法
void addNode(Plist list)
{
	Pnode newNode = (Pnode)malloc(sizeof(struct Node));
	if (newNode == NULL)
	{
		printf("newNode申请空间失败\n");
		return;
	}
	//填充数据域
	char name[100], addr[100], phone[100];
	printf("输入联系人姓名:");
	scanf_s("%s", name, 100);
	strcpy_s(newNode->name, 100, name);
	printf("输入联系人地址:");
	scanf_s("%s", addr, 100);
	strcpy_s(newNode->addr, 100, addr);
	printf("输入联系人电话号码:");
	scanf_s("%s", phone, 100);
	strcpy_s(newNode->phone, 100, phone);
	//1.空表;2.非空表 两种情况插入
	if (list->head == NULL)
	{
		list->head = newNode;
	}
	else
	{
		list->tail->next = newNode;
	}
	list->tail = newNode;
	newNode->next = NULL;
	system("cls");
	printf("添加联系人成功\n");
}
//获取链表长度
int nodeLen(Plist list)
{
	int len = 0;
	Pnode newNode = list->head;
	while (newNode != NULL)
	{
		len++;
		newNode = newNode->next;
	}
	return len;
}
//2.显示联系人信息功能 
void showNode(Plist list)
{
	Pnode newNode = list->head;
	while (newNode != NULL)
	{
		printf("姓名:%s\t地址:%s\t电话号码:%s\n", newNode->name, newNode->addr, newNode->phone);
		newNode = newNode->next;
	}
}
//通过数据域比较,获取结点地址
Pnode getNode(char name[], Plist newlist)
{
	Pnode newNode = newlist->head;
	while (strcmp(newNode->name, name) != 0)
	{
		newNode = newNode->next;
	}
	return newNode;
}
//遍历获取是第几个链表,返回地址
Pnode getNode2(Plist list, int len)
{
	Pnode newNode = list->head;
	int num = 1;
	while(num!=len)
	{
		num++;
		newNode = newNode->next;
	}
	return newNode;
}
//不知是第几个链表,返回值为 
int getNode3(Plist list, Pnode node)
{
	Pnode newNode = list->head;
	int len = 1;
	while (strcmp(newNode->name,node->name) != 0)
	{
		len++;
		newNode = newNode->next;
	}
	return len;
}
//删除联系人
void delNode(Plist list)
{
	printf("输入您要删除的联系人姓名\n");
	char name[100];
	scanf_s("%s", name, 100);
	Pnode newNode = getNode(name, list);
	int len = nodeLen(list);
	if (list->head == newNode && len == 1)	//删除第一个
	{
		list->head = newNode->next;
	}
	else if (list->tail == newNode)			//删除最后一个
	{
		list->tail = getNode2(list, len - 1);
		list->tail->next = NULL;
	}
	else									//删除中间某一个
	{
		int num = getNode3(list, newNode);
		Pnode node = getNode2(list, num - 1);
		node->next = newNode->next;
	}
	free(newNode);
	system("cls");
	printf("删除成功\n");

}
//4.修改联系人信息
void upDate(Plist list)
{
	printf("请输入你要修改的联系人姓名:\n");
	char name[100];
	scanf_s("%s", name, 100);
	Pnode newNode = getNode(name, list); //获取该链表
	system("cls");
	printf("1.修改姓名\n");
	printf("2.修改地址\n");
	printf("3.修改电话号码\n");
	printf("4.返回菜单\n");
	int key = 0;
	scanf_s("%d", &key);
	switch (key)
	{
		case 1:
			system("cls"); 
			printf("请输入新的姓名:\n");
			char newname[100];
			scanf_s("%s", newname, 100);
			strcpy_s(newNode->name,100,newname);
			printf("修改成功!");
			break;
		case 2:
			system("cls");
			printf("请输入新的地址:\n");
			char newaddr[100];
			scanf_s("%s", newaddr, 100);
			strcpy_s(newNode->addr,100, newaddr);
			printf("修改成功!");
			break;
		case 3:
			system("cls");
			printf("请输入新的电话号码:\n");
			char newphone[100];
			scanf_s("%s", newphone, 100);
			strcpy_s(newNode->phone,100, newphone);
			printf("修改成功!");
		case 4:
			exit(1);
			break;
	}
}

void queryNode(Plist list)
{
	printf("请输入你要查找的联系人姓名:\n");
	char name[100];
	scanf_s("%s", name, 100);
	Pnode newNode = getNode(name, list); //获取该链表
	system("cls");
	printf("姓名:%s\t地址:%s\t电话号码:%s\n", newNode->name, newNode->addr, newNode->phone);
}

//菜单显示
void Menu()
{
	//1.初始化链表
	Plist newlist = createList();
	if (NULL == newlist)
	{
		printf("创建失败\n");
	}
	while (1)
	{
		system("cls");
		printf("\n1.添加新联系人\n");
		printf("2.显示联系人信息\n");
		printf("3.删除联系人\n");
		printf("4.修改联系人信息\n");
		printf("5.查找联系人\n");
		printf("6.退出通讯录\n\n");
		int key = 0;
		scanf_s("%d", &key);
		switch (key)
		{
		case 1:
			system("cls"); addNode(newlist); system("pause");
			break;
		case 2:
			system("cls"); showNode(newlist); system("pause");
			break;
		case 3:
			system("cls"); delNode(newlist); system("pause");
			break;
		case 4:
			system("cls"); upDate(newlist); system("pause");
			break;
		case 5:
			system("cls"); queryNode(newlist); system("pause");
			break;
		case 6:
			exit(1);
			break;
		}
	}
}
// 学海无涯苦作舟,书山有路勤为径。 加油!
int main()
{
	Menu();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/GameStrategist/article/details/107727093