📄 changerecord.cpp
字号:
//changerecord.cpp
///////////////////////////////////////////////////////////////////
#include"changerecord.h"
#include<iomanip.h>
#include<stdio.h>
#include<fstream.h>
#include<string.h>
//顺序打印出主文件fname1中的每个记录
////////////////////////////////////////////////////////////////////
void ChangeRecord::PrintMainFile(char* fname1)
{
ifstream fin(fname1, ios::in|ios::nocreate|ios::binary);
if(!fin)
{
cerr<<fname1<<' '<<"not find!"<<endl;
return;
}
ElemType x;
fin.seekg(0,ios::end); //将文件指针移动到文件末
int b1=sizeof(ElemType);
int n=fin.tellg()/b1; //用n表示文件所含的记录数
int j=0;
fin.seekg(0); //将文件指针移动到文件尾
cout<<setw(20)<<"关键字"<<setw(20)<<"记录标识"
<<setw(14)<<"数据内容"<<endl;
for(int i=0;i<n;i++)
{
fin.read((char*) &x, b1); //从文件中读出一条记录
if(i%1==0)
cout<<endl; //每行显示1条记录
if(x.key==DeleteMark)
continue;
if(x.kind==1) //链接方式输出链接文件的二进制内容
{
PrintLinkFile(x);
}
if(x.kind==0) //字节流输出数据内容
{
cout<<setw(20)<<x.key<<setw(20)<<x.Mark
<<setw(x.len+5)<<x.Elem;
}
}
cout<<endl;
fin.close();
}
//顺序打印出索引文件fname2中每个有序索引项
///////////////////////////////////////////////////////////////////////////
void ChangeRecord::PrintIndexFile(char* fname2)
{
ifstream fin(fname2, ios::in|ios::nocreate|ios::binary);
if(!fin)
{
cerr<<fname2<<' '<<"not find!"<<endl;
return;
}
IndexItem x;
fin.seekg(0,ios::end); //将文件指针移动到文件末
int b2=sizeof(IndexItem);
int n=fin.tellg()/b2; //用n表示文件所含的记录数
fin.seekg(0); //将文件指针移动到文件尾
cout<<setw(20)<<"关键字"<<setw(20)<<"记录存储位置"<<endl;
for(int i=0;i<n;i++)
{
fin.read((char*) &x, b2); //从文件中读出一个索引项
if(i%1==0)
cout<<endl; //每行显示1个数据
cout<<setw(20)<<x.key<<setw(20)<<x.next;
}
cout<<endl;
fin.close();
}
//顺序打印出主文件fname1中的已删除的记录
////////////////////////////////////////////////////////////////////
void ChangeRecord::PrintDeleteFile(char* fname1)
{
ifstream fin(fname1, ios::in|ios::nocreate|ios::binary);
if(!fin)
{
cerr<<fname1<<' '<<"not find!"<<endl;
return;
}
ElemType x;
fin.seekg(0,ios::end); //将文件指针移动到文件末
int b1=sizeof(ElemType);
int n=fin.tellg()/b1; //用n表示文件所含的记录数
int j=0;
fin.seekg(0); //将文件指针移动到文件尾
cout<<setw(20)<<"关键字"<<setw(20)<<"记录标识"
<<setw(14)<<"数据内容"<<endl;
for(int i=0;i<n;i++)
{
fin.read((char*)&x, b1); //从文件中读出一条记录
if(i%1==0)
cout<<endl; //每行显示1条记录
if(x.key==DeleteMark)
{
if(x.kind==1) //链接方式输出链接文件的二进制内容
{
PrintLinkFile(x);
}
if(x.kind==0) //字节流输出数据内容
{
cout<<setw(20)<<x.key<<setw(20)<<x.Mark
<<setw(x.len+5)<<x.Elem;
}
}
else continue;
}
cout<<endl;
fin.close();
}
//向物理文件名为fname1指针所指字符串的主文件中追加n个记录
//////////////////////////////////////////////////////////////////////////
void ChangeRecord::MFAppend(char* fname1, char* fname2, ElemType a[], int n)
{
//定义一个输出文件流对象ofs与主文件相联系
ofstream ofs(fname1,ios::app|ios::binary);
if(!ofs)
{
cerr<<fname1<<' '<<"not open!"<<endl;
return;
}
int i;
int b1=sizeof(ElemType);
//把文件指针移动到文件尾
ofs.seekp(0, ios::end);
//求出当前文件长度
int flen=ofs.tellp()/b1;
//把a数组中的n个记录写入到文件中
for(i=0; i<n; i++)
ofs.write((char*) &a[i], b1);
//关闭文件ofs
ofs.close();
//把a中n个记录的索引项依次插入到索引文件fname2中
IndexItem x;
for(i=0; i<n; i++)
{
x.key=a[i].key;
x.next=flen+i;
IFInsert(fname2, x);
}
}
//从物理文件名为fname1指针所指字符串的主文件中删除n个记录
//////////////////////////////////////////////////////////////////////////
void ChangeRecord::MFDelete(char* fname1, char* fname2, KeyType a[], int n)
{
//定义一个输入输出文件流对象fio与主文件相联系
fstream fio(fname1,ios::in|ios::out|
ios::nocreate|ios::binary);
if(!fio)
{
cerr<<fname1<<' '<<"not open!"<<endl;
return;
}
int b1=sizeof(ElemType);
IndexItem x;
ElemType y;
int i;
//依次删除每个记录
for(i=0; i<n; i++)
{
x.key=a[i];
bool k=IFDelete(fname2,x);
if(!k)
{
cout<<" ";
cout<<"关键字为"<<x.key<<"的记录不存在"<<endl;
continue;
}
fio.seekg(x.next*b1);
fio.read((char*) &y, b1);
y.key=DeleteMark;
fio.seekg(-b1, ios::cur);
fio.write((char*) &y, b1);
cout<<" ";
cout<<"关键字为"<<x.key<<"的记录被删除"<<endl;
}
fio.close();
}
//从物理文件名为fname1指针所指字符串的主文件中查找n个记录
////////////////////////////////////////////////////////////////////////////
void ChangeRecord::MFSearch(char* fname1, char* fname2, KeyType a[], int n)
{
//定义一个输入输出文件流对象ifs与主文件相联系
ifstream ifs(fname1,ios::in|ios::nocreate|ios::binary);
if(!ifs)
{
cerr<<fname1<<' '<<"not open!"<<endl;
return;
}
int b1=sizeof(ElemType);
IndexItem x;
ElemType y;
int i;
//依次查找每个记录
for(i=0; i<n; i++)
{
x.key=a[i];
bool k=IFSearch(fname2,x);
if(!k)
{
cout<<" ";
cout<<"查找关键字为"<<x.key<<"的记录失败!"<<endl;
continue;
}
ifs.seekg(x.next*b1);
ifs.read((char*) &y, b1);
cout<<" ";
cout<<"查找关键字为"<<x.key<<"的记录成功!"<<endl;
cout<<"=========================================================="<<endl;
cout<<" 该记录内容为"<<endl;
cout<<"=========================================================="<<endl;
if(y.kind==1) //链接方式输出链接文件的二进制内容
{
PrintLinkFile(y);
}
if(y.kind==0) //字节流输出数据内容
{
cout<<setw(20)<<y.key<<setw(20)<<y.Mark
<<setw(y.len+5)<<y.Elem;
}
cout<<endl;
}
ifs.close();
}
//把一个记录的索引项插入到有序数组A中
///////////////////////////////////////////////////////////////////////////
void ChangeRecord::SeqInsert(IndexItem A[], int mm, IndexItem x)
{
for(int i=mm-1; i>=0; i--)
{
//从尾部向前为寻找插入位置进行顺序比较和移动
if(A[i].key>x.key)
A[i+1]=A[i];
else
{
A[i+1]=x;
break;
}
}
if(i<0)
A[0]=x;
}
//向由fname2指针所表示的索引有序文件中插入x索引项
/////////////////////////////////////////////////////////////////////////////
void ChangeRecord::IFInsert(char *fname2, IndexItem x)
{
//以输入方式打开由fname2指针所表示的索引有序文件
ifstream ifs(fname2, ios::in|ios::binary);
if(!ifs)
{
cerr<<fname2<<' '<<"not open!"<<endl;
return;
}
//以输出方式打开temp文件
ofstream ofs("temp",ios::out|ios::binary);
if(!ofs)
{
cerr<<"temp"<<' '<<"not open!"<<endl;
return;
}
//动态定义一个具有m+1个元素的数组A
IndexItem* A=new IndexItem[m+1];
//将原文件指针指向文件开始位置,此语句可以省略
ifs.seekg(0);
//通过while循环完成插入操作
int b2=sizeof(IndexItem);
while(1)
{
ifs.read((char*)A, m*b2);
int s=ifs.gcount()/b2;
//读入数组A的世纪索引项数被存入s中
if(s==m)
{
if(A[m-1].key<x.key)
{
ofs.write((char*)A, m*b2);
}
else
{
SeqInsert(A, m, x); //将x索引项插入到有序数组A中
ofs.write((char*)A,(m+1)*b2);
while(!ifs.eof())
{
//把原文件中剩余的所有记录写入到结果文件中
ifs.read((char*)A, m*b2);
s=ifs.gcount()/b2;
ofs.write((char*)A, s*b2);
}
break; //退出while(1)循环
}
}
else
{
SeqInsert(A, s, x);
ofs.write((char*)A, (s+1)*b2);
break; //处理完最后一个数据块后退出while(1)循环
}
}
delete [] A;
ifs.close();
ofs.close();
remove(fname2);
rename("temp", fname2);
}
//从有序数组A中删除一个关键字为x.key的索引项
/////////////////////////////////////////////////////////////////////////////
bool ChangeRecord::SeqDelete(IndexItem A[], int mm, IndexItem& x)
{
//从数组A的首元素开始顺序查找关键字为x.key的索引项
int i=0;
while(i<mm && A[i].key<x.key)
i++;
//若不存在待删除的索引项则返回假
if(i==mm || A[i].key!=x.key) return false;
//被删除的索引项赋给x带回
x=A[i];
//使i1至m-1的所有元素前移一个位置
for(int j=i+1; j<mm; j++)
A[j-1]=A[j];
//返回真表示删除成功
return true;
}
//从由name2指针所表示的索引有序文件中删除关键字为x.key的索引项,并由x带回被删除的索引项
///////////////////////////////////////////////////////////////////////////////////////////
bool ChangeRecord::IFDelete(char*fname2,IndexItem&x)
{
//以输入方式打开由fname2指针所表示的索引有序文件
ifstream ifs(fname2, ios::in|ios::nocreate|ios::binary);
if(!ifs)
{
cerr<<fname2<<' '<<"not found!"<<endl;
return false;
}
//以输出方式打开temp文件
ofstream ofs("temp",ios::out|ios::binary);
if(!ofs)
{
cerr<<"temp"<<' '<<"not open!"<<endl;
return false;
}
int b2=sizeof(IndexItem);
//动态定义一个具有m个元素的数组A
IndexItem* A=new IndexItem[m];
//用d等于true或false表示删除是否成功
bool d;
//通过while完成删除操作
while(1)
{
ifs.read((char*)A, m*b2);
int s=ifs.gcount()/b2;
//读入数组A的实际索引项数被存入s中
if(s==m)
{
if(A[m-1].key<x.key)
{
ofs.write((char*)A, m*b2);
}
else
{
d=SeqDelete(A, m, x);
if(d)
ofs.write((char*)A,(m-1)*b2);
else
ofs.write((char*)A,m*b2);
while(!ifs.eof())
{
//把原文件中剩余的所有记录写入到结果文件中
ifs.read((char*)A, m*b2);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -