节点关系
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
删除表头,要改变表头的指向 第一个节点是要删除的节点要 单独处理
处理删除表头的情况:
1. 记录当前节点的(表头)下一个节点 2. 释放表头
//删除的是表头
Node* nextNode = curNode->getNext();
delete headNode;
headNode = nextNode;
this->curSize--; //删除成功改变size
处理删除链表中某个数据的情况:
//删除链表中的数据
preNode->getNext() = curNode->getNext();
delete curNode;
curNode = nullptr;
this->curSize--; //删除成功改变size
#include "list.h" #includeusing 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)
{
MM* mm = new MM; //因为存的是指针,所以每个数据都要new一个对象出来,要有无参构造函数
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类的数据
链表的删除、查找 由(通过数据做查找)改为 通过姓名做删除、查找
#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* 不会报错, 指针只是声明一下,创建对象要已经存在,对象要有创建的过程
#pragma once #include#include #include 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 << "tt0.退出系统" << endl;
cout << "tt1.插入数据" << endl;
cout << "tt2.删除数据" << endl;
cout << "tt3.查找数据" << endl;
cout << "tt4.修改数据" << endl;
cout << "tt5.浏览数据" << 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" #includeint main() { MMSystem* pSystem = new MMSystem; while (1) { pSystem->MakeMenu(); pSystem->KeyDown(); system("pause"); system("cls"); } return 0; }



