数据结构实践——索引文件

本文是针对[数据结构基础系列(11):文件]中的实践项目。

【项目】索引文件
有若干学生的成绩数据如下,将这些数据保存到st数组中:

  学号     姓名    年龄 性别 语文 数学 英语
    1      陈华    20   男   78   90   84
    5      张明    21   男   78   68   92
    8      王英    20   女   86   81   86
    3      刘丽    21   女   78   92   88
    2      许可    20   男   80   83   78
    4      陈军    20   男   78   88   82
    7      马胜    21   男   56   67   75
    6      曾强    20   男   78   89   82

基于这些数据,编程序实现下面的功能:
(1)将st数组中学生记录写入stud.dat文件作为主文件
(2)输出主文件中的学生记录
(3)建立与主文件相对应的索引文件,其中每个记录由两个字段组成:学号和该学生记录在数据文件中的位移量(例:上面列出数据中学号为2的学生许可,其位移量是5。由于本例用定长文件,可以根据位移量计算记录在主文件中的相对地址)。索引文件按学号有序。
(4)输出索引文件中的全部记录
(5)根据用户输入的学号,利用索引文件,用二分查找法找到对应的记录号,再通过主文件输出该记录
(6)是否有想法,将这个项目再扩充了?加大数据量、哈希文件、多关键字文件……

[参考解答]

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#define MaxRec 100 //最多的记录个数
typedef struct Index        //定义索引文件结构
{
    int no;                 //学号
    long offset;            //主文件中的记录号
} Index;
typedef struct
{
    int no;                 //学号
    char name[10];          //姓名
    int age;                //年龄
    char sex[3];            //性别
    int deg1,deg2,deg3;     //课程1-课程3成绩
} StudType;
void InsertSort(Index R[],int n) //采用直接插入排序法对R[0..n-1]按学号递增排序
{
    int i,j;
    Index temp;
    for (i=1; i<n; i++)
    {
        temp=R[i];
        j=i-1;
        while (j>=0 && temp.no<R[j].no)
        {
            R[j+1]=R[j];    //将关键字大于R[i].key的记录后移
            j--;
        }
        R[j+1]=temp;        //在j+1处插入R[i]
    }
}
void CreatIdxFile()         //建立索引文件
{
    FILE *mfile,*idxfile;
    Index idx[MaxRec];
    StudType st;
    int n=0,i;
    if ((mfile=fopen("stud.dat","rb"))==NULL)
    {
        printf(" 提示:不能打开主文件\n");
        return;
    }
    if ((idxfile=fopen("index.dat","wb"))==NULL)
    {
        printf(" 提示:不能建立索引文件\n");
        return;
    }
    i=0;
    while ((fread(&st,sizeof(StudType),1,mfile)))
    {
        idx[i].no=st.no;
        idx[i].offset=++n;
        i++;
    }
    InsertSort(idx,n);  //对idx数组按no值排序
    rewind(idxfile);
    for (i=0; i<n; i++)
        fwrite(&idx[i],sizeof(Index),1,idxfile);
    fclose(mfile);
    fclose(idxfile);
    printf(" 提示:索引文件建立完毕\n");
}
void OutputMainFile()   //输出主文件全部记录
{
    FILE *mfile;
    StudType st;
    int i=1;
    if ((mfile=fopen("stud.dat","rb"))==NULL)
    {
        printf(" 提示:不能读主文件\n");
        return;
    }
    printf(" ----学生成绩表----\n");
    printf("记录号 学号 姓名 年龄 性别 语文 数学 英语\n");
    while ((fread(&st,sizeof(StudType),1,mfile))==1)
    {
        printf("%6d%5d%10s%6d%5s%5d%5d%5d\n",i,st.no,st.name,st.age,st.sex,st.deg1,st.deg2,st.deg3);
        i++;
    }
    fclose(mfile);
}
void OutputIdxFile()    //输出索引文件全部记录
{
    FILE *idxfile;
    Index irec;
    printf(" ----学生索引表----\n");
    printf("\t学号 记录号\n");
    if ((idxfile=fopen("index.dat","rb"))==NULL)
    {
        printf(" 提示:不能读索引文件\n");
        return;
    }
    while ((fread(&irec,sizeof(Index),1,idxfile))==1)
        printf("\t%5d%6ld\n",irec.no,irec.offset);
    fclose(idxfile);
}
void ReadIndexFile(Index idx[MaxRec],int &n)    //读索引文件数据存入idx数组中
{
    int j;
    FILE *idxfile;
    if ((idxfile=fopen("index.dat","rb"))==NULL)
    {
        printf(" 提示:索引文件不能打开\n");
        return;
    }
    fseek(idxfile,0,2);
    j=ftell(idxfile);       //j求出文件长度
    rewind(idxfile);
    n=j/sizeof(Index);      //n求出文件中的记录个数
    fread(idx,sizeof(Index),n,idxfile);
    fclose(idxfile);
}
int SearchNum(Index idx[],int n,int no) //在含有n个记录的索引文件idx中查找学号为no的记录对应的记录号
{
    int mid,low=0,high=n-1;
    while (low<=high)                   //二分查找
    {
        mid=(low+high)/2;
        if (idx[mid].no>no)
            high=mid-1;
        else if (idx[mid].no<no)
            low=mid+1;
        else    //idx[mid].no==no
            return idx[mid].offset;
    }
    return -1;
}
void FindStudent()          //输出指定学号的记录
{
    int no;
    FILE *mfile;
    Index idx[MaxRec];
    StudType st;
    int i,n;
    if ((mfile=fopen("stud.dat","rb+"))==NULL)
    {
        printf(" 提示:主文件中没有任何记录\n");
        return;
    }
    ReadIndexFile(idx,n);       //读取索引数组idx
    printf("输入学号:");
    scanf("%d",&no);
    i=SearchNum(idx,n,no);      //在idx中查找
    if (i==-1)
        printf(" 提示:学号%d不存在\n",no);
    else
    {
        fseek(mfile,(i-1)*sizeof(StudType),SEEK_SET); //由记录号直接跳到主文件中对应的记录
        fread(&st,sizeof(StudType),1,mfile);
        printf("%5d%10s%6d%5s%5d%5d%5d\n",st.no,st.name,st.age,st.sex,st.deg1,st.deg2,st.deg3);
    }
    fclose(mfile);
}
void WriteFile(StudType st[], int n)  //将st数组中的n个学生记录写入stud.dat文件中
{
    int i;
    FILE *fp;
    if ((fp=fopen("stud.dat","wb"))==NULL)
    {
        printf("\t提示:不能创建stud.dat文件\n");
        return;
    }
    for (i=0; i<n; i++)
        fwrite(&st[i],1,sizeof(StudType),fp);
    fclose(fp);
    printf(" 提示:文件stud.dat创建完毕\n");
}
int main()
{
    int n=8,sel;        //n为实际学生人数
        StudType st[]= {
  {
  1,"陈华",20,"男",78,90,84},
        {
  5,"张明",21,"男",78,68,92},
        {
  8,"王英",20,"女",86,81,86},
        {
  3,"刘丽",21,"女",78,92,88},
        {
  2,"许可",20,"男",80,83,78},
        {
  4,"陈军",20,"男",78,88,82},
        {
  7,"马胜",21,"男",56,67,75},
        {
  6,"曾强",20,"男",78,89,82}
    };
    printf("建立主文件\n");
    WriteFile(st,n);        //建立主文件
    do
    {
        printf("1:输出主文件 2:建索引文件 3:输出索引文件 4:按学号查找 0:退出:");
        scanf("%d",&sel);
        switch(sel)
        {
        case 1:
            OutputMainFile();
            break;
        case 2:
            CreatIdxFile();
            break;
        case 3:
            OutputIdxFile();
            break;
        case 4:
            FindStudent();
            break;
        }
    }
    while (sel!=0);
    return 0;
}
    原文作者:迂者-贺利坚
    原文地址: https://blog.csdn.net/sxhelijian/article/details/50245013
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞