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;
}


目录
相关文章
基于 C++ 语言的迪杰斯特拉算法在局域网计算机管理中的应用剖析
在局域网计算机管理中,迪杰斯特拉算法用于优化网络路径、分配资源和定位故障节点,确保高效稳定的网络环境。该算法通过计算最短路径,提升数据传输速率与稳定性,实现负载均衡并快速排除故障。C++代码示例展示了其在网络模拟中的应用,为企业信息化建设提供有力支持。
61 15
|
18天前
|
企业员工数据泄露防范策略:基于 C++ 语言的布隆过滤器算法剖析[如何防止员工泄密]
企业运营过程中,防范员工泄密是信息安全领域的核心议题。员工泄密可能致使企业核心数据、商业机密等关键资产的流失,进而给企业造成严重损失。为应对这一挑战,借助恰当的数据结构与算法成为强化信息防护的有效路径。本文专注于 C++ 语言中的布隆过滤器算法,深入探究其在防范员工泄密场景中的应用。
37 8
从集思录可转债数据探秘:Python与C++实现的移动平均算法应用
本文探讨了如何利用移动平均算法分析集思录提供的可转债数据,帮助投资者把握价格趋势。通过Python和C++两种编程语言实现简单移动平均(SMA),展示了数据处理的具体方法。Python代码借助`pandas`库轻松计算5日SMA,而C++代码则通过高效的数据处理展示了SMA的计算过程。集思录平台提供了详尽且及时的可转债数据,助力投资者结合算法与社区讨论,做出更明智的投资决策。掌握这些工具和技术,有助于在复杂多变的金融市场中挖掘更多价值。
76 12
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
80 5
|
3月前
|
【C++面向对象——输入输出流】处理二进制文件(头歌实践教学平台习题)【合集】
本任务要求使用C++读取二进制文件并在每行前添加行号后输出到控制台。主要内容包括: 1. **任务描述**:用二进制方式打开指定文件,为每一行添加行号并输出。 2. **相关知识**: - 流类库中常用的类及其成员函数(如`iostream`、`fstream`等)。 - 标准输入输出及格式控制(如`cin`、`cout`和`iomanip`中的格式化函数)。 - 文件的应用方法(文本文件和二进制文件的读写操作)。 3. **编程要求**:编写程序,通过命令行参数传递文件名,使用`getline`读取数据并用`cout`输出带行号的内容。 4. **实验步骤**:参考实验指
104 5
C++多线程应用
【10月更文挑战第29天】C++ 中的多线程应用广泛,常见场景包括并行计算、网络编程中的并发服务器和图形用户界面(GUI)应用。通过多线程可以显著提升计算速度和响应能力。示例代码展示了如何使用 `pthread` 库创建和管理线程。注意事项包括数据同步与互斥、线程间通信和线程安全的类设计,以确保程序的正确性和稳定性。
112 5
|
6月前
|
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
2022年第十三届蓝桥杯大赛C/C++语言B组省赛题解
174 5
深入计算机语言之C++:类与对象(上)
深入计算机语言之C++:类与对象(上)
深入计算机语言之C++:C到C++的过度-1
深入计算机语言之C++:C到C++的过度-1
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等