C++语言基础 例程 二进制文件应用案例-阿里云开发者社区

开发者社区> 开发与运维> 正文

C++语言基础 例程 二进制文件应用案例

简介: 贺老师的教学链接  本课讲解 系统升级第一步:转换现有数据格式(附:数据文件点击打开链接) #include <iostream> #include <fstream> #include <cstdlib> using namespace std; typedef struct { int NO; char name[8]; in

贺老师的教学链接  本课讲解


系统升级第一步:转换现有数据格式(附:数据文件点击打开链接

#include <iostream>
#include <fstream>
#include <cstdlib>

using namespace std;
typedef struct
{
    int NO;
    char name[8];
    int chinese;
    int math;
    int english;
    int Comprehensive;
    int total;
} Student;  //高考学生信息
const int maxNum = 10000;
void display(Student*, int);


int main()
{
    ifstream asciiFile("asciidata.txt", ios::in);
    if(!asciiFile)
    {
        cerr<<"cannot open ascii file!"<<endl;
        exit(1);
    }
    int stuNum = 0;
    Student students[maxNum];

    //读入文本文件
    while(!asciiFile.eof())
    {
        asciiFile>>students[stuNum].NO;
        asciiFile>>students[stuNum].name;
        asciiFile>>students[stuNum].chinese;
        asciiFile>>students[stuNum].math;
        asciiFile>>students[stuNum].english;
        asciiFile>>students[stuNum].Comprehensive;
        asciiFile>>students[stuNum].total;
        stuNum++;
    }
    asciiFile.close();
    display(students, stuNum);
    //写入到二进制文件
    int i;
    ofstream binaryFile("binarydata.dat", ios::out|ios::binary);
    if(!binaryFile)
    {
        cerr<<"cannot open binary file!"<<endl;
        exit(1);
    }
    binaryFile.write((char*)&stuNum, sizeof(stuNum));
    for(i=0; i<stuNum; ++i)
    {
        binaryFile.write((char*)&students[i], sizeof(Student));
    }
    binaryFile.close();
    return 0;
}


void display(Student *s, int n)
{
    cout<<"共"<<n<<"名考生:"<<endl;
    int i;
    for(i=0; i<n; ++i)
    {
        cout<<i<<": "<<s[i].NO<<"\t";
        cout<<s[i].name<<"\t";
        cout<<s[i].chinese<<"\t";
        cout<<s[i].math<<"\t";
        cout<<s[i].english<<"\t";
        cout<<s[i].Comprehensive<<"\t";
        cout<<s[i].total<<"\t"<<endl;
    }
}


用二进制文件完成业务
#include <iostream>
#include <fstream>
#include <cstdlib>


using namespace std;
typedef struct
{
    int NO;
    char name[8];
    int chinese;
    int math;
    int english;
    int Comprehensive;
    int total;
} Student;  //高考学生信息
void display(Student*, int);
void sort(Student*, int);
int main()
{
    int stuNum = 0;
    Student *students;
    fstream binaryFile("binarydata.dat", ios::in|ios::out|ios::binary);
    if(!binaryFile)
    {
        cerr<<"cannot open binary file!"<<endl;
        exit(1);
    }
    //读入考生人数
    binaryFile.read((char*)&stuNum, sizeof(stuNum));


    //读入数据
    students = new Student[stuNum];
    int i;
    for(i=0; i<stuNum; ++i)
    {
        binaryFile.read((char*)&students[i], sizeof(Student));
    }
    display(students, stuNum);


    //各种操作(例排序,还可以查找、修改等)
    sort(students, stuNum);


    //查看操作结果
    //display(students, stuNum);
    //将数据再写入文件
    binaryFile.seekg(0, ios::beg);
    binaryFile.write((char*)&stuNum, sizeof(stuNum));
    for(i=0; i<stuNum; ++i)
    {
        binaryFile.write((char*)&students[i], sizeof(Student));
    }
    //关闭文件
    binaryFile.close();


    return 0;
}


void display(Student *s, int n)
{
    cout<<"共"<<n<<"名考生:"<<endl;
    int i;
    for(i=0; i<n; ++i)
    {
        cout<<i<<": "<<s[i].NO<<"\t";
        cout<<s[i].name<<"\t";
        cout<<s[i].chinese<<"\t";
        cout<<s[i].math<<"\t";
        cout<<s[i].english<<"\t";
        cout<<s[i].Comprehensive<<"\t";
        cout<<s[i].total<<"\t"<<endl;
    }
}


void sort(Student *s, int n)
{
    int i, j;
    Student temp;   //用于交换的中间变量
    for (i=0; i<n-1; i++)
        for(j=0; j<n-i-1; j++)
            if (s[j].NO>s[j+1].NO)
            {
                temp=s[j];
                s[j]=s[j+1];
                s[j+1]=temp;
            }
    return;
}


索引文件的建立
#include <iostream>
#include <fstream>
#include <cstdlib>


using namespace std;
typedef struct
{
    int NO;
    char name[8];
    int chinese;
    int math;
    int english;
    int Comprehensive;
    int total;
} Student;  //高考学生信息


typedef struct
{
    int NO;
    long offset;  //数据在文件中的偏移量
} StudentIndex;   //高考学生索引


void createIndex();
void writeIndex(StudentIndex *si, int n);


int main()
{
    createIndex();
    return 0;
}
/*
功能:创建索引
*/


void createIndex()
{
    int stuNum;
    StudentIndex *studentsIndex;  //索引表的起始地址
    Student student;
    ifstream binaryFile("binarydata.dat", ios::in|ios::binary);
    if(!binaryFile)
    {
        cerr<<"cannot open binary file!"<<endl;
        exit(1);
    }
    //建立索引
    binaryFile.read((char*)&stuNum, sizeof(stuNum));  //读入实际人数
    //读入数据,建立未排序的索引表
    studentsIndex = new StudentIndex[stuNum];
    int i, j;
    long mOffset;
    for(i=0; i<stuNum; ++i)
    {
        mOffset = binaryFile.tellg();
        binaryFile.read((char*)&student, sizeof(Student));
        studentsIndex[i].NO = student.NO;
        studentsIndex[i].offset = mOffset;   //记录对应学号学生数据的偏移量
    }
    //关闭数据文件
    binaryFile.close();
    //为索引表排序
    StudentIndex temp;   //用于交换的中间变量
    for (i=0; i<stuNum-1; i++)
        for(j=0; j<stuNum-i-1; j++)
            if (studentsIndex[j].NO>studentsIndex[j+1].NO)
            {
                temp=studentsIndex[j];
                studentsIndex[j]=studentsIndex[j+1];
                studentsIndex[j+1]=temp;
            }
    //将建好的索引表通过文件存储
    writeIndex(studentsIndex, stuNum);
    return;
}


/*
功能:将索引写入文件
参数:si - 索引表起始地址;n - 考生人数,索引记录条数
*/
void writeIndex(StudentIndex *si, int n)
{
    //打开文件
    ofstream indexFile("binarydata.idx", ios::out|ios::binary);
    if(!indexFile)
    {
        cerr<<"cannot open index file!"<<endl;
        exit(1);
    }
    int i;
    for(i=0; i<n; ++i)
    {
        //indexFile<<si[i].NO<<"\t"<<si[i].offset<<endl;  //索引用作文本文件时
       indexFile.write((char*)&si[i], sizeof(StudentIndex)); //索引用二进制文件时  
    }
    //关闭文件
    indexFile.close();
    return;
}


索引文件的利用
#include <iostream>
#include <fstream>
#include <cstdlib>


using namespace std;
typedef struct
{
    int NO;
    char name[8];
    int chinese;
    int math;
    int english;
    int Comprehensive;
    int total;
} Student;  //高考学生信息


typedef struct
{
    int NO;
    long offset;  //数据在文件中的偏移量
} StudentIndex;   //高考学生索引


//为方便起见,下面变量用全局变量表示。若用局部变量,各模块间通过引用传递参数亦可
fstream dataFile, indexFile;
int stuNum, maxNum;
StudentIndex *studentsIndex;  //索引表入口地址


//函数声明
void createIndex();
void writeIndex(StudentIndex *si, int n);
void init();
void work();
int chooseInMenu();
void done();
void displayByIndex();
void displayStudent(Student &s);


int main()
{
    char yn;
    cout<<"需要重建索引吗?(Y/N)";
    cin>>yn;
    if('Y'==yn||'y'==yn)
        createIndex();
    init();
    work();
    done();
    return 0;
}


/*
功能:创建索引
*/
void createIndex()
{
    int stuNum;
    StudentIndex *studentsIndex;  //索引表的起始地址
    Student student;
    ifstream binaryFile("binarydata.dat", ios::in|ios::binary);
    if(!binaryFile)
    {
        cerr<<"cannot open binary file!"<<endl;
        exit(1);
    }
    //建立索引
    binaryFile.read((char*)&stuNum, sizeof(stuNum));  //读入实际人数
    //读入数据,建立未排序的索引表
    studentsIndex = new StudentIndex[stuNum];
    int i, j;
    long mOffset;
    for(i=0; i<stuNum; ++i)
    {
        mOffset = binaryFile.tellg();
        binaryFile.read((char*)&student, sizeof(Student));
        studentsIndex[i].NO = student.NO;
        studentsIndex[i].offset = mOffset;   //记录对应学号学生数据的偏移量
    }
    //关闭数据文件
    binaryFile.close();
    //为索引表排序
    StudentIndex temp;   //用于交换的中间变量
    for (i=0; i<stuNum-1; i++)
        for(j=0; j<stuNum-i-1; j++)
            if (studentsIndex[j].NO>studentsIndex[j+1].NO)
            {
                temp=studentsIndex[j];
                studentsIndex[j]=studentsIndex[j+1];
                studentsIndex[j+1]=temp;
            }
    //将建好的索引表通过文件存储
    writeIndex(studentsIndex, stuNum);
    return;
}


/*
功能:将索引写入文件
参数:si - 索引表起始地址;n - 考生人数,索引记录条数
*/
void writeIndex(StudentIndex *si, int n)
{
    //打开文件
    ofstream indexFile("binarydata.idx", ios::out|ios::binary);
    if(!indexFile)
    {
        cerr<<"cannot open index file!"<<endl;
        exit(1);
    }
    int i;
    for(i=0; i<n; ++i)
    {
        //indexFile<<si[i].NO<<"\t"<<si[i].offset<<endl;  //索引用作文本文件时
        indexFile.write((char*)&si[i], sizeof(StudentIndex)); //索引用二进制文件时
    }
    //关闭文件
    indexFile.close();
    return;
}


/*
功能:初始化,为几个全局变量获得初值
*/
void init()
{
    //第一件工作:打开数据文件
    dataFile.open("binarydata.dat", ios::in|ios::out|ios::binary);
    if(!dataFile)
    {
        cerr<<"cannot open data file!"<<endl;
        exit(1);
    }
    //读入考生人数
    dataFile.read((char*)&stuNum, sizeof(stuNum));  //读入实际人数
    maxNum = stuNum * 1.1;   //最多人数多留10%的空间,以备增加数据用(本例用不着)
    studentsIndex = new StudentIndex[maxNum];  //为索引表分配空间


    //从索引文件中读取数据,保存在索引表中
    //在业务运行过程中,索引表独立工作,以发挥其速度优势
    //打开文件
    indexFile.open("binarydata.idx", ios::in|ios::binary);
    if(!indexFile)
    {
        cerr<<"cannot open index file!"<<endl;
        exit(1);
    }
    int i;
    for(i=0; i<stuNum; ++i)
    {
        indexFile.read((char*)&studentsIndex[i], sizeof(StudentIndex)); //索引用二进制文件时
    }
    //关闭文件
    indexFile.close();
    return;
}


/*
功能:完成"善后"工作
*/
void work()
{
    int iChoice;   //用于选择系统功能
    //办理业务
    do
    {
        iChoice = chooseInMenu();  //从菜单中获得功能代码
        switch(iChoice)
        {
        case 1:
            displayByIndex();  //按索引显示
            break;
        case 2:
            out<<"请设计函数searchStudent(),输入考号,在索引表中二分查找,然后到数据文件中读取数据并显示"<<endl;
            break;
        case 3:
            cut<<"请设计函数updateStudent(),输入考号,在索引表中二分查找,输入新值,并且更新数据文件中的数据"<<endl;
            break;
        case 4:
            cout<<"请设计函数addStudent(),输入考生息,保存到数据文件的最后,将新考生的信息插入在索引表中的合适位置,以使索引表与数据文件仍然同步"<<endl;
            break;
        case 5:
            cout<<"索引表与数据文件相配合开展工作,在工程中太实用了,请自提需求,尝试实现"<<endl;
            break;
        case 0:
            cout<<"欢迎您再来. "<<endl;
        }
    }
    while(iChoice);
    cout<<"什么也没有做!"<<endl;


}


/*
功能:显示菜单并由业务员选择
返回值:用户选择的功能,范围0-9
*/
int chooseInMenu()
{
    int i;
    while(1)
    {
        cout<<endl;
        cout<<"+---------------+"<<endl;
        cout<<"+ 1 按索引显示  +"<<endl;
        cout<<"+ 2 查询考生    +"<<endl;
        cout<<"+ 3 更新数据    +"<<endl;
        cout<<"+ 4 增加考生    +"<<endl;
        cout<<"+ 5 增加考生    +"<<endl;
        cout<<"+ 0 退出        +"<<endl;
        cout<<"+---------------+"<<endl;
        cout<<"请输入操作指令:"<<endl;
        cin>>i;
        if(i>=0 && i<=5)
            break;
        else
            cout<<"请重新选择功能\n"<<endl;
    }
    return i;
}


void done()
{
    //关闭数据文件
    dataFile.close();
    //若数据进行过增删改,索引表会发生变化,重新保存到文件中
    writeIndex(studentsIndex, stuNum);
}


void displayByIndex()
{
    Student stu;
    indexFile.seekg(ios::beg);
    int i;
    long location;
    cout<<"共"<<stuNum<<"名考生:"<<endl;
    for(i=0; i<stuNum; ++i)
    {
        location = studentsIndex[i].offset;
        dataFile.seekg(location, ios::beg);
        dataFile.read((char*)&stu, sizeof(Student));
        cout<<i<<": ";
        displayStudent(stu);
    }
}


void displayStudent(Student &s)
{
    cout<<s.NO<<"\t";
    cout<<s.name<<"\t";
    cout<<s.chinese<<"\t";
    cout<<s.math<<"\t";
    cout<<s.english<<"\t";
    cout<<s.Comprehensive<<"\t";
    cout<<s.total<<"\t"<<endl;
}


版权声明:本文首发在云栖社区,遵循云栖社区版权声明:本文内容由互联网用户自发贡献,版权归用户作者所有,云栖社区不为本文内容承担相关法律责任。云栖社区已升级为阿里云开发者社区。如果您发现本文中有涉嫌抄袭的内容,欢迎发送邮件至:developer2020@service.aliyun.com 进行举报,并提供相关证据,一经查实,阿里云开发者社区将协助删除涉嫌侵权内容。

分享:
开发与运维
使用钉钉扫一扫加入圈子
+ 订阅

集结各类场景实战经验,助你开发运维畅行无忧

其他文章