实验十 文件读写 1. 学生成绩管理(二进制文件读写)

学生成绩管理(二进制文件读写)
【问题描述】
在以下问题中,定义学生的结构体student,录入学生信息,并存入到二进制文件grade.bin中,要求存入的是按照总成绩从大到小的顺序存储,数据可以分多次录入,每次录入前,都将显示文件中已有的数据,其具体形式如下:

No: 3
Name: Hong
Sex: F
Age: 9
Scores: 123.000000 531241.000000

No: 2
Name: Zhang
Sex: F
Age: 98
Scores: 123.000000 434.000000

No: 1
Name: Wang
Sex: M
Age: 32
Scores: 12.000000 54.000000

Input continue(y/n)?
在提示Input continue(y/n)?下输入’y’,则可以继续输入,否则将退出。继续输入的内容将与现有的数据进行重新按总分从大到小的顺序排列后重新写入文件grade.bin中。

【输入形式】

Input continue(y/n)?y
No: 15
Name: LiuYing
Sex(M/F): M
Age: 25
Chinese score: 100
Computer score: 85
Input continue(y/n)?y
No: 16
Name: WangLiLi
Sex(M/F): F
Age: 23
Chinese score: 95.5
Computer score: 68.8
Input continue(y/n)?n
【输出形式】文件

调试时的测试文件grade.bin:下载链接为http://gofile.me/4tv7L/5O3fI22ZP,(下载文件``竟不存在,这究竟是天性的沦丧还是人性的泯灭还是我太垃圾了? )请将这个文件下载到与源代码相同的文件夹下。

#include  <iostream>
using  namespace  std;

/*
        定义结构体student用于表示学生的基本信息,采用链表结构
*/
struct  student
{
        int  no;                                                                                                                                          //  学号
        char  name[20],  sex;                                                                                              //  姓名以及性别,  请思考如果将name[20]修改为*name,结果将会怎样,还适合本题的处理方式吗?
        int  age;                                                                                                                                      //  年龄
        float  chinese,  computer;                                                                                  //  表示两门课程的成绩
        student  *next;
        bool  operator<(const  student  &another)  const            //  重载运算符  <  (小于),用于结构体对象之间的比较,在LinkSort中比较链表的两个节点大小
        {
                return
(chinese + computer) < (another.chinese + another.computer)
;
        }
};

student*  ReadFile(FILE  *fp,  student  *head,  int  &n);            //  从二进制文件(文件指针为fp)中将所有数据读入,存储于以head为头指针的链表中
void  display(student  *head);                                                                                    //  用于显示链表的内容
void  WriteFile(FILE  *fp,  student  *head);                                                //  将以head为头指针的链表中的数据写入二进制文件(文件指针为fp)
student*  input(student  *head,  int  &n);                                                      //  输入新的数据,将新数据连接到链表末尾
student*  LinkSort(student  *head,  const  int  &n);                        //  实现对链表的排序,按总成绩从大到小排列,冒泡排序
void  swapNode(student  *s,  student  *q);                                              //  实现对链表节点的数据交换,用于排序,  在函数LinkSort中调用

int  main()
{
        int  n  =  0;                                                                                                                                                        //  定义变量n,用于存储学生人数
        student  *head  =  NULL;                                                                                                          //  链表头指针
        FILE  *fp;

        fp  =  fopen("grade.bin",
"rb+"
);                                                    //  打开二进制文件,用于读写以及添加记录
        head  =  ReadFile(
fp, head, n
);
        display(head);
        fclose(fp);

        head  =  input(head,  n);
        head  =  LinkSort(head,  n);

        fp  =  fopen("grade.bin",  "wb");
        WriteFile(fp,  head);
        fclose(fp);

        return  0;
}

student*  ReadFile(FILE*  fp,  student*  head,  int  &n)              //本函数将调用fread函数读数据块,这个函数非常有用
{
        student  *q  =  head;
        if  (head)
                while(q->next)  q  =  q->next;

        while(1)
        {
                student  *p  =  new  student;                                                                          //  用于存储读入的数据块
                if  (!fread(
p,sizeof(student),1,fp
))                                                                        //  从文件fp中读入大小为sizeof(student)的数据块,保存于内存缓冲区p之中,  fread将返回读入的字节数,如果为0,则结束读文件
                {
                        delete  p;
                        break;
                }
                p->next  =  NULL;
                if  (!head)
                        head  =  p;
                else
                        q->next  =  p;

                q  =  p;
                n++;
        }

        return  head;
}

void  WriteFile(
FILE  *fp,  student  *head
)                              //本函数将调用fwrite函数写数据块,这个函数非常有用
{
        while(head)
        {
                fwrite(
head,sizeof(student),1,fp
);                          //  将缓冲区head中的内容(数据块)写入文件中
                head  =  head->next;
        }
}


void  display(student*  head)
{
        student  *p  =  head;
        while(p)
        {

printf("No:  ");
            cout << &p->no << endl;
            printf("Name:  ");
            cout << p->name << endl;
            printf("Sex(M/F):  ");
            cout << p->sex << endl;
            printf("Age:  ");
            cout << &p->age<<endl;
            printf("Chinese  score:  ");
            cout << &p->chinese << endl;
            printf("Computer  score:  ");
            cout<< &p->computer<<endl;
            p=p->next;//  输出链表节点内容
        }
}

student*  input(student*  head,  int  &n)
{

        student  *q  =  head;

        if  (head)
                while(q->next)  q  =  q->next;

        while(1)
        {
                printf("Input  continue(y/n)?");
                if  (getchar()  !=  'y')
                        break;

                student  *p  =  new  student;

                printf("No:  ");
                scanf("%d",  &p->no);
                getchar();
                printf("Name:  ");
                gets(p->name);
                printf("Sex(M/F):  ");
                p->sex  =  getchar();
                printf("Age:  ");
                scanf("%d",  &p->age);
                printf("Chinese  score:  ");
                scanf("%f",  &p->chinese);
                printf("Computer  score:  ");
                scanf("%f",  &p->computer);
                p->next  =  NULL;
                getchar();

                if  (!head)
                        head  =  p;
                else
                        q->next  =  p;

                q  =  p;
                n++;
        }

        return  head;
}

student*  LinkSort(student*  head,  const  int  &n)
{
        student  *p;
        for(int  i  =  1;  i  <=  n  -  1;  i++)
        {
                p  =  head;
                for(int  j  =  1;  j  <=  n  -  i;  j++)
                {
                        if  (*p  <  *p->next)
                        {
                                swapNode(p  ,  p->next);
//  交换节点值
                        }
                        p  =  p->next;
                }
        }

        return  head;
}

void  swapNode(student*  s,  student*  q)
{
        student  *snext  =  s->next,  *qnext  =  q->next,  tmp;
        tmp  =  *s;
        *s  =  *q;
        *q  =  tmp;
        s->next  =  snext;
        q->next  =  qnext;
}

用到FILE结构体中的函数:

1.FILE *fopen(const char *filename,const char *mode)
例如:fp = fopen(“file.txt”, “w+”);

2.size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

  1. void *ptr:指向用于储存读取内容的内存块。void是无类型指针,可以指向任意类型的数据。
  2. size_t size:读取的内存块的大小,以字节为单位。可以用sizeof() 获得。
  3. size_t nmemb:读取的内存块的次数。
  4. FILE *stream:指向要读取的文件(输入流)的指针。

3.size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream)
与fread()类似。

注:fwrite和fread的返回值不是字节数,而是实际读取的规定大小代码块的个数。可能与函数调用的第三个参数不同。











(咸鱼+菜鸟的所有文章都用于方便自己总结一些易错内容和知识点,如有错漏,纯属应当(滑稽逃跑))

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值