前言:
前面介绍到了C++的泛型编程,并实现了万能容器,不过那使用的是数组,今天呢咱带大家实践一下使用泛型技术,结合单链表实现一个职工管理系统。保证大家看完之后有所感悟。
一、泛型编程思想
所谓泛型就是类型不固定,只需修改少量代码就可以扩展为其他类型的应用,由于C++是一门静态编译型的语言,变量的类型都是事先编译好的,如果不用泛型进行编程,一段代码始终就是那么点作用。使用泛型编程后,可以很简单的对其他类型进行扩展。泛型编程核心思想就是将数据类型设置为模板,第一次编译是对模板进行编译,第二次编译会带入人为传的类型参数。前面文章有讲函数模板与类模板,忘记的小伙伴可以去看看。
二、单链表是什么?
单链表中的单代表一条,链表意思就是一个个节点链接起来的表结构。
其最典型的特征就是节点只有一个指针域。并且该指针域指向下一节点的地址
1.图示
- 链表中的第一个节点被称为头结点,一般不存储数据,指向头结点的指针称为头指针
- 第一个存储数据的节点称为首节点,末尾节点称为尾节点,指针域赋空,防止变为野指针。
2.链表的节点结构【节点类】
①常规链表节点
- 包含数据域,指针域。指针域指针类型与节点类型保持一致。
class node { private: //数据域 string data1; string data2; //指针域 node* next; public: node() { } }
②泛型链表节点
其中T代表的是一种不确定的数据类型,data是一个T类型的对象,其作用类似于结构体存储数据域的信息,但是在c++中他必须用类实现,因为该数据类型要有属于自己的属性与方法。node* next
代表一个T类型的node指针,其本质还是node指针,只不过T的类型决定着node *指向的节点中的data的类型。
代码如下:
templateclass node { private: //数据域 T data; //指针域 node * next; public: node() { } }
3.链表类
常规链表类中需要包含一个头指针,指向链表的头结点,然后创建一个链表对其增删改查泛型编程中的链表类,也要是一个链表类。实现类型的参数化,具体如下:
templateclass link { private: //传入类型的时候,先传给link然后link会传给node; node * head; public: link() { } bool add(){ } bool del(){ }
三、泛型编程核心
1.实现数据类
泛型就是要将你写的类型,像对待int string类型那样对待。首先要进行的就是运算符重载重载了运算符你可以使用cin,cout直接对相应的对象进行输入,输出。可以直接使用=进行赋值。
具体实现如下:
class officer { //重载了标准输入输出流函数、文件输入输出流函数(可以直接存文件) friend ostream& operator<<(ostream& out, officer& obj); friend istream& operator>>(istream& in, officer& obj); friend ofstream& operator<<(ofstream& outfile, officer& obj);//--------输出到文件 friend ifstream& operator>>(ifstream& infile, officer& obj);//---------读取文件 private: string id_card; string name; string sex; int age; string post; int money; public://---------------------------------私有属性管理方法 officer() { id_card = ""; name = ""; sex = ""; age = 0; post = ""; money = 0; } //拷贝构造函数结合赋值函数,直接进行赋值。 officer(officer& obj) { this->id_card = obj.getid(); this->name = obj.getname(); this->sex = obj.getsex(); this->age = obj.getage(); this->money = obj.getmoney(); this->post = obj.getpost(); } officer& operator=(officer& obj) { this->id_card = obj.getid(); this->name = obj.getname(); this->sex = obj.getsex(); this->age = obj.getage(); this->money = obj.getmoney(); this->post = obj.getpost(); return *this; } //查重时使用 bool operator==(officer& obj) { if (this->getid() == obj.getid() && this->getname() == obj.getname() && this->getsex() == obj.getsex()\ && this->getage() == obj.getage() && this->getpost() == obj.getpost() && this->getmoney() == obj.getmoney()) { return true; } return false; } bool operator!=(officer& obj) { if (this->getid() == obj.getid()) { return false; } return true; } //排序时使用,根据工资的高低。 bool operator>(officer& obj) { if (this->getmoney() > obj.getmoney()) { return true; } return false; } bool operator<(officer& obj) { if (this->getmoney() < obj.getmoney()) { return true; } return false; } void setpost(string post) { this->post = post; } void setmoney(int money) { this->money = money; } void setid(string id) { id_card = id; } void setname(string name) { this->name = name; } void setsex(string sex) { this->sex = sex; } void setage(int age) { this->age = age; } string getid() { return id_card; } string getname() { return name; } string getsex() { return sex; } int getage() { return age; } string getpost() { return post; } int getmoney() { return money; } };
2.实现链表类
泛型的链表类、节点类一般就是写死的,做到换一个数据类还可以用的效果所以在泛型链表类中的提示性语句要有一定的泛化程度,不可以针对某种类型提示。
templateclass link { private: node * head; public: link() { string classname; ifstream infile; node * p, * q; p = new node ; p->setnext(NULL); head = new node ; head->setnext(NULL); q = head; classname = head->GetClass(); classname.erase(remove(classname.begin(), classname.end(), '<'), classname.end()); classname.erase(remove(classname.begin(), classname.end(), '>'), classname.end()); //cout << classname << endl; infile.open(classname); while (infile >> p->opedata()) { q->setnext(p); q = q->getnext(); p = new node ; p->setnext(NULL); } delete p; infile.close(); } void addnode() {//-------------------------增 node * p, * q; p = new node ; p->setnext(NULL); cout << "请输入您要存储的数据:" << endl; cin >> p->opedata(); q = head; for (; q->getnext() != NULL; q = q->getnext()) { if (q->getnext()->opedata() == p->opedata()) { cout << "您输入的数据,已存在,不需要重复录入" << endl; system("pause"); delete p; return; } } q->setnext(p); savelink(); cout << "存储成功!" << endl; system("pause"); } void delnode() {//---------------------------删 bool k = false; node * p, * q, * r; p = new node ; p->setnext(NULL); cout << "请输入您要删除的数据" << endl; cin >> p->opedata(); q = head; for (; q->getnext() != NULL; q = q->getnext()) { if (q->getnext()->opedata() == p->opedata() && q->getnext()->getnext() != NULL) { r = q->getnext(); q->getnext() = q->getnext()->getnext(); delete r; k = true; break; } else if (q->getnext()->opedata() == p->opedata() && q->getnext()->getnext() == NULL) { r = q->getnext(); delete r; q->setnext(NULL); k = true; break; } } if (k == false) { cout << "没有找到您要删除的数据,请核实后再来!" << endl; } else if (k == true) { savelink(); cout << "删除成功!" << endl; } delete p; system("pause"); return; } void altenode() {//-------------------------------改 int judgecin = 0; bool k = false; node * p, * q, * r; p = new node ; p->setnext(NULL); cout << "请输入您要改动的数据" << endl; judgecin = 1; cin >> p->opedata(); judgecin = 0; q = head; for (; q->getnext() != NULL; q = q->getnext()) { if (q->getnext()->opedata() == p->opedata()) { cout << "请输入新的数据:" << endl; rewrite: cin >> p->opedata(); for (r = head; r->getnext() != NULL; r = r->getnext()) { if (r->getnext()->opedata() == p->opedata() && p->opedata() != q->getnext()->opedata()) { system("cls"); judgecin++; if (judgecin == 3) { cout << "您多次输入信息错误,请核实后再来,将要返回主菜单" << endl; delete p; system("pause"); return; } cout << "请输入您自己的身份信息!或输入新的身份证号" << endl; goto rewrite; } } q->getnext()->opedata() = p->opedata(); k = true; } } if (k == true) { savelink(); cout << "修改成功!" << endl; } else { cout << "修改失败!没有找到该数据!" << endl; } delete p; system("pause"); return; } void selnode() {//----------------------------------查 cout << "请输入您要查找的数据" << endl; bool k = false; node * p, * q; p = new node ; p->setnext(NULL); cin >> p->opedata(); for (q = head; q->getnext() != NULL; q = q->getnext()) { if (q->getnext()->opedata() == p->opedata()) { k = true; cout << "您要查找的数据如下!" << endl; cout << q->getnext()->opedata() << endl; //break; } } if (k == false) { cout << "没有找到您要查找的数据!抱歉" << endl; } system("pause"); return; } void printlink() {//------------------------------打印链表 node * p; sortlink(); for (p = head; p->getnext() != NULL; p = p->getnext()) { cout << p->getnext()->opedata() << endl; } system("pause"); } void sortlink() {//-------------------------------排序 node * p, * q; if (head->getnext() == NULL) { cout << "没有数据,无需排序!" << endl; return; } if (head->getnext()->getnext() == NULL) { cout << "一组数据,无需排序!" << endl; return; } for (p = head->getnext(); p->getnext() != NULL; p = p->getnext()) { for (q = p->getnext(); q != NULL; q = q->getnext()) { if (q->opedata() > p->opedata()) { node temp; temp = *q; *q = *p; *p = temp; temp.getnext() = q->getnext(); q->getnext() = p->getnext(); p->getnext() = temp.getnext(); } } } } void savelink() {//--------------------------------------存链表 ofstream outfile; string classname; node * p; p = head; classname = head->GetClass(); classname.erase(remove(classname.begin(), classname.end(), '<'), classname.end()); classname.erase(remove(classname.begin(), classname.end(), '>'), classname.end()); outfile.open(classname); while (p->getnext() != NULL) { p = p->getnext(); outfile << p->opedata() << endl; } outfile.close(); } ~link() {//--------------------------------------------销毁链表 node * p; p = head->getnext(); while (p != NULL) { delete head; head = p; p = p->getnext(); } }// };
四、运行截图
1.主菜单
2.查看信息
3.更换数据类型
- 将officer类型注释掉,使用int类型
4.再次显示所有信息【抛转】
- 可以看到就算将
officer
类型换为int类型,程序依旧可以稳定的运行。 - 这里打印职工信息系统的提示性语句出现到了这里,如果大家真的理解了泛型的思想
- 肯定可以轻而易举的改掉这处不足,有什么想法的小伙伴评论区留言博主吧。
五、源码
char off_menu(); class officer; int mynum(string str) {//-----------------判断字符串是否全为数字 for (unsigned int i = 0; i < str.length(); i++) { if (!isdigit(str[i])) { return 1; } } return 0; } templateclass node { private: T data; node * next; public: node() { } void setnext(node * p) { if (p != NULL) { next = new node ; next->data = p->opedata(); next->next = p->getnext(); } else next = p; } T& opedata() { return data; } node *& getnext() { return next; } const char* GetClass() { return typeid(*this).name(); } }; template class link { private: node * head; public: link() { string classname; ifstream infile; node * p, * q; p = new node ; p->setnext(NULL); head = new node ; head->setnext(NULL); q = head; classname = head->GetClass(); classname.erase(remove(classname.begin(), classname.end(), '<'), classname.end()); classname.erase(remove(classname.begin(), classname.end(), '>'), classname.end()); //cout << classname << endl; infile.open(classname); while (infile >> p->opedata()) { q->setnext(p); q = q->getnext(); p = new node ; p->setnext(NULL); } delete p; infile.close(); } void addnode() {//-------------------------增 node * p, * q; p = new node ; p->setnext(NULL); cout << "请输入您要存储的数据:" << endl; cin >> p->opedata(); q = head; for (; q->getnext() != NULL; q = q->getnext()) { if (q->getnext()->opedata() == p->opedata()) { cout << "您输入的数据,已存在,不需要重复录入" << endl; system("pause"); delete p; return; } } q->setnext(p); savelink(); cout << "存储成功!" << endl; system("pause"); } void delnode() {//---------------------------删 bool k = false; node * p, * q, * r; p = new node ; p->setnext(NULL); cout << "请输入您要删除的数据" << endl; cin >> p->opedata(); q = head; for (; q->getnext() != NULL; q = q->getnext()) { if (q->getnext()->opedata() == p->opedata() && q->getnext()->getnext() != NULL) { r = q->getnext(); q->getnext() = q->getnext()->getnext(); delete r; k = true; break; } else if (q->getnext()->opedata() == p->opedata() && q->getnext()->getnext() == NULL) { r = q->getnext(); delete r; q->setnext(NULL); k = true; break; } } if (k == false) { cout << "没有找到您要删除的数据,请核实后再来!" << endl; } else if (k == true) { savelink(); cout << "删除成功!" << endl; } delete p; system("pause"); return; } void altenode() {//-------------------------------改 int judgecin = 0; bool k = false; node * p, * q, * r; p = new node ; p->setnext(NULL); cout << "请输入您要改动的数据" << endl; judgecin = 1; cin >> p->opedata(); judgecin = 0; q = head; for (; q->getnext() != NULL; q = q->getnext()) { if (q->getnext()->opedata() == p->opedata()) { cout << "请输入新的数据:" << endl; rewrite: cin >> p->opedata(); for (r = head; r->getnext() != NULL; r = r->getnext()) { if (r->getnext()->opedata() == p->opedata() && p->opedata() != q->getnext()->opedata()) { system("cls"); judgecin++; if (judgecin == 3) { cout << "您多次输入信息错误,请核实后再来,将要返回主菜单" << endl; delete p; system("pause"); return; } cout << "请输入您自己的身份信息!或输入新的身份证号" << endl; goto rewrite; } } q->getnext()->opedata() = p->opedata(); k = true; } } if (k == true) { savelink(); cout << "修改成功!" << endl; } else { cout << "修改失败!没有找到该数据!" << endl; } delete p; system("pause"); return; } void selnode() {//----------------------------------查 cout << "请输入您要查找的数据" << endl; bool k = false; node * p, * q; p = new node ; p->setnext(NULL); cin >> p->opedata(); for (q = head; q->getnext() != NULL; q = q->getnext()) { if (q->getnext()->opedata() == p->opedata()) { k = true; cout << "您要查找的数据如下!" << endl; cout << q->getnext()->opedata() << endl; //break; } } if (k == false) { cout << "没有找到您要查找的数据!抱歉" << endl; } system("pause"); return; } void printlink() {//------------------------------打印链表 node * p; sortlink(); for (p = head; p->getnext() != NULL; p = p->getnext()) { cout << p->getnext()->opedata() << endl; } system("pause"); } void sortlink() {//-------------------------------排序 node * p, * q; if (head->getnext() == NULL) { cout << "没有数据,无需排序!" << endl; return; } if (head->getnext()->getnext() == NULL) { cout << "一组数据,无需排序!" << endl; return; } for (p = head->getnext(); p->getnext() != NULL; p = p->getnext()) { for (q = p->getnext(); q != NULL; q = q->getnext()) { if (q->opedata() > p->opedata()) { node temp; temp = *q; *q = *p; *p = temp; temp.getnext() = q->getnext(); q->getnext() = p->getnext(); p->getnext() = temp.getnext(); } } } } void savelink() {//--------------------------------------存链表 ofstream outfile; string classname; node * p; p = head; classname = head->GetClass(); classname.erase(remove(classname.begin(), classname.end(), '<'), classname.end()); classname.erase(remove(classname.begin(), classname.end(), '>'), classname.end()); outfile.open(classname); while (p->getnext() != NULL) { p = p->getnext(); outfile << p->opedata() << endl; } outfile.close(); } ~link() {//--------------------------------------------销毁链表 node * p; p = head->getnext(); while (p != NULL) { delete head; head = p; p = p->getnext(); } }// }; class officer { friend ostream& operator<<(ostream& out, officer& obj); friend istream& operator>>(istream& in, officer& obj); friend ofstream& operator<<(ofstream& outfile, officer& obj);//--------输出到文件 friend ifstream& operator>>(ifstream& infile, officer& obj);//---------读取文件 private: string id_card; string name; string sex; int age; string post; int money; public://---------------------------------私有属性管理方法 officer() { id_card = ""; name = ""; sex = ""; age = 0; post = ""; money = 0; } officer(officer& obj) { this->id_card = obj.getid(); this->name = obj.getname(); this->sex = obj.getsex(); this->age = obj.getage(); this->money = obj.getmoney(); this->post = obj.getpost(); } officer& operator=(officer& obj) { this->id_card = obj.getid(); this->name = obj.getname(); this->sex = obj.getsex(); this->age = obj.getage(); this->money = obj.getmoney(); this->post = obj.getpost(); return *this; } bool operator==(officer& obj) { if (this->getid() == obj.getid() && this->getname() == obj.getname() && this->getsex() == obj.getsex()\ && this->getage() == obj.getage() && this->getpost() == obj.getpost() && this->getmoney() == obj.getmoney()) { return true; } return false; } bool operator!=(officer& obj) { if (this->getid() == obj.getid()) { return false; } return true; } bool operator>(officer& obj) { if (this->getmoney() > obj.getmoney()) { return true; } return false; } bool operator<(officer& obj) { if (this->getmoney() < obj.getmoney()) { return true; } return false; } void setpost(string post) { this->post = post; } void setmoney(int money) { this->money = money; } void setid(string id) { id_card = id; } void setname(string name) { this->name = name; } void setsex(string sex) { this->sex = sex; } void setage(int age) { this->age = age; } string getid() { return id_card; } string getname() { return name; } string getsex() { return sex; } int getage() { return age; } string getpost() { return post; } int getmoney() { return money; } }; ostream& operator<<(ostream& out, officer& obj) { out << obj.getid() << "\t"; out << obj.getname() << "\t"; out << obj.getsex() << "\t"; out << obj.getage() << "\t"; out << obj.getpost() << "\t"; out << obj.getmoney() << "\t"; // cout << endl; return out; } istream& operator>>(istream& in, officer& obj) { cout << "身份证(18位):"; id_here: in >> obj.id_card; if (obj.getid() == "00") { return in; } else if (obj.getid().length() != 18) { cout << "输入格式不规范请重新输入:"; goto id_here; } //if (judgecin == 1) { // return in; //} cout << "姓名:"; in >> obj.name; cout << "性别:"; sex_here: in >> obj.sex; if (obj.getid() == "00") { return in; } else if (obj.getsex() != "男" && obj.getsex() != "女") { cout << "请输入准确的性别:"; goto sex_here; } cout << "年龄:"; string age; age_here: in >> age; if (obj.getid() == "00") { return in; } else if (mynum(age) || age.length() > 3) { cout << "输入不规范请重新输入:"; goto age_here; } obj.age = atoi(age.c_str()); cout << "职位:"; post_here: in >> obj.post; if (obj.getid() == "00") { return in; } else if (obj.getpost() != "监狱长" && obj.getpost() != "探长" && \ obj.getpost() != "参谋长" && obj.getpost() != "大警司" && obj.getpost() != "小警司") { cout << "请输入职位(监狱长,探长,参谋长,大警司,小警司):"; goto post_here; } if (obj.getpost() == "监狱长") { obj.money = 30000; } else if (obj.getpost() == "探长") { obj.money = 24000; } else if (obj.getpost() == "参谋长") { obj.money = 24500; } else if (obj.getpost() == "大警司") { obj.money = 20000; } else if (obj.getpost() == "小警司") { obj.money = 18000; } return in; } ofstream& operator<<(ofstream& outfile, officer& obj) { outfile << obj.getid() << " " << obj.getname() << " " << obj.getsex() << " " << obj.getage()\ << " " << obj.getpost() << " " << obj.getmoney();// << endl; return outfile; } ifstream& operator>>(ifstream& infile, officer& obj) { string post1; int money1; string id1; string name1; string sex1; int age1; infile >> id1 >> name1 >> sex1 >> age1 >> post1 >> money1; obj.setid(id1); obj.setname(name1); obj.setsex(sex1); obj.setage(age1); obj.setpost(post1); obj.setmoney(money1); return infile; } int main() { //link myarray; link myarray; char menun; while (1) { menun = off_menu(); if (menun == '1') { system("cls"); int len; cout << "请输入您要增加节点的个数:"; cin >> len; for (int i = 0; i < len; i++) { myarray.addnode(); system("cls"); } } else if (menun == '2') { myarray.delnode(); } else if (menun == '3') { myarray.altenode(); } else if (menun == '4') { myarray.selnode(); } else if (menun == '5') { cout << "身份证\t\t\t姓名\t性别\t年龄\t职位\t工资" << endl; myarray.printlink(); } else if (menun == '6') { break; } system("cls"); } return 0; } char off_menu() { char n; n = '0'; system("cls"); cout << "\n\n\n"; cout << "\t\t\t\t\t-------欢迎使用本信息管理系统-------" << endl; cout << "\t\t\t\t\t*\t \t\t\t *" << endl; cout << "\t\t\t\t\t*\t 1.录入员工信息\t *" << endl; cout << "\t\t\t\t\t*\t \t\t\t *" << endl; cout << "\t\t\t\t\t*\t 2.删除员工信息\t *" << endl; cout << "\t\t\t\t\t*\t \t\t\t *" << endl; cout << "\t\t\t\t\t*\t 3.修改员工信息\t *" << endl; cout << "\t\t\t\t\t*\t \t\t\t *" << endl; cout << "\t\t\t\t\t*\t 4.查询员工信息\t *" << endl; cout << "\t\t\t\t\t*\t \t\t\t *" << endl; cout << "\t\t\t\t\t*\t 5.查看员工信息\t *" << endl; cout << "\t\t\t\t\t*\t \t\t\t *" << endl; cout << "\t\t\t\t\t*\t 6.退出该系统\t\t *" << endl; cout << "\t\t\t\t\t*\t \t\t\t *" << endl; cout << "\t\t\t\t\t------------------------------------" << endl; cout << "———————————————————————————————————————————————————————----------" << endl; cout << "———————————————————————————————————————————————————————----------" << endl; cout << "please your choose:"; while (1) { n = _getch(); if (n >= '1' && n <= '6') { break; } } cout << endl; return n; }
总结:
理解了泛型会对python等解释性语言有更好的理解。希望大家能够好好理解这个项目,在博主的基础之上更上一层楼
到此这篇关于基于C++泛型编程职工管理系统的文章就介绍到这了,更多相关C++泛型编程职工管理系统内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!