用单链表编程实现一个简易的高校学籍管理系统

【实验题目内容】

用单链表编程实现一个简易高校学籍管理系统并完成报告。
(1)学生信息包括学号、姓名、性别、专业和出生年月等,采用单链表存储方式;
(2)提供建立、查询、删除、增加和更新等功能;
(3)设计主函数中测试各项功能。

【实验环境】(使用的软件):VS - 2010

【项目设计源代码】

//stdafx.h头文件即所需的头文件
#include <iostream>
#include <string>

using namespace std;
// linkNode.h单链表的结点类模板头文件
#pragma once //VS-2010自动生成的代码
// 单链表的结点
// T为单链表中元素的模板类型
template <class T>
class linkNode
{
public:
	// 构造结点
	linkNode(void);
	// 析构结点
	~linkNode(void);
	// 元素
	T data;
	// 后继指针
	linkNode<T>* next;
};

// 构造结点
template <class T>
linkNode<T>::linkNode(void)
{
}

// 析构结点
template <class T>
linkNode<T>::~linkNode(void)
{
}
// LinkList.h单链表类模板头文件
#pragma once
#include "linkNode.h"
// 单链表
// T为单链表中元素的模板类型
template <class T>
class LinkList
{
public:
	// 默认构造函数
	LinkList(void);
	// 析构造函数
	~LinkList(void);
protected:
	// 单链表的头指针
	linkNode<T>* head;
public:
	// 遍历输出单链表
	void Print(void);
	// 根据数组Array中前Count个元素构造新的单链表
	LinkList(T* Array, long Count);
	// 求单链表的长度(元素个数,不包括头结点)
	long Count(void);
	// 如果第position个元素存在,则取出第position
	// 个元素Data,返回true,否则,返回false
	bool getData(long position, T& Data);
	// 搜索元素Data,若找到,则返回其地址current
	// 和前趋地址precursor,并返回true,否则,返回false
	bool Search(T Data, linkNode<T>*& precursor, linkNode<T>*& current);
	// 将原来的元素oldData更新为新元素newData,
	// 更新成功,则返回true,否则,返回false
	bool Update(T oldData, T newData);
	// 在第position个位置插入新元素newData,
	// 若插入成功,则返回true,否则,返回false
	bool Insert(long position, T newData);
	// 删除元素deleteData,删除成功,
	// 则返回true,否则,返回false
	bool Delete(T deleteData);
	// 逆置单链表,逆置成功,则返回true,否则,返回false
	bool Invert(void);
	// 取头结点(地址)
	linkNode<T>* getHead(void);
};

// 默认构造函数
template <class T>
LinkList<T>::LinkList(void)
{
	// 动态分配头结点
	head = new linkNode<T>;
	if(head==NULL)
	{
		cerr<<"分配内存失败。"<<endl;
		exit(1);
	}
	// (空链表)头结点的后继为空
	head->next = NULL;
}

// 析构造函数
template <class T>
LinkList<T>::~LinkList(void)
{
	linkNode<T>* deleteNode,*current=head;
	while(current)
	{
		deleteNode=current;
		current=current->next;
		delete deleteNode;
	}
	head=NULL;
}

// 遍历输出单链表
template <class T>
void LinkList<T>::Print(void)
{
	cout<<"head→[头结点]";
	linkNode<T>* current=head->next;
	while(current!=NULL)
	{
		cout<<"[-]→["<<current->data<<"]";
		current=current->next;
	}
	cout<<"[^]"<<endl;
}

// 根据数组Array中前Count个元素构造新的单链表
template <class T>
LinkList<T>::LinkList(T* Array, long Count)
{
	// 动态分配头结点
	linkNode<T>* rear = head = new linkNode<T>;
	if(rear==NULL)
	{
		cerr<<"分配内存失败。"<<endl;
		exit(1);
	}
	linkNode<T>* current;
	for(long Index=0;Index<Count;Index++)
	{
		current=new linkNode<T>;
		if(current==NULL)
		{
			cerr<<"分配内存失败。"<<endl;
			exit(1);
		}
		rear->next=current;
		current->data=Array[Index];
		rear=rear->next;
	}
	// 链尾的后继为空
	rear->next = NULL;
}

// 求单链表的长度(元素个数,不包括头结点)
template <class T>
long LinkList<T>::Count(void)
{
	linkNode<T>* current=head->next;
	long count=0;
	while(current!=NULL)
	{
		count++;
		current=current->next;
	}
	return count;
}

// 如果第position个元素存在,则取出第position个元素Data,
// 返回true,否则,返回false
template <class T>
bool LinkList<T>::getData(long position, T& Data)
{
	if(position<1)
	{
		return false;
	}
	else
	{
		linkNode<T>* current=head->next;
		for(long count=1;current && (count<position);count++)
		{
			current=current->next;
		}
		if(current)
		{
			Data=current->data;
			return true;
		}
		else
		{
			cerr<<"未找到第"<<position<<"个元素。"<<endl;
			return false;
		}
	}
}

// 搜索元素Data,若找到,则返回其地址current
// 和前趋地址precursor,并返回true,否则,返回false
template <class T>
bool LinkList<T>::Search(T Data, linkNode<T>*& precursor, linkNode<T>*& current)
{
	precursor = head;
	current=head->next;
	if(precursor==NULL || current==NULL)
	{
		return false;
	}
	while(current && current->data!=Data)
	{
		precursor = current;
		current=current->next;
	}
	if(current && current->data==Data)
	{
		return true;
	}
	else
	{
		return false;
	}
}

// 将原来的元素oldData更新为新元素newData,
// 更新成功,则返回true,否则,返回false
template <class T>
bool LinkList<T>::Update(T oldData, T newData)
{
	linkNode<T>* precursor = head;
	linkNode<T>* current=head->next;
	if(Search(oldData,precursor,current))
	{
		// 找到了元素oldData,更新为新元素newData
		current->data=newData;
		return true;
	}
	else
	{
		return false;
	}
}

// 在第position个位置插入新元素newData,若插入成功,
// 则返回true,否则,返回false
template <class T>
bool LinkList<T>::Insert(long position, T newData)
{
	linkNode<T>* current=head;
	long currentPosition=0;
	while(current && currentPosition<position-1)
	{
		current=current->next;
		currentPosition++;
	}
	if(current)
	{
		linkNode<T>* newNode=new linkNode<T>;
		newNode->data=newData;
		newNode->next=current->next;
		current->next=newNode;
		return true;
	}
	else
	{
		return false;
	}
}

// 删除的元素deleteData,删除成功,
// 则返回true,否则,返回false
template <class T>
bool LinkList<T>::Delete(T deleteData)
{
	linkNode<T>* precursor = head;
	linkNode<T>* current=head->next;
	if(Search(deleteData,precursor,current))
	{
		// 找到删除的元素deleteData,使其脱链
		precursor->next=current->next;
		// 释放被删除元素所占的空间
		delete current;
		// 删除成功,返回true
		return true;
	}
	else
	{
		// 未删除的元素deleteData,返回false
		return false;
	}
}

// 逆置单链表,逆置成功,则返回true,否则,返回false
template <class T>
bool LinkList<T>::Invert(void)
{
	if(head==NULL)
	{
		cerr<<"逆置的单链表不存在。"<<endl;
		return false;
	}
	else
	{
		linkNode<T>* first,*current=head->next;
		// 将逆置后的单链表初始化为空表
		head->next=NULL;
		// 遍历单链表中的结点
		while(current)
		{
			first=current;
			current=current->next;
			// 将结点插入到逆置后单链表的表头
			first->next=head->next;
			head->next=first;
		}
		return true;
	}
}

// 取头结点(地址)
template <class T>
linkNode<T>* LinkList<T>::getHead(void)
{
	return head;
}

//Student.h
#pragma once
class Student
{
	string ID;
	string Name;
	int Age;
	string Speciality;
	string Date;
public:
	Student(void);
	~Student(void);
	void updateID(string id){ ID = id; }
	void Print();
	bool operator == (Student student);
	bool operator != (Student student);
	friend istream & operator >> (istream & in, Student & student);
    friend ostream & operator << (ostream & out,Student & student);
};


//Student.cpp
#include "Stdafx.h"
#include "Student.h"


Student::Student(void)
{
}


Student::~Student(void)
{
}

bool Student::operator == (Student student)
{
    return ID == student.ID;
}

bool Student::operator != (Student student)
{
    return ID != student.ID;
}

istream & operator >> (istream & in, Student & student)
{
	cout << "学号?";
    in >> student.ID;
    cout << "姓名?";
    in >> student.Name;
    cout << "年龄?";
    in >> student.Age;
	cout << "专业?";
    in >> student.Speciality;
	cout << "出生年月?";
    in >> student.Date;
    return in;
}

ostream & operator << (ostream & out, Student & student)
{
    out << "学生的学号为" << student.ID << ",姓名为" << student.Name << ",年龄为" << student.Age << ",专业为" << student.Speciality << ",出生年月为" << student.Date;
    return out;
}
//主函数
#include "stdafx.h"
#include "LinkList.h"
#include "Student.h"
int _tmain(int argc, _TCHAR* argv[])
{
	//这个操作主要是设置运行窗口为白底黑字的
	system("color F0");
	//测试
	cout << "//测试操作" << endl;
    cout << "测试建立一个简易的学生管理系统studentList。";
    LinkList<Student> studentList;
	int position = 0;
    cout << "测试遍历输出学生管理系统studentList:";
    studentList.Print();
	cout << "测试在学生管理系统studentList中增加1个学生。";
	cout << endl;
    Student student, oldStudent, newStudent, deleteStudent;
    cout << "输入新学生的信息:";
	cout << endl;
    cin >> student;
    if(studentList.Insert(position++, student))
    {
		cout << "已在学生管理系统studentList中增加1个新学生。" << student << "。新的学生管理系统studentList:";
    }
	 else
    {
		cout << "在学生管理系统studentList中无法插入新学生。" << student <<"。原来的学生管理系统studentList:";
    }
    studentList.Print();

	
	//查询
	cout << endl;
	cout << "//查询操作" << endl;
	string id;
	linkNode <Student> *p;
	p = studentList.getHead();
    cout << "测试在学生管理系统studentList中查询学生。" << endl;
	cout << "找什么学号的学生?";
    cin >> id;
    student.updateID(id);
    if(studentList.Search(student, p, p -> next))
    {
		cout << "找到学号为" << id << "的学生。" << student << "。" << endl;
    }
	else
    {
		cout << "未找到学号为" << id << "的学生。" << endl;
    }
	
	//更新
	cout << endl;
	cout << "//更新操作" << endl;
	cout << "测试更新指定学号的学生。" << endl;
	cout << "要更新什么学号的学生?";
    cin >> id;
    cout << "输入新学生的信息:" << endl;
    cin >> newStudent;
    oldStudent.updateID(id);
    if(studentList.Update(oldStudent,newStudent))
    {
		cout << "学号为" << id << "的学生已更新为新学生。" << newStudent << "。新的学生管理系统studentList:";
    }
	else
    {
		cout << "未找学号为" << id << "的学生,未更新任何学生。原来的学生管理系统studentList:";
    }
    studentList.Print();
	
	//删除
	cout << endl;
	cout << "//删除操作" << endl;
	cout << "测试删除指定学号的学生。" << endl;
	cout << "要删除什么学号的学生?";
    cin >> id;
    deleteStudent.updateID(id);
    if(studentList.Delete(deleteStudent))
    {
		cout << "已删除学号为" << id << "的学生。" << "新的学生管理系统studentList:";
    }
	else
	{
		cout << "未找到学号为" << id << "的学生。未删除任何学生。原来的学生管理系统studentList:";
	}   
    studentList.Print();

    system("PAUSE");
	return 0;
}

【项目测试运行结果截图】

运行结果展示

备注:各位小可爱们如果有任何的疑问可以在评论区留下你的思考,大家一起进步 yo~*

学生包含以下信息项:学号、姓名、学院、班级、高数成绩、英语成绩、C语言成绩、总分、平均分。 系统的主要功能包括: 1. 创建学生成绩信息文件,根据提示输入学生的各项信息,计算出总分和平均分,然后按学号对学生信息进行排序,并将排序后的学生成绩信息存储到一个二进制文件中。 2. 增加学生信息,在原有学生信息文件的基础上增加新的学生成绩信息,要求:增加后的学生信息仍按学号排序,并继续保存至原文件。 3. 删除学生信息,提示用户输入要进行删除操作的学号,如果在文件中有该信息存在,则将该学号所对应的学生信息删除,否则输出提示信息,并提示用户选择是否继续进行删除操作。 4. 修改学生信息,提示用户输入要进行修改操作的学号,如果在文件中有该息存在,则将提示用户输入该学号对应的要修改的选项,结果保存至原文件,并提示用户选择是否继续进行修改操作。 5. 按不同条件对学生信息进行查询操作,输出满足条件的学生信息。 (1) 按学号查询,输入一个学号,输出对应的学生信息。 (2) 按姓名查询,包括精确查询(输入全名),模糊查询(输入姓)。 (3) 按学院查询,输入学院名称,输出该学院的全部学生的信息。 (4) 按班级查询,输入班级名称,输出该班级的全部学生的信息。 6. 按不同条件对学生成绩进行统计工作。 (1) 按总分对学生信息进行排序(由高到低),输出排序后的信息,并将排序后的学生信息存放到一个新的二进制文件中。 (2) 按平均分统计各个分数段的学生人数(不及格,60-69,70-79,80-89,90-100)。 (3) 分别找出3门课程成绩最高的学生,并输出他们的信息。 (4) 分别统计出3门课程的不及格率,并输出。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值