| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 361 人关注过本帖
标题:关于链表的程序,请高手指教
只看楼主 加入收藏
猎豹
Rank: 1
来 自:河南
等 级:新手上路
帖 子:7
专家分:0
注 册:2010-4-10
结帖率:0
收藏
 问题点数:0 回复次数:0 
关于链表的程序,请高手指教
#include<iostream>
#include<fstream>
#include<iomanip>
#include<conio.h>
using namespace std;
struct student
{
     char name[20];
     char number[20];
     int year;
     int month;
     char hobby[20];
     //hobby[20]代表爱好
     student *next;//下一个学生结点指针
};
int num=0;
//s表示一组学生信息链表的表头指针
void input_student(student *&s);
//采用插入法,边插入边按由大到小排序
//形参*&s表示s是一个引用指针,用于返回输入的指针值
void output_student(student *p);
//输出p为头指针的链表表示的学生信息。
void save_student(char *n,student *p);
//将以p为头指针的链表表示的学生信息保存在以字符串n为文件名的磁盘文件中
void read_student(char *n,student *&p);
void delete_student(student *&s);
//在以s为链表头结点指针的链表中,删除一个结点,s作为引用指针变量
//是为了返回链表头结点指针
int main()
{
    student *s=NULL;//s为链表头指针
    cout<<"请输入一组学生数据"<<endl;
    input_student(s);
    cout<<"学生信息为"<<endl;
    output_student(s);
    cout<<"将学生信息保存在磁盘文件中,输入磁盘文件名"<<endl;
    char cdname[20];
    //cdname[20]代表磁盘名字
    cin>>cdname;
    save_student(cdname,s);
    cout<<"从磁盘中读入一组学生数据,请输入磁盘文件名"<<endl;
    cin>>cdname;
    read_student(cdname,s);//从磁盘读入学生数据
    cout<<"读入的学生信息"<<endl;
    output_student(s);
    //删除学生信息
    delete_student(s);
    cout<<"删除一个结点后的链表信息为"<<endl;
    output_student(s);
    cout<<"将学生信息再保存回磁盘文件中,请输入磁盘文件名"<<endl;
    cin>>cdname;
    save_student(cdname,s);
    system("pause");
    return 0;
}
void input_student(student *&s)
{
     student *t;//流动结点指针,用于指向新产生的结点
     cout<<"请输入学生信息"<<endl;
     do
     {                          
        char name[20]={'0'};
        //name[20]代表姓名
        char number[20]={'0'};
        //number[20]代表学号
        int year=0,month=0;
        char hobby[20]={'0'};
        //hobby[20]代表爱好
        cout<<"学生姓名(*为终止标志):";cin>>name;
        if(strcmp(name,"*")==0)break;
        m:cout<<"请输入学号"<<endl;
        for(int i=0;i<9;i++)
        {
           number[i]=getch();
           putch(number[i]);
           //这样设置最多只能输入9位
           if(!isdigit(number[i])&&number[i]!=13)
           //isdigit判断一个数是否整数。
           //13表示回车
           {
              cout<<int(number)<<endl;
              cout<<"你敲的不是数字, 请重新输入!\n";
              goto m;
           }
        }
        cout<<endl;
        char year1[15];
        //用于存出生年份的字符数组
        w1:cout<<"学生出生年份:";
        for(int i=0;i<4;i++)
        {
           year1[i]=getch();
           putch(year1[i]);
           //这样设置最多只能输入4位
           if(!isdigit(year1[i])&&year1[i]!=13)
           //isdigit判断一个数是否整数。
           //13表示回车
           {
              cout<<int(year1)<<endl;
              cout<<"你敲的不是数字, 请重新输入!\n";
              goto w1;
           }
        }                  
        year=atol(year1);
        cout<<endl;
        char month1[10];
        //用于存月份的字符数组
        w2:cout<<"学生出生月份:";
        for(int i=0;i<2;i++)
        {
           month1[i]=getch();
           putch(month1[i]);
           //这样设置最多只能输入2位
           if(!isdigit(month1[i])&&month1[i]!=13)
           //isdigit判断一个数是否整数。
           //13表示回车
           {
              cout<<int(month1)<<endl;
              cout<<"你敲的不是数字, 请重新输入!\n";
              goto w2;
           }
        }            
        month=atol(month1);
        if(month>12)
        {
            cout<<"你输错了,请重新输入"<<endl;
            goto w2;
        }        
        cout<<endl;      
        cout<<"爱好:";cin>>hobby;
        num++;
        t=new student;
        //t->name=name;
        strcpy(t->name,name);
        strcpy(t->number,number);
        t->year=year;
        t->month=month;
        strcpy(t->hobby,hobby);
        t->next=NULL;
        //给新结点填充数据,下一项指针next置空
        if(!s)//原头指针空
          s=t; //新结点指针作为头指针
        else
        {
            student *p=s;//p作为循环用的流动指针,从头指针开始
            if(t->year>p->year||(t->year==p->year&&t->month>=p->month))
            //t指向的结点比原来头指针指向的结点大
            {
               s=t;//t取代头指针s,原头指针p作为新头指针s的后继
               s->next=p;
            }                                   
            else
            {
                student *q;//设置指针q用于查找新指针t在链表中位置的前驱
                while(p&&(t->year<p->year)||(t->year==p->year&&t->month<p->month))
                //查找新结点应该插入的位置q之后p之前
                {
                   q=p;
                   p=p->next;
                }// while循环终止时,有两种情况,1,t在q和p之间直接插入
                //2,t在结尾之后q指向尾结点,p空指针,将t接在q后,t接空指针
                q->next=t;
                t->next=p;
            }
        }
     }while(1);//while条件永真,出口设在输入姓名“*”处
}
void output_student(student *p)
{
     student *t=p;//t作为流动指针
     cout<<"共有"<<num<<"个学生,从小到大排列为"<<endl;
     cout<<"姓名"<<setw(10)<<"学号"<<setw(15)<<"出生年份"
     <<setw(10)<<"出生月份"<<setw(10)<<"爱好"<<endl;
     while(t)//t不空,表示t所指向的结点存在,输出相关信息
     {
        cout<<t->name<<setw(15)<<t->number<<setw(10)<<t->year
        <<setw(10)<<t->month<<setw(13)<<t->hobby<<endl;
        t=t->next;
     }
}
void save_student(char *n,student *p)
{
     ofstream out(n,ios::out|ios::binary);
     if(!out)
     {
        cout<<"磁盘文件"<<n<<"打开失败"<<endl;
        system("pause");
        return;
     }
     out.write((char*)&num,sizeof(int));
     //保存学生人数,以便读文件时使用
     for(student *t=p;t;t=t->next)
     {
      //t作为流动指针,从头指针p开始,当前结点输出之后,指针后移一项
        out.write((char*)t,sizeof(student));
        //第一个参数是输出数据的位置,即指针t所指结点的地址
        //即&(*t),实际上就是t
        //第二个参数是输出数据的长度,即输出一个结点的长度
      }
      out.close();
      cout<<"输出结点的个数为"<<num<<endl;
}                                                                 
void read_student(char *n,student *&p)
{
     ifstream in(n,ios::in|ios::binary);
     if(!in)
     {
        cout<<"磁盘文件"<<n<<"打开失败"<<endl;
        system("pause");
        return;
     }
     p=NULL;
     if(!in.eof())
        in.read((char*)&num,sizeof(int));
     if(num>0)
     {
        p=new student;      
        in.read((char*)p,sizeof(student));
        //第一个参数是磁盘数据读入内存的位置,即指针p所指结点的地址即&(*p)实际上就是p
        //第二个参数是读入数据的长度,即一个结点的长度
     }
     p->next=NULL;
     student *q=p;
     //q,t是为了从文件中读出结点数据后,形成链表用的,q为已存在的结点指针
     //t为新形成的结点指针,t为q的后继,同时,再次生成t之前,q后移一项
     student *t;
     for(int i=1;i<num;i++)
     {
          t=new student;
          in.read((char*)t,sizeof(student));
          t->next=NULL;
          //因为新链表只需要磁盘文件中的实际数据,读入结点的后继结点指针不起作用
          //新链表的结点地址要靠new student来分配,在下一个结点读入之前,后继
          //指针置空
          q->next=t;
          q=t;
     }
     //此处使用for循环,而不使用while循环,是因为若使用成员函数eof()来控制循环结束
     // 文件的eof()函数有一个问题,文件读完之后,他仍不为真,必须试图读取文件结束标志之后
     //eof()才为真,这样以来,若使用while(!in.eof())直接控制读完整个文件,势必多读出一个结点
     //为此,在文件开头保存结点个数,再使用for循环控制,读出全部结点
     in.close();
}
void delete_student(student *&s)
{
     char name[20];
     cout<<"请输入要删除学生名单:";cin>>name;
     student *t=s;
     if(strcmp(t->name,name)==0)
     {
        s=t->next;
        delete t;
        num--;
        return;
     }
     //要删除学生结点为链表头,上述程序删除头结点
     //下面在链表中先查找要删除的结点,再删除
     student *q=t;//t作为流动指针,q作为t的前驱结点指针
     while(t&&strcmp(t->name,name))
     {
        q=t;
        t=t->next;
     }
     if(t)
     {
         q->next=t->next;
         delete t;
         num--;
     }
     else
     {
         cout<<"没有找到要删除的学生"<<endl;
         system("pause");
         exit(1);
     }
}                             
                              
                              
      
            
                             
                     
                        
                                                                                                        
                                                                  
            
   
                                                                  
                 
                                   
     
     
 
  
搜索更多相关主题的帖子: 链表 指教 
2010-05-20 12:56
快速回复:关于链表的程序,请高手指教
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.021378 second(s), 10 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved