/* 学生信息管理系统 需求分析 1. 创建学生学生记录信息链表。 2. 输出全部学生信息 3. 查询学生信息记录(按姓名) 4. 删除学生信息记录(按姓名) 5. 按总成绩来排序 6. 插入记录 7. 保存记录到文件中 8. 打开文件读取学生记录 9. 删除全部学生记录 10. 退出系统 */ #include <iostream> #include <string> #include <fstream> #define lEN sizeof(STUDENT) using namespace std; typedef struct stu /*定义结构体数组用于缓存数据*/ { int num; string name; //char name[20]; int score[3]; int sum; float average; int order; stu *next; }STUDENT; //函数声明 int menu_select(); /*菜单函数*/ STUDENT *create_List(); /*创建链表*/ void print_List(STUDENT * head); /* 显示全部记录*/ void search_STUDENT(STUDENT * head,string name); /*按名字查找记录*/ void search_STUDENT(STUDENT * head); /*查找记录*/ STUDENT * delete_STUDENT(STUDENT * head); /*删除记录*/ STUDENT * delete_List(STUDENT * head); //删除链表 STUDENT *sort_List(STUDENT * head); /*排序*/ STUDENT *insert_STUDENT(STUDENT * head,STUDENT * S); /*插入某一记录*/ STUDENT *insert_STUDENT(STUDENT * head); /*插入记录*/ void save_toFile(STUDENT *head); /*保存文件*/ STUDENT *load_from_File(); /*读文件*/ void exit_system(); //退出系统 int count=0; int main() { //menu_select(); STUDENT *head=NULL; for(;;) { switch(menu_select()) { case 1: head=create_List();break; //1.新创建学生记录 case 2: print_List(head);break; //2.打印学生记录 case 3: search_STUDENT(head);break; //3.查询学生记录 case 4: head=delete_STUDENT(head);break; //4.删除学生记录 case 5: head=sort_List(head);break; //5.排序 case 6: head=insert_STUDENT(head);break; //6.插入记录 case 7: save_toFile(head);break; //7.保存文件 case 8: head=load_from_File();break; //8.保存文件 case 9: head=delete_List(head) ;break; //9.删除全部学生记录(链表) case 10: exit_system() ;break; //10.退出系统 } } /* head=create_List(); //创建链表 print_List(head); //遍历链表 */ /* string search_name; cout<<"\n输入您要查找的学生姓名: "; cin>>search_name; search_STUDENT( head,search_name); //按姓名进行查找 */ /* STUDENT *s=new STUDENT; cout<<"输入要插入的学生信息"<<endl; cout<<"学号 姓名 数学成绩 语文成绩 英语成绩 "<<endl; cin>>s->num>>s->name>>s->score[0]>>s->score[1]>>s->score[2]; s->sum=s->score[0]+s->score[1]+s->score[2]; s->average=(float)s->sum/3; s->order=count+1; s->next=NULL; head=insert_STUDENT( head,s); //插入节点后头指针可能会改变 print_List(head); cout<<"按照总成绩排序后"<<endl; head=sort_List(head); //排序 print_List(head); head=delete_STUDENT(head); print_List(head); //遍历链表 //删除后重新排序,此时记录中的order会发生改变,为当前记录集的排序序号 head=sort_List(head); //排序 print_List(head); //遍历链表 */ /* save_toFile(head); //保存到文件 //head=delete_List(head); //删除整个链表 head=load_from_File() ; //读入链表 print_List(head); //遍历链表 */ return 0; } int menu_select() /*菜单函数*/ { int choice; cout<<"\n\t\t学生管理系统菜单选择"<<endl; cout<<"***************************************************"<<endl<<endl; cout<<"\t\t1.输入学生记录"<<endl; cout<<"\t\t2.打印学生记录"<<endl; cout<<"\t\t3.按姓名查找学生记录"<<endl; cout<<"\t\t4.按姓名删除记录"<<endl; cout<<"\t\t5.排序"<<endl; cout<<"\t\t6.插入记录"<<endl; cout<<"\t\t7.保存文件"<<endl; cout<<"\t\t8.加载文件"<<endl; cout<<"\t\t9.删除全部学生记录"<<endl; cout<<"\t\t10.退出系统"<<endl; cout<<"***************************************************"<<endl<<endl; cout<<"输入你的选择1~10: "; cin>>choice; while(choice<1||choice>10) { cout<<"您输入的选项有误,请重新输入: "; cin>>choice; } return choice; } STUDENT *create_List() //创建链表 { cout<<"开始输入用户信息(输入的x学号为0或小于0退出):"<<endl; STUDENT * head=NULL; //链表头节点 STUDENT * p=NULL; //int count=0; //记录要创建的链表节点个数 STUDENT * s=new STUDENT; cout<<"学号 姓名 数学成绩 语文成绩 英语成绩 "<<endl; cin>>s->num>>s->name>>s->score[0]>>s->score[1]>>s->score[2]; s->next=NULL; while(s->num>0) { s->sum=s->score[0]+s->score[1]+s->score[2]; s->average=(float)s->sum/3; s->order=count+1; if(head==NULL) //如果是第一个节点 { head=s; p=s; //p指向当前链表中的最后一个节点 } else //如果不是第一个节点 { p->next=s; p=s; //p指向当前链表中的最后一个节点 } count++; s=new STUDENT; cin>>s->num>>s->name>>s->score[0]>>s->score[1]>>s->score[2]; s->next=NULL; } delete s; cout<<count<<"条学生记录建立成功"<<endl<<endl; return head; } void print_List(STUDENT * head) //显示全部记录 { STUDENT * p=head; int rec=1; if(head==NULL) //判断是否为空链表 { cout<<"当前学生信息记录条数为0!"<<endl; return ; } cout<<"记录号 学号 姓名 数学成绩 语文成绩 英语成绩 总成绩 平均成绩 排序号"<<endl; while(p->next!=NULL) //遍历链表,输出各个节点数据 { cout<<rec<<" "<<p->num<<" "<<p->name<<" "<<p->score[0]<<" " <<p->score[1]<<" "<<p->score[2]<<" "<<p->sum<<" "<<p->average<<" "<<p->order<<endl; p=p->next; rec++; } cout<<rec<<" "<<p->num<<" "<<p->name<<" "<<p->score[0]<<" " <<p->score[1]<<" "<<p->score[2]<<" "<<p->sum<<" "<<p->average<<" "<<p->order<<endl; } STUDENT *delete_STUDENT(STUDENT * head) //删除记录 { STUDENT *p=head; STUDENT *q=head; cout<<"请输入您要删除的学生姓名 :"; string name; cin>>name; int rec=0; while(p!=NULL) { if(p->name!=name) { q=p;//q为p之前的节点 p=p->next; } else { if(p==head)//删除的节点在链表头部 { head=head->next; delete p; rec++; count--; //链表个数减少一个 p=head; } else //删除的节点不在链表头部 { q->next=p->next; delete p; rec++; count--; //链表个数减少一个 p=q->next; } } } cout<<"已删除 "<<rec<<" 个"<<"姓名是 "<<name<<" 的记录!"<<endl<<endl; return head; } STUDENT *insert_STUDENT(STUDENT * head,STUDENT * s) //插入记录//插入一个节点,s指向要插入的节点,找到比s数据大的节点前插入 { STUDENT * p=NULL; //指向要插入的节点位置 STUDENT * q=NULL; //指向要插入的节点位置的前一个位置 p=head; if(head==NULL) head=s; else { if (s->sum<p->sum) //要插入的节点比头节点数据还小(总成绩) { s->next=p; head=s; } else { while(s->sum>p->sum&&p->next!=NULL) { q=p; p=p->next; } if(p->next!=NULL) { s->next=p; q->next=s; } if(p->next==NULL) { if(s->sum>p->sum) p->next=s; else { s->next=p; q->next=s; } } } } count++; //链表个数增加一个 //cout<<"insert a STUDENT successful!"<<endl<<endl; return head; } STUDENT *insert_STUDENT(STUDENT * head) /*插入记录*/ { STUDENT *s=new STUDENT; cout<<"输入要插入的学生信息"<<endl; cout<<"学号 姓名 数学成绩 语文成绩 英语成绩 "<<endl; cin>>s->num>>s->name>>s->score[0]>>s->score[1]>>s->score[2]; s->sum=s->score[0]+s->score[1]+s->score[2]; s->average=(float)s->sum/3; s->order=count+1; s->next=NULL; head=insert_STUDENT( head,s); //插入节点后头指针可能会改变 cout<<"插入记录成功!"<<endl; return head; } //排序思路 //将无序链表从第一个节点开始依次插入到一个开始为空的空链表上(插入函数要先找到要插入的位置) STUDENT *sort_List(STUDENT * head) //链表排序 { STUDENT * head_sort=NULL; if(head==NULL) return head; STUDENT * p; while(head!=NULL) //排序 { p=head; //将p指向的节点从原链表中删除 head=head->next; //原链表头节点后移 p->next=NULL; //将p与原链表中的下一个节点断开 head_sort=insert_STUDENT(head_sort,p); } //排序完要对链表中的节点order成员进行修改 p=head_sort; int order=1; while(p!=NULL) { p->order=order; order++; p=p->next; } cout<<"排序完成!"<<endl; return head_sort; } void search_STUDENT(STUDENT * head,string name) //查找记录,按姓名查找 { STUDENT * p=head; bool flag=0; //作为是否找到的标记 if(head==NULL) //判断是否为空链表 { cout<<"the list is empty! "<<endl; return ; } while(p!=NULL) //遍历链表,输出各个节点数据 { if (p->name==name) { flag=1; cout<<"您查找的姓名为 "<<name<<" 的用户存在,具体记录信息如下:"<<endl; cout<<" "<<p->num<<" "<<p->name<<" "<<p->score[0]<<" " <<p->score[1]<<" "<<p->score[2]<<" "<<p->sum<<" "<<p->average<<" "<<p->order<<endl; } p=p->next; } if(flag==0) { cout<<"您查找的姓名为 "<<name<<" 的用户不存在!"<<endl; } } void search_STUDENT(STUDENT * head) /*查找记录*/ { string search_name; cout<<"\n输入您要查找的学生姓名: "; cin>>search_name; search_STUDENT( head,search_name); //按姓名进行查找 } STUDENT * delete_List(STUDENT * head) //删除链表 { int count=0; if(head==NULL) { cout<<"the list is empty ,no STUDENT to delete!"<<endl; return head; } STUDENT * p; while(head!=NULL) { p=head; head=head->next; delete p; count++; } cout<<"整个链表删除完成,已删除掉"<<count<<"个链表节点!"<<endl<<endl; ::count-=count; return head; } void save_toFile(STUDENT *head) //保存文件 { ofstream outfile("student.out",ios::binary); if(!outfile) { cout<<"打开保存文件失败!"; return; } STUDENT * p=head; int rec=0; while(p!=NULL) { rec++; outfile.write((char *)p,lEN); p=p->next; } cout<<"文件保存成功!"<<rec<<" 条记录被保存"<<endl; outfile.close(); } STUDENT * load_from_File() //读文件 { ifstream infile("student.out",ios::binary); if(!infile) { cout<<"打开读入文件失败!"; return NULL; } int rec=0; STUDENT * head=NULL; STUDENT *p=NULL; STUDENT *s=NULL; //while(!infile.eof()) //如果此处用eof函数判断文件结尾时,会多读取一条记录。因为eof要先读取出EOF后再下一次返回真 while(!(infile.peek()==EOF)) //用peek函数去监读取是否到文件结束EOF { s=new STUDENT; infile.read((char *)s,lEN); s->next=NULL; if(head==NULL) //如果是第一个节点 { head=s; p=s; //p指向当前链表中的最后一个节点 rec++; } else //如果不是第一个节点 { p->next=s; p=s; //p指向当前链表中的最后一个节点 rec++; } } cout<<"\n文件读取成功!"<<rec<<" 条记录被读取"<<endl; infile.close(); return head; } void exit_system() //退出系统 { cout<<"退出系统..."<<endl; exit(0); }
-----------------------------------------------------------------------------
注意:一下函数中的红色部分
STUDENT * load_from_File() //读文件 { ifstream infile("student.out",ios::binary); if(!infile) { cout<<"打开读入文件失败!"; return NULL; } int rec=0; STUDENT * head=NULL; STUDENT *p=NULL; STUDENT *s=NULL; //while(!infile.eof()) //如果此处用eof函数判断文件结尾时,会多读取一条记录。因为eof要先读取出EOF后再下一次返回真 while(!(infile.peek()==EOF)) //用peek函数去监读取是否到文件结束EOF { s=new STUDENT; infile.read((char *)s,lEN); s->next=NULL; if(head==NULL) //如果是第一个节点 { head=s; p=s; //p指向当前链表中的最后一个节点 rec++; } else //如果不是第一个节点 { p->next=s; p=s; //p指向当前链表中的最后一个节点 rec++; } } cout<<"\n文件读取成功!"<<rec<<" 条记录被读取"<<endl; infile.close(); return head; }
相关的理解可以参考
C++ eof()函数相关应用技巧分享