c++ --- 通讯录管理系统(多文档编程、文件操作、链表)
·
节点关系
node.h
#pragma once
class MM;
class Node{
public:
Node();
Node(MM *data);
Node(MM *data,Node* next);
Node*& getNext(); //返回指针的引用,用于访问它里面的指针
MM*& getData(); //提供公有接口,用于访问它里面的数据
protected:
MM *data;
Node* next;
};
node.cpp
.h要避免头文件包含(避免头文件的重复包含)---在.cpp中包含头文件即可
头插法实现数据插入---新插入的数据在最前面

#include "node.h" //用到了Node节点,需要包含头文件node.h
#include "mm.h"
Node::Node()
{
this->next = nullptr;//无参构造函数 直接把指针置为空
}
Node::Node(MM* data)
{
this->data = data; //把数据做初始化,再把指针置为空或统一采用初始化参数列表的方式
this->next = nullptr;
}
Node::Node(MM* data, Node* next)
{
this->data = data;
this->next = next;
}
Node*& Node::getNext()
{
return next;
}
MM*& Node::getData()
{
// TODO: 在此处插入 return 语句
return data;
}
实现链表增删改查
list.h
#pragma once
#include "mm.h"
#include "node.h"
//无头链表:表头存数据(这里实现的是有头链表操作)
//有头链表:表头不存数据
class list
{
public:
list();
void insertList(MM* data); //采用头插法插入数据
void printList(); //打印链表中的数据
void deleteAppoin(string posData); //删除链表中的数据,根据姓名做删除
Node* searchByData(string posData); //查找链表中的数据,根据姓名做查找
void saveListToFile(const char* fileName); //文件操作,把链表的数据流到文件中
void readFileToList(const char* fileName); //把文件的数据流到链表中
protected:
Node* headNode;
int curSize; //当前节点个数
};
list.cpp
删除表头,要改变表头的指向 第一个节点是要删除的节点要 单独处理
处理删除表头的情况
-
记录当前节点的(表头)下一个节点
-
释放表头

//删除的是表头
Node* nextNode = curNode->getNext();
delete headNode;
headNode = nextNode;
this->curSize--; //删除成功改变size
处理删除链表中某个数据的情况

//删除链表中的数据
preNode->getNext() = curNode->getNext();
delete curNode;
curNode = nullptr;
this->curSize--; //删除成功改变size
list.cpp
#include "list.h"
#include <iostream>
using namespace std;
list::list()
{
this->headNode = nullptr;
this->curSize = 0;
}
//头插法
void list::insertList(MM* data)
{
//表头插入
headNode = new Node(data, headNode);
this->curSize++;
}
//打印链表
void list::printList()
{
Node* pmove = headNode;
cout << "name" << "\t" << "age" << "\t" << "tel" << "\t" << "sex" << endl;
while (pmove != nullptr)
{
//cout << pmove->getData() << endl;
pmove->getData()->printMM();
pmove = pmove->getNext();
}
}
//删除链表
void list::deleteAppoin(string posData)
{
Node* preNode = headNode;
Node* curNode = headNode;
while (curNode!=nullptr&&curNode->getData()->getName() != posData)
{
preNode = curNode;
curNode = curNode->getNext();
}
if (curNode == nullptr) //如果链表为空,说明没找到
{
cout << "删除失败!" << endl;
}
else if (curNode == preNode) //删除的节点是第一个节点,代表删除表头
{
Node* nextNode = curNode->getNext();
delete headNode;
headNode = nextNode;
this->curSize--;
}
else
{
preNode->getNext() = curNode->getNext();
delete curNode;
curNode = nullptr;
this->curSize--; //删除成功改变size
}
}
//查找链表中数据
Node* list::searchByData(string posData)
{
Node* pmove = headNode;
while (pmove!=nullptr&&pmove->getData()->getName() != posData)
{
pmove = pmove->getNext();
}
return pmove;
}
//文件操作---从链表流入文件
void list::saveListToFile(const char* fileName)
{
fstream save(fileName, ios::out);
Node* pmove = headNode;
while (pmove != nullptr)
{
pmove->getData()->saveFile(save);
pmove = pmove->getNext();
}
save.close();
}
//文件操作---从文件流入链表
void list::readFileToList(const char* fileName)
{
fstream read(fileName, ios::in);
while (1)
{
MM* mm = new MM;
mm->readFile(read);
if (read.eof())
break;
insertList(mm);
}
read.close();
}
文件操作解析
-
所有数据存在链表中,对链表做封装文件操作
-
代码中做了数据的修改的地方,就要做一下文件的保存操作---修改成功后、插入、删除
pList->saveListToFile("1.txt");
//文件操作---从链表流入文件 写
void list::saveListToFile(const char* fileName)
{
fstream save(fileName, ios::out);
Node* pmove = headNode;
while (pmove != nullptr)
{
pmove->getData()->saveFile(save); //直接调用saveFile()
pmove = pmove->getNext();
}
save.close();
}
//文件操作---从文件流入链表 读
void list::readFileToList(const char* fileName)
{
fstream read(fileName, ios::in);
while (1)
{
//因为存的是指针,所以每个数据都要new一个对象出来,要有无参构造函数
MM* mm = new MM;
mm->readFile(read);//把数据读到链表中去
//最后一个读取不应该把数据读到链表中(多读了一次),否则会有乱码
if (read.eof())
break;
insertList(mm); //把对象存到链表中去
}
read.close();
}
测试链表的代码
int main()
{
list myList; //或者new一个对象出来
//插入3个数据
for(int i=0;i<3;i++){
myList.insert[i];//需要手动写析构函数
}
myList.printlist(); //打印数据
}
mm.h---通讯录中包含的人物数据:
-
单独描述成一个类
-
提供一些方法能够打印对象,能够打印数据
注意:
-
需要改链表存储数据的类型---管理的是MM类的数据
-
链表的删除、查找 由(通过数据做查找)改为 通过姓名做删除、查找
mm.h
#pragma once
class MM;
class Node{
public:
Node();
Node(MM *data);
Node(MM *data,Node* next);
Node*& getNext();
MM*& getData();
protected:
MM *data; //如果用MM data需要包含头文件#include "mm.h" 否则会报错
Node* next;
};
//用指针MM* 不会报错 指针只是声明作用 创建对象要已经存在要有创建的过程
mm.h
#pragma once
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class MM
{
public:
MM(string name, int age, string tel, string sex);
MM();
void printMM();
void saveFile(fstream& file); //把链表中的数据存到文件中--->流进去
void readFile(fstream& file); //读取文件的数据到链表--->流出来
string& getName();
int& getAge();
string& getTel();
string& getSex();
protected:
string name; //通讯录的数据
int age;
string tel;
string sex;
};
mm.cpp
#include "mm.h"
MM::MM(string name, int age, string tel, string sex):name(name),age(age),tel(tel),sex(sex)
{
}
MM::MM()
{
}
void MM::printMM()
{
cout << name << "\t" << age << "\t" << tel << "\t" << sex << endl;
}
void MM::saveFile(fstream& file) //提供保存数据的接口
{
file << name << " " << age << " " << tel << " " << sex << endl; //直接把数据流到文件中
}
void MM::readFile(fstream& file)
{
file >> name >> age >> tel >> sex; //分别流到name,age中,流出来忽视空格
}
string& MM::getName()
{
return name;
}
int& MM::getAge()
{
// TODO: 在此处插入 return 语句
return age;
}
string& MM::getTel()
{
// TODO: 在此处插入 return 语句
return tel;
}
string& MM::getSex()
{
// TODO: 在此处插入 return 语句
return sex;
}
MMSystem.h---实现通讯录人物增删改查功能的函数
#pragma once
#include "list.h"
class MMSystem
{
public:
MMSystem();
void MakeMenu(); //菜单
void KeyDown(); //交互处理
void insertMM(); //插入数据(查找数据、删除数据也可以封装成函数)
list*& getPList(); //提供接口访问属性pList
protected:
list* pList;
};
在当前文件夹中新建一个1.txt 文本文档---用于处理链表流出来的数据和把数据流到链表中
MMSystem.cpp
#include "MMsystem.h"
MMSystem::MMSystem():pList(new list) //类的组合:以另一个对象为数据成员
{
pList->readFileToList("1.txt"); //对象创建完后要把存在1.txt中的数据加载到链表中
}
void MMSystem::MakeMenu()
{
cout << "----------------【通讯录】------------------" << endl;
cout << "\t\t0.退出系统" << endl;
cout << "\t\t1.插入数据" << endl;
cout << "\t\t2.删除数据" << endl;
cout << "\t\t3.查找数据" << endl;
cout << "\t\t4.修改数据" << endl;
cout << "\t\t5.浏览数据" << endl;
cout << "--------------------------------------------" << endl;
}
void MMSystem::KeyDown()
{
int userKey = 0;
//new对象准备的变量
string name;
Node* result; //准备一个指针变量,因为返回的是一个指针变量
cin >> userKey;
switch (userKey)
{
case 0:
exit(0);
break;
case 1:
this->insertMM();
pList->saveListToFile("1.txt");
break;
case 2:
cout << "请输入需要删除的姓名:"; //这里可以封装成函数处理,类似 insertMM();
cin >> name;
pList->deleteAppoin(name);
pList->saveListToFile("1.txt");
break;
case 3:
cout << "请输入需要查找的姓名:";
cin >> name;
result = pList->searchByData(name);
if (result == nullptr)
{
cout << "查无此人!" << endl;
}
else
{
cout << "查找信息如下:" << endl;
result->getData()->printMM();
}
break;
case 4:
cout << "请输入要修改的姓名:";
cin >> name;
result = pList->searchByData(name); //通过姓名做查找
if (result == nullptr)
{
cout << "查无此人!无法修改" << endl;
}
else
{
cout << "请输入修改的信息:" << endl;
cin >> result->getData()->getName()
>> result->getData()->getAge()
>> result->getData()->getTel()
>> result->getData()->getSex();
cout << "修改成功" << endl;
pList->saveListToFile("1.txt");
}
break;
case 5:
pList->printList();
break;
}
}
void MMSystem::insertMM() //new对象准备的变量
{
string name;
int age;
string tel; //电话
string sex; //性别
cout << "请分别输入姓名、年龄、电话号码、性别:" << endl;
cin >> name >> age >> tel >> sex;
pList->insertList(new MM(name, age, tel, sex));
}
list*& MMSystem::getPList()
{
// TODO: 在此处插入 return 语句
return pList;
}
c++管理系统.cpp---主函数部分
#include "MMsystem.h"
#include <cstdlib>
int main()
{
MMSystem* pSystem = new MMSystem;
while (1)
{
pSystem->MakeMenu();
pSystem->KeyDown();
system("pause");
system("cls");
}
return 0;
}
更多推荐




所有评论(0)