单链表实现学生健康系统:c++类模板

用单链表实现学生健康情况管理的几个操作功能(新建、插入、删除、从文件读取、写入文件和查询、屏幕输出等功能)。健康表中学生的信息有学号、姓名、出生日期、性别、身体状况等。

目录

关键词

1)建立结点类模板

2)建立链表类模板

3)定义一系列链表操作

4)定义学生结构体类型

5)各功能函数

完整代码实现


关键词

链式结构 类模板 结构体 文件输入输出

1)建立结点类模板

//声明单链表类模板
template <class Type> class List;

//定义链表结点类模板
template <class Type> 
class ListNode {
private:
	friend class List<Type>;//单链表类是链表结点类的友元类
	Type data; //结点数据域 
	ListNode<Type> * next; //结点指针域
public:
	ListNode() :next(NULL) { }
	ListNode(Type& item) :data(item), next(NULL) {}
	//建立一个新结点
	ListNode<Type>* CreateNode(Type& item, ListNode<Type>* next = NULL);
	//取得结点中数据
	Type GetData() { return data; }
	//取得结点中指针值
	ListNode<Type>* GetPointer() { return next; }
	//设置结点的data值
	void SetDate(Type value) { data = value; }
	//修改结点的指针值
	void SetPointer(ListNode<Type>* nextT) { next = nextT; }
};

其中建立新结点时要与后一个结点连接

//建立一个新结点
template <class Type>
ListNode<Type>* ListNode<Type>::CreateNode(Type& item, ListNode<Type>* next ) {

	ListNode<Type>* newNode = new ListNode<Type>(item);
	// 将当前结点后面的结点接在新建结点上
	newNode->next = next;
	return newNode;
}

2)建立链表类模板

写入结点类模板为友元函数

//定义单链表类模板
template <class Type> class List {
private:
	//链表的表头指针和当前结点指针
	ListNode<Type>* first, * current;
public:
	//构造带头结点的单链表(空表)
	List(){ //头结点无数据
		first = current = new ListNode<Type>;
	}
	~List(){
		MakeEmpty();//置空表 
		delete first, current;
	}
	void MakeEmpty();//将链表置空
	int Length() const;	//计算链表的长度
	ListNode<Type>* Firster() {  return first; }//返回头结点地址
	ListNode<Type>* Find(Type value); //搜索含数据value的结点并置为当前结点
	Type GetData(); //获得当前结点的数据
	void Insert(Type value); //插入数据
	void RemoveCurrentNode(Type value); //将链表当前结点删去
	Type* Next();//获得当前结点后继的数据域地址
	bool IsEmpty(){//判断表空
		return Length() == 0 ? true : false;
	}
	void Dispaly();//输出链表
};

3)定义一系列链表操作

链表置空

//链表置空
template <class Type>  
void List<Type>::MakeEmpty(){
	//删去链表中除表头结点外的所有其他结点
	ListNode<Type>* q;
	while (first->next != NULL) {
		q = first->next;
		first->next = q->next;
		delete q;
	}
	current = first;
}

计算链表长度

//获取表长
template <class Type>
int List<Type>::Length() const{
	ListNode<Type>* p = first->next;
	int count = 0;
	while (p != NULL) {
		count++;
		p = p->next;
	}
	return count;
}

插入结点

//插入数据 尾插法
template<class Type>
void List<Type>::Insert(Type value) {
	if (current == NULL) {
		cout << "插入失败!" << endl;
		return;
	}
	ListNode<Type>* newNode = current->CreateNode(value, current->next);
	current = current->next = newNode;
	cout << "插入成功!" << endl;
	return;
}

搜索结点

//搜索含数据value的结点并返回该结点
template <class Type>
ListNode<Type>* List<Type>::Find(Type value){
	ListNode<Type>* p = first->next;
	while (p) {
		if (p->data == value) break;
		else p = p->next;
	}
	return p;
}

删除结点:用到搜索结点的函数

//将链表当前结点删去
template <class Type>
void List<Type>::RemoveCurrentNode(Type value){
	if (current == first) {
		cout << "表空,无可删除数据" << endl;
		return;
	}
	ListNode<Type>* p = Find(value);
	ListNode<Type>* prior = first;
	//寻找当前元素的前驱元素结点
	while (prior->next != p)
		prior = prior->next;
	prior->next = p->next;
	delete p;
	cout << "删除成功!" << endl;
	return;
}

输出链表所有值。

//显示输出链表
template <class Type>
void List<Type>::Dispaly() {
	ListNode<Type>* p = current;
	current = first->next;
	while (current) {
		cout << current->data << " ";
		current = current->next;
	}
	cout << endl;
	current = p;
}

4)定义学生结构体类型

转换为类模板中的类型,结构体的输入输出等运算符进行重载,便于数据的读写操作

//学生结构体
typedef struct student {
	int num;
	char name[10];
	string birth;
	string sex;
	string body;
	//重载运算符
	friend istream& operator >> (istream& is, student& t) {
		is >> t.num >> t.name >> t.birth >> t.sex >> t.body;
		return is;
	}
	friend ostream& operator << (ostream& os, student& t) {
		os << t.num << '\t' << t.name << '\t' << t.birth << '\t' << t.sex << '\t' << t.body << endl;
		return os;
	}
	bool operator ==(const student& t) {
		return this->num == t.num;
	}
	bool operator !=(const student& t) {
		return this->num != t.num;
	}
}stutype;

5)各功能函数

这里只放文件读写操作函数

//从文件中读取信息
void readfile() {
	ifstream ifs("student.txt");  //读取文件
	if (!ifs.good()) {
		cerr << "ifstream open file error!\n";
		return;
	}
	string line;
	vector<string> lines;
	while (getline(ifs, line)) {
		lines.push_back(line);   //将每一行依次存入到vector中
		cout << line << endl;    //顺便打印一下这一行
	}
	ifs.close();
	return;
}

文件写入时遇到一个问题:运行时会报错为显示p为空指针,加上判断p为空则返回即可,解决方法参考的是这个哥的http://t.csdnimg.cn/sl8vp 感恩

void infile() {
	fstream fout("student.txt", ios::out | ios::app);
	if (fout.fail()) {
		cout << "文件打开失败" << endl;
		exit(0);
	}
	ListNode<stutype> * p = stu.Firster();
	p = p->GetPointer();
	while (p) {
		fout << p->GetData().num << '\t' << p->GetData().name << '\t' << p->GetData().birth 
			<< '\t' << p->GetData().sex << '\t' << p->GetData().body << endl;
		p = p->GetPointer();
		if (p == NULL) break;
	}
	fout.close();
	cout << "写入成功!" << endl;
	return;
}

完整代码实现

#include <iostream>
using namespace std;
#include<string>
#include<fstream>
#include<vector>

//声明单链表类模板
template <class Type> class List;

//定义链表结点类模板
template <class Type> 
class ListNode {
private:
	friend class List<Type>;//单链表类是链表结点类的友元类
	Type data; //结点数据域 
	ListNode<Type> * next; //结点指针域
public:
	ListNode() :next(NULL) { }
	ListNode(Type& item) :data(item), next(NULL) {}
	//建立一个新结点
	ListNode<Type>* CreateNode(Type& item, ListNode<Type>* next = NULL);
	//取得结点中数据
	Type GetData() { return data; }
	//取得结点中指针值
	ListNode<Type>* GetPointer() { return next; }
	//设置结点的data值
	void SetDate(Type value) { data = value; }
	//修改结点的指针值
	void SetPointer(ListNode<Type>* nextT) { next = nextT; }
};
//建立一个新结点
template <class Type>
ListNode<Type>* ListNode<Type>::CreateNode(Type& item, ListNode<Type>* next ) {

	ListNode<Type>* newNode = new ListNode<Type>(item);
	// 将当前结点后面的结点接在新建结点上
	newNode->next = next;
	return newNode;
}
//定义单链表类模板
template <class Type> class List {
private:
	//链表的表头指针和当前结点指针
	ListNode<Type>* first, * current;
public:
	//构造带头结点的单链表(空表)
	List(){ //头结点无数据
		first = current = new ListNode<Type>;
	}
	~List(){
		MakeEmpty();//置空表 
		delete first, current;
	}
	void MakeEmpty();//将链表置空
	int Length() const;	//计算链表的长度
	ListNode<Type>* Firster() {  return first; }//返回头结点地址
	ListNode<Type>* Find(Type value); //搜索含数据value的结点并置为当前结点
	Type GetData(); //获得当前结点的数据
	void Insert(Type value); //插入数据
	void RemoveCurrentNode(Type value); //将链表当前结点删去
	Type* Next();//获得当前结点后继的数据域地址
	bool IsEmpty(){//判断表空
		return Length() == 0 ? true : false;
	}
	void Dispaly();//输出链表
};
//链表置空
template <class Type>  
void List<Type>::MakeEmpty(){
	//删去链表中除表头结点外的所有其他结点
	ListNode<Type>* q;
	while (first->next != NULL) {
		q = first->next;
		first->next = q->next;
		delete q;
	}
	current = first;
}
//获取表长
template <class Type>
int List<Type>::Length() const{
	ListNode<Type>* p = first->next;
	int count = 0;
	while (p != NULL) {
		count++;
		p = p->next;
	}
	return count;
}
//插入数据 尾插法
template<class Type>
void List<Type>::Insert(Type value) {
	if (current == NULL) {
		cout << "插入失败!" << endl;
		return;
	}
	ListNode<Type>* newNode = current->CreateNode(value, current->next);
	current = current->next = newNode;
	cout << "插入成功!" << endl;
	return;
}
//获得当前结点的数据域的地址
template <class Type>
Type List<Type>::GetData(){
	if (current == NULL)
		return NULL;
	else
		return current->GetData();
}

//搜索含数据value的结点并返回该结点
template <class Type>
ListNode<Type>* List<Type>::Find(Type value){
	ListNode<Type>* p = first->next;
	while (p) {
		if (p->data == value) break;
		else p = p->next;
	}
	return p;
}

//将链表当前结点删去
template <class Type>
void List<Type>::RemoveCurrentNode(Type value){
	if (current == first) {
		cout << "表空,无可删除数据" << endl;
		return;
	}
	ListNode<Type>* p = Find(value);
	ListNode<Type>* prior = first;
	//寻找当前元素的前驱元素结点
	while (prior->next != p)
		prior = prior->next;
	prior->next = p->next;
	delete p;
	cout << "删除成功!" << endl;
	return;
}

//获得当前结点后继的数据域地址
template <class Type>
Type* List<Type>::Next(){
	if (current == NULL || current->next == NULL)
		return NULL;
	current = current->next;
	return current->GetData();
}

//显示输出链表
template <class Type>
void List<Type>::Dispaly() {
	ListNode<Type>* p = current;
	current = first->next;
	while (current) {
		cout << current->data << " ";
		current = current->next;
	}
	cout << endl;
	current = p;
}

//学生结构体
typedef struct student {
	int num;
	char name[10];
	string birth;
	string sex;
	string body;
	//重载运算符
	friend istream& operator >> (istream& is, student& t) {
		is >> t.num >> t.name >> t.birth >> t.sex >> t.body;
		return is;
	}
	friend ostream& operator << (ostream& os, student& t) {
		os << t.num << '\t' << t.name << '\t' << t.birth << '\t' << t.sex << '\t' << t.body << endl;
		return os;
	}
	bool operator ==(const student& t) {
		return this->num == t.num;
	}
	bool operator !=(const student& t) {
		return this->num != t.num;
	}
}stutype;

List<stutype> stu;//新建
void meau() {
	cout << "1------新建学生健康表" << endl
		<< "2------向学生健康表插入学生信息" << endl
		<< "3------在健康表删除学生信息" << endl
		<< "4------从文件中读取健康表信息" << endl
		<< "5------向文件写入学生健康表信息" << endl
		<< "6------在健康表中查询学生信息(按学生学号来进行查找)" << endl
		<< "7------在屏幕中输出全部学生信息" << endl
		<< "8------退出" << endl
		<< "请输入需要使用的功能:";
	return;
}
//从文件中读取信息
void readfile() {
	ifstream ifs("student.txt");  //读取文件
	if (!ifs.good()) {
		cerr << "ifstream open file error!\n";
		return;
	}
	string line;
	vector<string> lines;
	while (getline(ifs, line)) {
		lines.push_back(line);   //将每一行依次存入到vector中
		cout << line << endl;    //顺便打印一下这一行
	}
	ifs.close();
	return;
}
//向文件写入信息
void infile() {
	fstream fout("student.txt", ios::out | ios::app);
	if (fout.fail()) {
		cout << "文件打开失败" << endl;
		exit(0);
	}
	ListNode<stutype> * p = stu.Firster();
	p = p->GetPointer();
	while (p) {
		fout << p->GetData().num << '\t' << p->GetData().name << '\t' << p->GetData().birth 
			<< '\t' << p->GetData().sex << '\t' << p->GetData().body << endl;
		p = p->GetPointer();
		if (p == NULL) break;
	}
	fout.close();
	cout << "写入成功!" << endl;
	return;
}
//插入学生信息
void instu() {
	student data;
	cout << "请依次输入要插入的学生学号、姓名、出生日期、性别、身体状况:(使用空格间隔)" << endl;
	cin >> data;
	stu.Insert(data);
	return;
}
//删除学生信息
void delstu() {
	student data;
	cout << "请输入要删除的学生学号:";
	cin >> data.num;
	stu.RemoveCurrentNode(data);
	return;
}
//查询学生信息
void findstu() {
	student data;
	cout << "请输入要查询的学生学号:";
	cin >> data.num;
	if (stu.Find(data) == NULL) cout << "查无此人" << endl;
	else {
		student o = stu.Find(data)->GetData();
		cout << o;
	}
	return;
}
//输出所有学生信息
void showstu() {
	stu.Dispaly();
	return;
}

int main() {
	int a;
	while (true) {
		meau();
		cin >> a;
		switch (a) {
		case 1:
			cout << "学生表已建立,请返回菜单进行插入数据操作!" << endl;
			break;
		case 2:
			//插入学生信息
			instu();
			break;
		case 3:
			//删除学生信息
			delstu();
			break;
		case 4:
			//文件中读取信息
			readfile();
			break;
		case 5:
			//文件中写入信息
			infile();
			break;
		case 6:
			//查询学生信息 学号查询
			findstu();
			break;
		case 7:
			//输出所有学生信息
			showstu();
			break;
		case 8:
			//推出
			return 0;
		default:
			cout << "请重新输入:";
		}
		system("pause");
		system("cls");
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值