学生管理系统

/*
 学生信息管理系统
需求分析
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<<"
输入您要查找的学生姓名: ";
    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<<"
		学生管理系统菜单选择"<<endl;
    cout<<"***************************************************"<<endl<<endl;
    cout<<"		1.输入学生记录"<<endl;
    cout<<"		2.打印学生记录"<<endl;
    cout<<"		3.按姓名查找学生记录"<<endl;
    cout<<"		4.按姓名删除记录"<<endl;
    cout<<"		5.排序"<<endl;
    cout<<"		6.插入记录"<<endl;
    cout<<"		7.保存文件"<<endl;
    cout<<"		8.加载文件"<<endl;
    cout<<"		9.删除全部学生记录"<<endl;
    cout<<"		10.退出系统"<<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<<"
输入您要查找的学生姓名: ";
    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<<"
文件读取成功!"<<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<<"
文件读取成功!"<<rec<<" 条记录被读取"<<endl;
infile.close();
return head;
}

相关的理解可以参考 

C++ eof()函数相关应用技巧分享

原文地址:https://www.cnblogs.com/beautiful-code/p/5239307.html