//本类可自动检查游戏存档中的数值
//属于模板类
//T代表要寻找数据的类型//如金钱,生命等属于整型
//但不排除以后要查找其他类型的数据。为了可扩充性,使用了模板。
template <typename T>
class CheckBinaryFile{
public:
typedef fstream::off_type AddressType;//要找的数据在文件中的地址类型
CheckBinaryFile();//构造函数
void Run();
private:
static const int MaxByte=sizeof(T);//要查找的数据的类型所占的字节数
const int CharSize;
EInputStream CIN;//一个加强输入流(第三方类)
string FileName;//文件名称
T OldData;//输入的要查找的数据
int ByteNumber;//要查找的数据所占的字节数
//mutable关键字是const的反义作用,容易变动的变量经常使用它
mutable bool InputIsOk;
//用于读的文件对象
mutable ifstream BinaryFile;
mutable list<AddressType> AddressList;
//操作方法
void Input();
int Check() const;
void SaveAddressToFile(ostream&) const;//最后的"const"作用是防止修改本类对象的状态,即除mutable关键字标识的变量外其他都不可在此函数内做修改
void AutoModifySave(const T&) const;//在函数内防止修改T类型的参数
};
template <typename T>
//如果是static声明的静态变量在类体内做了声明,则在类外必须再做定义,而且只能被声明一次
const int CheckBinaryFile<T>::MaxByte;
//源文件
//构造函数
template <typename T>
CheckBinaryFile<T>::CheckBinaryFile():CharSize(char),CIN(cin){
InputIsOk=true;
Input();
//CharSize 为sizeof(char),把cin 绑定到CIN。由于CharSize是常量,必须在构造函数的初始化列表中设定。
}
//私有函数:输入成员函数
template <typename T>
void CheckBinaryFile<T>::Input()
{
//打开指定的输入文件名的二进制文件
cout<<"Binary Filename:/t";
cin>>FileName;
BinaryFile.open(FileName.c_str(),ios::in|ios::binary);
if(!BinaryFile)
{
InputIsOk=false;
cerr<<"open file failed!/n";
return;
}
//输入要查找的数据
cout<<"the Integer you want to search:/t";
CIN>>OldData;
//要找的数据的所占的数据位(字节数)
cout<<"byte number:(1--"<<CheckBinaryFile<T>::MaxByte<<"):/t";
CIN>>ByteNumber;
//字节数是否溢出的检查
if(ByteNumber<1||ByteNumber>CheckBinaryFile<T>::MaxByte)
{
ByteNumber=CheckBinaryFile<T>::MaxByte;
// cout<<"Byte number was amended to "<<ByteNumber<<endl;
cout<<"Byte number was amended to "<<CheckBinaryFile<T>::ByteNumber<<endl;//???????????????
}
}
//私有函数:检查输入的二进制文件中有多少个OldData,并保存地址到list链表对象中
//memory.h
template <typename T>
int CheckBinaryFile<T>::Check() const{
//将数据地址转换为字符串地址
const char* p=reinterpret_cast<const char*>(&OldData);
char Range[CheckBinaryFile<T>::MaxByte];
int Occurs=0;
AddressType Addr=0;
//填充0
memset(Range,0,CheckBinaryFile<T>::MaxByte*CharSize);
BinaryFile.read(Range,CharSize*ByteNumber);//填满Range
//如果读文件成功
while(BinaryFile)
{
if(memcmp(p,Range,CharSize*ByteNumber)==0)
{
AddressList.push_back(Addr);
++Occurs;
}
//删除一个最旧的
memcpy(Range,&Range[1],CharSize*(ByteNumber-1));
//读最新
BinaryFile.read(&Range[ByteNumber-1],CharSize);
++Addr;
}
//返回匹配数量
return Occurs;
}
//私有函数:保存找到的地址到文件
template <typename T>
void CheckBinaryFile<T>::SaveAddressToFile(ostream& os) const
{
copy(AddressList.begin(),AddressList.end(),ostream_iterator<T>(os,"/t"));
}
//私有函数:保存修改结果分别为一个文件
template <typename T>
void CheckBinaryFile<T>::AutoModifySave(const T& NewValue) const
{
list<AddressType>::const_iterator Beg=AddressList.begin(),End=AddressList.end();
const char *p=reinterpret_cast<const char*>(&NewValue);
for(;Beg!=End;++Beg){
//每个地址都要重新开头读
BinaryFile.clear();//清除错误状态
BinaryFile.seekg(0,ios::beg);//指向文件开头,准备读取
AddressType Addr=0;
char ch;
stringstream NewFile;
NewFile<<"@"<<*Beg;
string NewFileName(NewFile.str());
ofstream Write(NewFileName.c_str(),IOS::out|IOS::binary);
//文件对象错误
if(!Write)
{
cerr<<"NewFileName"<<" Failed!/n";
continue;
}
while(Addr<*Beg&&BinaryFile)
{
//小于地址内容
BinaryFile.read(&ch,CharSize);
Write.write(&ch,CharSize);
++Addr;
}
for(int k=0;k<ByteNumber;++k)
{
BinaryFile.read(&ch,CharSize);
}
Write.write(p,CharSize*ByteNumber);
while(BinaryFile)
{
BinaryFile.read(&ch,CharSize);
Write.write(&ch,CharSize);
}
Write.close();
cout<<NewFileName<<"...successfully./n";
//下次循环的时候文件已经成为bad状态,要清除这个状态
}//for
}
//公有函数:void Run();
template <typename T>
void CheckBinaryFile<T>::Run()
{
if(InputIsOk==false)
return;
//查找到的地址数量
const int Occurs=Check();
cout<<Occurs<<" different address were found!/n";
//没有找到内存地址,返回
if(Occurs==0) return;
//提示保存cout<<"Save address info to files(y/n)?/t";
cout<<"Save address info into files?(y/n)?/t";
char YN;
CIN>>YN;
if(YN=='Y'||YN=='y'){
cout<<"Address file name:/t";//提示输入保存的地址文件的名字
string AddressFileName;
CIN>>AddressFileName;
ofstream Save(AddressFileName.c_str(),ios::out);
if(!Save)
{
cerr<<"Create log file:"<<AddressFileName<<" error!/n";
}else{
SaveAddressToFile(Save);
}
Save.close();
}
cout<<"Modify binary file automatically(y/n)?/t";
CIN>>YN;
if(YN=='Y'||YN=='y')
{
cout<<"New value:/t";
T NewValue;
CIN>>NewValue;
system("dir>@tmp");//下句删除文件在不存在@开头的文件的时候错误,故首先建立一个名为@temp的文件
system("del @*/q");//执行DOS命令删除所有以@开头的文件
//将修改的文件分别保存一个单独的文件
AutoModifySave(NewValue);
}
}
//扩展1.取得2个地址文件的交集
//核心方法:set_intersection函数
template <typename T>
void GetInersection()
{
EInputStream CIN(cin);
//提示输入几个交叉的文件名,使用不存在的集合文件来结束输入
cout<<"Input some text filenames for reading,end with a nonexistent one:/n";
string fn;
CIN>>fn;
ifstream Read(fn.c_str());
if(!Read)
{
cerr<<"Open "<<fn<<" failed!/n";
return;
}
vector<T> V1;
//copy(istream_iterator<T>(Read),istream_iterator<T> (),back_inserter(V1));//保存file1的内容到V1
//保存file1的内容到V1中
copy(istream_iterator<T>(Read),istream_iterator<T>(),back_inserter(V1));
CIN<<fn;
Read.clear();
Read.close();
Read.open(fn.c_str());
if(!Read)
{
cerr<<"Open the file failed!/n";
return;
}
vector<T> V2,V3;
copy(istream_iterator<T>(Read),istream_iterator<T>(),back_inserter(V2));//保存file2的内容到向量V2中
sort(V1.begin(),V1.end());//对V1排序
V1.erase(unique(V1.begin(),V2.end()),V1.end());///???????删除重复数据
sort(V2.begin(),V2.end());//对V1排序
V2.erase(unique(V2.begin(),V2.end()),V2.end());
set_intersection(V1.begin(),V1.end(),V2.begin(),V2.end(),back_inserter(V3));
while(V3.empty()==false)
{
//如果是空集就退出
CIN<<fn;
Read.clear();
Read.close();
Read.open(fn.c_str());
if(!Read)
break;
//建立空容器和V1交换以清除V1
vector<T>().swap(V1);
copy(istream_iterator<T>(Read),istream_iterator<T>(),back_inserter(V1));
sort(V1.begin(),V1.end());
V1.erase(unique(V1.begin(),V1.end()),V1.end());
V2.swap(V3);
vector<T>().swap(V3);
set_intersection(V1.begin(),V1.end(),V2.begin(),V2.end(),back_inserter(V3));
}
if(V3.empty())
{
cout<<"An empty aggregate was found after reading"<<fn<<"./n";
return;
}
cout<<V2.size()<<"value were enumerated./n";
cout<<"Input save filename:/t";
CIN>>fn;
ofstream Dest(fn.c_str());
if(!Dest)
{
cerr<<"Create file failed!/n";
return;
}else
{
copy(V3.begin(),V3.end(),ostream_iterator<T>(Dest,"/t"));
Dest.close();
}
}
//查找相对值函数
template<class T>
void RelativeValue()
{
typedef fstream::off_type AddressType;
EInputStream CIN(cin);
string FN;
cout<<"First binary file name:/t";
CIN>>FN;
ifstream Read1(FN.c_str(),ios::in ios::binary);
//读+二进制模式
if(!Read1)
{
cerr<<"Open "<<FN<<" failed./n";
return;
}
cout<<"Second binary file name:/t";
CIN>>FN;
ifstream Read2(FN.c_str(),ios::in ios::binary);
if(!Read2)
{
cerr<<"Open "<<FN<<" failed./n";
return;
}
int ByteNumber;
cout<<"Byte number:/t";
CIN>>ByteNumber;//字节数
int RV;//指定的相对值
cout<<"Relative value(value1-value2):/t";
cin>>RV;
const int MaxByte=sizeof(T);
const int CharSize=sizeof(char);
if(ByteNumber<1ByteNumber>MaxByte)
ByteNumber=MaxByte;
T Value1,Value2;//两个文件中的数值
char* P1=reinterpret_cast<char*>(&Value1);
char* P2=reinterpret_cast<char*>(&Value2);
//先全部清0
memset(P1,0,MaxByte*CharSize);
memset(P2,0,MaxByte*CharSize);
AddressType Address=0;
//填充满P1
Read1.read(P1,CharSize*ByteNumber);
//填充满P2
Read2.read(P2,CharSize*ByteNumber);
//保存信息的链表
typedef list<pair<AddressType,pair<T,T> > > InfoList;
InfoList IL;
int Occurs=0;
//当两个文件都还没有读完
while(Read1 && Read2)
{
if(Value1-Value2==RV)//符合条件了
{
//保存信息
IL.push_back(make_pair(Address,make_pair(Value1, Value2)));
++Occurs;
}
//除旧
memcpy(P1,&P1[1],CharSize*(ByteNumber-1));
memcpy(P2,&P2[1],CharSize*(ByteNumber-1));
//迎新
Read1.read(&P1[ByteNumber-1],CharSize);
Read2.read(&P2[ByteNumber-1],CharSize);
++Address;
}//while(Read1 && Read2)
cout<<Occurs<<" different addresses were found./n";
if(Occurs==0) return;
cout<<"Input save filename:/t";
CIN>>FN;
//保存至文件
ofstream SaveFile(FN.c_str());
if(!SaveFile)
{
cerr<<"Create "<<FN<<" failed./n";
return;
}
SaveFile<<"Relative value is " <<RV<<"/nAddress/tValue1/tValue2/n";
for(InfoList::const_iterator Beg=IL.begin(), End=IL.end();Beg!=End;++Beg)
{
SaveFile<<(*Beg).first<<'/t' <<(*Beg).second.first <<'/t'<<(*Beg).second.second <<'/n';
}
}
///修改多个地址值的类/
template<class T>
class Modify
{
public:
typedef fstream::off_type AddressType;
static const int MaxByte=sizeof(T);
Modify();
void Run() const;
private:
strUCt ModifyInfoUnit
{
//修改要素——地址
AddressType Address;
//修改要素——新的数值
T NewValue;
//修改要素——新数值的字节数
int ByteNumber;
//排序原则
bool operator<(const Modify<T>::ModifyInfoUnit& rhs) const;
//从输入流读取一个单元
void ReadFrom(istream&);
};
const int CharSize;
EInputStream CIN;
void Input();
bool InputIsOk;
mutable ifstream SourceFile;
mutable ofstream DestFile;
set<ModifyInfoUnit> ModifyInfoSet;//集合
};
template<class T>
const int Modify<T>::MaxByte;
template<class T>
Modify<T>::Modify():CharSize(sizeof(char)),CIN(cin)
{
InputIsOk=true;
Input();
}
//构造函数,设置输入状态。
template<class T>
void Modify<T>::Input()
{
string fn;
cout<<"Source binary file name:/t";
CIN>>fn;
SourceFile.open(fn.c_str(),ios::in ios::binary);
if(!SourceFile)
{
cerr<<"Open "<<fn<<" failed./n";
InputIsOk=false;
return;
}
cout<<"Save file name:/t";
CIN>>fn;
DestFile.open(fn.c_str(),ios::out ios::binary);
if(!DestFile)
{
cerr<<"Create "<<fn<<" failed./n";
InputIsOk=false;
return;
}
cout<<"Any character which makes format error will end the input progress.(etc a)/n";
cout<<"Address(Dec)/tNewValue/tByteNumber(1--" <<Modify<T>::MaxByte<<")/n";
while(true)
{
ModifyInfoUnit MIU;
//从真实的输入流中读取一个ModifyInfoUnit
MIU.ReadFrom(CIN.Actual());
//输入失败就退出循环
if(!CIN.Actual()) break;
//把输入成功的单元存入集合,自动排序
ModifyInfoSet.insert(MIU);
}
CIN.ClearAndIgnore();//清除流的失败状态
}
template<class T>
void Modify<T>::Run() const
{
if(InputIsOk==false) return;
set<ModifyInfoUnit>::const_iterator Beg=
ModifyInfoSet.begin(),End=ModifyInfoSet.end();
AddressType Address=0;
char ch;
while(SourceFile && Beg!=End)
{
//SourceFile没有读完并且集合也没有遍历结束
if(Address==Beg->Address)
{
//到了指定的地址了
const char*P=reinterpret_cast<const char*>(&(Beg->NewValue));
for(int k=0;k<Beg->ByteNumber;++k)
{
//忽略源文件
SourceFile.read(&ch,CharSize);
}
//写新值
DestFile.write(P,CharSize*Beg->ByteNumber);
Address+=Beg->ByteNumber;
++Beg;
}
else
{
SourceFile.read(&ch,CharSize);
DestFile.write(&ch,CharSize);
++Address;
}
}
//源文件中可能还有剩余的内容
while(SourceFile.read(&ch,CharSize))DestFile.write(&ch,CharSize);
}
template<class T>
bool Modify<T>::ModifyInfoUnit::operator<(const Modify<T>::
ModifyInfoUnit& rhs) const
{
return Address<rhs.Address;
}
//定义排序原则,应该是一个const成员函数。
template<class T>
void Modify<T>::ModifyInfoUnit::ReadFrom(istream& IS)
{
IS>>Address>>NewValue>>ByteNumber;
if(ByteNumber<1ByteNumber>Modify<T>::MaxByte)
ByteNumber=Modify<T>::MaxByte;
}
//属于模板类
//T代表要寻找数据的类型//如金钱,生命等属于整型
//但不排除以后要查找其他类型的数据。为了可扩充性,使用了模板。
template <typename T>
class CheckBinaryFile{
public:
typedef fstream::off_type AddressType;//要找的数据在文件中的地址类型
CheckBinaryFile();//构造函数
void Run();
private:
static const int MaxByte=sizeof(T);//要查找的数据的类型所占的字节数
const int CharSize;
EInputStream CIN;//一个加强输入流(第三方类)
string FileName;//文件名称
T OldData;//输入的要查找的数据
int ByteNumber;//要查找的数据所占的字节数
//mutable关键字是const的反义作用,容易变动的变量经常使用它
mutable bool InputIsOk;
//用于读的文件对象
mutable ifstream BinaryFile;
mutable list<AddressType> AddressList;
//操作方法
void Input();
int Check() const;
void SaveAddressToFile(ostream&) const;//最后的"const"作用是防止修改本类对象的状态,即除mutable关键字标识的变量外其他都不可在此函数内做修改
void AutoModifySave(const T&) const;//在函数内防止修改T类型的参数
};
template <typename T>
//如果是static声明的静态变量在类体内做了声明,则在类外必须再做定义,而且只能被声明一次
const int CheckBinaryFile<T>::MaxByte;
//源文件
//构造函数
template <typename T>
CheckBinaryFile<T>::CheckBinaryFile():CharSize(char),CIN(cin){
InputIsOk=true;
Input();
//CharSize 为sizeof(char),把cin 绑定到CIN。由于CharSize是常量,必须在构造函数的初始化列表中设定。
}
//私有函数:输入成员函数
template <typename T>
void CheckBinaryFile<T>::Input()
{
//打开指定的输入文件名的二进制文件
cout<<"Binary Filename:/t";
cin>>FileName;
BinaryFile.open(FileName.c_str(),ios::in|ios::binary);
if(!BinaryFile)
{
InputIsOk=false;
cerr<<"open file failed!/n";
return;
}
//输入要查找的数据
cout<<"the Integer you want to search:/t";
CIN>>OldData;
//要找的数据的所占的数据位(字节数)
cout<<"byte number:(1--"<<CheckBinaryFile<T>::MaxByte<<"):/t";
CIN>>ByteNumber;
//字节数是否溢出的检查
if(ByteNumber<1||ByteNumber>CheckBinaryFile<T>::MaxByte)
{
ByteNumber=CheckBinaryFile<T>::MaxByte;
// cout<<"Byte number was amended to "<<ByteNumber<<endl;
cout<<"Byte number was amended to "<<CheckBinaryFile<T>::ByteNumber<<endl;//???????????????
}
}
//私有函数:检查输入的二进制文件中有多少个OldData,并保存地址到list链表对象中
//memory.h
template <typename T>
int CheckBinaryFile<T>::Check() const{
//将数据地址转换为字符串地址
const char* p=reinterpret_cast<const char*>(&OldData);
char Range[CheckBinaryFile<T>::MaxByte];
int Occurs=0;
AddressType Addr=0;
//填充0
memset(Range,0,CheckBinaryFile<T>::MaxByte*CharSize);
BinaryFile.read(Range,CharSize*ByteNumber);//填满Range
//如果读文件成功
while(BinaryFile)
{
if(memcmp(p,Range,CharSize*ByteNumber)==0)
{
AddressList.push_back(Addr);
++Occurs;
}
//删除一个最旧的
memcpy(Range,&Range[1],CharSize*(ByteNumber-1));
//读最新
BinaryFile.read(&Range[ByteNumber-1],CharSize);
++Addr;
}
//返回匹配数量
return Occurs;
}
//私有函数:保存找到的地址到文件
template <typename T>
void CheckBinaryFile<T>::SaveAddressToFile(ostream& os) const
{
copy(AddressList.begin(),AddressList.end(),ostream_iterator<T>(os,"/t"));
}
//私有函数:保存修改结果分别为一个文件
template <typename T>
void CheckBinaryFile<T>::AutoModifySave(const T& NewValue) const
{
list<AddressType>::const_iterator Beg=AddressList.begin(),End=AddressList.end();
const char *p=reinterpret_cast<const char*>(&NewValue);
for(;Beg!=End;++Beg){
//每个地址都要重新开头读
BinaryFile.clear();//清除错误状态
BinaryFile.seekg(0,ios::beg);//指向文件开头,准备读取
AddressType Addr=0;
char ch;
stringstream NewFile;
NewFile<<"@"<<*Beg;
string NewFileName(NewFile.str());
ofstream Write(NewFileName.c_str(),IOS::out|IOS::binary);
//文件对象错误
if(!Write)
{
cerr<<"NewFileName"<<" Failed!/n";
continue;
}
while(Addr<*Beg&&BinaryFile)
{
//小于地址内容
BinaryFile.read(&ch,CharSize);
Write.write(&ch,CharSize);
++Addr;
}
for(int k=0;k<ByteNumber;++k)
{
BinaryFile.read(&ch,CharSize);
}
Write.write(p,CharSize*ByteNumber);
while(BinaryFile)
{
BinaryFile.read(&ch,CharSize);
Write.write(&ch,CharSize);
}
Write.close();
cout<<NewFileName<<"...successfully./n";
//下次循环的时候文件已经成为bad状态,要清除这个状态
}//for
}
//公有函数:void Run();
template <typename T>
void CheckBinaryFile<T>::Run()
{
if(InputIsOk==false)
return;
//查找到的地址数量
const int Occurs=Check();
cout<<Occurs<<" different address were found!/n";
//没有找到内存地址,返回
if(Occurs==0) return;
//提示保存cout<<"Save address info to files(y/n)?/t";
cout<<"Save address info into files?(y/n)?/t";
char YN;
CIN>>YN;
if(YN=='Y'||YN=='y'){
cout<<"Address file name:/t";//提示输入保存的地址文件的名字
string AddressFileName;
CIN>>AddressFileName;
ofstream Save(AddressFileName.c_str(),ios::out);
if(!Save)
{
cerr<<"Create log file:"<<AddressFileName<<" error!/n";
}else{
SaveAddressToFile(Save);
}
Save.close();
}
cout<<"Modify binary file automatically(y/n)?/t";
CIN>>YN;
if(YN=='Y'||YN=='y')
{
cout<<"New value:/t";
T NewValue;
CIN>>NewValue;
system("dir>@tmp");//下句删除文件在不存在@开头的文件的时候错误,故首先建立一个名为@temp的文件
system("del @*/q");//执行DOS命令删除所有以@开头的文件
//将修改的文件分别保存一个单独的文件
AutoModifySave(NewValue);
}
}
//扩展1.取得2个地址文件的交集
//核心方法:set_intersection函数
template <typename T>
void GetInersection()
{
EInputStream CIN(cin);
//提示输入几个交叉的文件名,使用不存在的集合文件来结束输入
cout<<"Input some text filenames for reading,end with a nonexistent one:/n";
string fn;
CIN>>fn;
ifstream Read(fn.c_str());
if(!Read)
{
cerr<<"Open "<<fn<<" failed!/n";
return;
}
vector<T> V1;
//copy(istream_iterator<T>(Read),istream_iterator<T> (),back_inserter(V1));//保存file1的内容到V1
//保存file1的内容到V1中
copy(istream_iterator<T>(Read),istream_iterator<T>(),back_inserter(V1));
CIN<<fn;
Read.clear();
Read.close();
Read.open(fn.c_str());
if(!Read)
{
cerr<<"Open the file failed!/n";
return;
}
vector<T> V2,V3;
copy(istream_iterator<T>(Read),istream_iterator<T>(),back_inserter(V2));//保存file2的内容到向量V2中
sort(V1.begin(),V1.end());//对V1排序
V1.erase(unique(V1.begin(),V2.end()),V1.end());///???????删除重复数据
sort(V2.begin(),V2.end());//对V1排序
V2.erase(unique(V2.begin(),V2.end()),V2.end());
set_intersection(V1.begin(),V1.end(),V2.begin(),V2.end(),back_inserter(V3));
while(V3.empty()==false)
{
//如果是空集就退出
CIN<<fn;
Read.clear();
Read.close();
Read.open(fn.c_str());
if(!Read)
break;
//建立空容器和V1交换以清除V1
vector<T>().swap(V1);
copy(istream_iterator<T>(Read),istream_iterator<T>(),back_inserter(V1));
sort(V1.begin(),V1.end());
V1.erase(unique(V1.begin(),V1.end()),V1.end());
V2.swap(V3);
vector<T>().swap(V3);
set_intersection(V1.begin(),V1.end(),V2.begin(),V2.end(),back_inserter(V3));
}
if(V3.empty())
{
cout<<"An empty aggregate was found after reading"<<fn<<"./n";
return;
}
cout<<V2.size()<<"value were enumerated./n";
cout<<"Input save filename:/t";
CIN>>fn;
ofstream Dest(fn.c_str());
if(!Dest)
{
cerr<<"Create file failed!/n";
return;
}else
{
copy(V3.begin(),V3.end(),ostream_iterator<T>(Dest,"/t"));
Dest.close();
}
}
//查找相对值函数
template<class T>
void RelativeValue()
{
typedef fstream::off_type AddressType;
EInputStream CIN(cin);
string FN;
cout<<"First binary file name:/t";
CIN>>FN;
ifstream Read1(FN.c_str(),ios::in ios::binary);
//读+二进制模式
if(!Read1)
{
cerr<<"Open "<<FN<<" failed./n";
return;
}
cout<<"Second binary file name:/t";
CIN>>FN;
ifstream Read2(FN.c_str(),ios::in ios::binary);
if(!Read2)
{
cerr<<"Open "<<FN<<" failed./n";
return;
}
int ByteNumber;
cout<<"Byte number:/t";
CIN>>ByteNumber;//字节数
int RV;//指定的相对值
cout<<"Relative value(value1-value2):/t";
cin>>RV;
const int MaxByte=sizeof(T);
const int CharSize=sizeof(char);
if(ByteNumber<1ByteNumber>MaxByte)
ByteNumber=MaxByte;
T Value1,Value2;//两个文件中的数值
char* P1=reinterpret_cast<char*>(&Value1);
char* P2=reinterpret_cast<char*>(&Value2);
//先全部清0
memset(P1,0,MaxByte*CharSize);
memset(P2,0,MaxByte*CharSize);
AddressType Address=0;
//填充满P1
Read1.read(P1,CharSize*ByteNumber);
//填充满P2
Read2.read(P2,CharSize*ByteNumber);
//保存信息的链表
typedef list<pair<AddressType,pair<T,T> > > InfoList;
InfoList IL;
int Occurs=0;
//当两个文件都还没有读完
while(Read1 && Read2)
{
if(Value1-Value2==RV)//符合条件了
{
//保存信息
IL.push_back(make_pair(Address,make_pair(Value1, Value2)));
++Occurs;
}
//除旧
memcpy(P1,&P1[1],CharSize*(ByteNumber-1));
memcpy(P2,&P2[1],CharSize*(ByteNumber-1));
//迎新
Read1.read(&P1[ByteNumber-1],CharSize);
Read2.read(&P2[ByteNumber-1],CharSize);
++Address;
}//while(Read1 && Read2)
cout<<Occurs<<" different addresses were found./n";
if(Occurs==0) return;
cout<<"Input save filename:/t";
CIN>>FN;
//保存至文件
ofstream SaveFile(FN.c_str());
if(!SaveFile)
{
cerr<<"Create "<<FN<<" failed./n";
return;
}
SaveFile<<"Relative value is " <<RV<<"/nAddress/tValue1/tValue2/n";
for(InfoList::const_iterator Beg=IL.begin(), End=IL.end();Beg!=End;++Beg)
{
SaveFile<<(*Beg).first<<'/t' <<(*Beg).second.first <<'/t'<<(*Beg).second.second <<'/n';
}
}
///修改多个地址值的类/
template<class T>
class Modify
{
public:
typedef fstream::off_type AddressType;
static const int MaxByte=sizeof(T);
Modify();
void Run() const;
private:
strUCt ModifyInfoUnit
{
//修改要素——地址
AddressType Address;
//修改要素——新的数值
T NewValue;
//修改要素——新数值的字节数
int ByteNumber;
//排序原则
bool operator<(const Modify<T>::ModifyInfoUnit& rhs) const;
//从输入流读取一个单元
void ReadFrom(istream&);
};
const int CharSize;
EInputStream CIN;
void Input();
bool InputIsOk;
mutable ifstream SourceFile;
mutable ofstream DestFile;
set<ModifyInfoUnit> ModifyInfoSet;//集合
};
template<class T>
const int Modify<T>::MaxByte;
template<class T>
Modify<T>::Modify():CharSize(sizeof(char)),CIN(cin)
{
InputIsOk=true;
Input();
}
//构造函数,设置输入状态。
template<class T>
void Modify<T>::Input()
{
string fn;
cout<<"Source binary file name:/t";
CIN>>fn;
SourceFile.open(fn.c_str(),ios::in ios::binary);
if(!SourceFile)
{
cerr<<"Open "<<fn<<" failed./n";
InputIsOk=false;
return;
}
cout<<"Save file name:/t";
CIN>>fn;
DestFile.open(fn.c_str(),ios::out ios::binary);
if(!DestFile)
{
cerr<<"Create "<<fn<<" failed./n";
InputIsOk=false;
return;
}
cout<<"Any character which makes format error will end the input progress.(etc a)/n";
cout<<"Address(Dec)/tNewValue/tByteNumber(1--" <<Modify<T>::MaxByte<<")/n";
while(true)
{
ModifyInfoUnit MIU;
//从真实的输入流中读取一个ModifyInfoUnit
MIU.ReadFrom(CIN.Actual());
//输入失败就退出循环
if(!CIN.Actual()) break;
//把输入成功的单元存入集合,自动排序
ModifyInfoSet.insert(MIU);
}
CIN.ClearAndIgnore();//清除流的失败状态
}
template<class T>
void Modify<T>::Run() const
{
if(InputIsOk==false) return;
set<ModifyInfoUnit>::const_iterator Beg=
ModifyInfoSet.begin(),End=ModifyInfoSet.end();
AddressType Address=0;
char ch;
while(SourceFile && Beg!=End)
{
//SourceFile没有读完并且集合也没有遍历结束
if(Address==Beg->Address)
{
//到了指定的地址了
const char*P=reinterpret_cast<const char*>(&(Beg->NewValue));
for(int k=0;k<Beg->ByteNumber;++k)
{
//忽略源文件
SourceFile.read(&ch,CharSize);
}
//写新值
DestFile.write(P,CharSize*Beg->ByteNumber);
Address+=Beg->ByteNumber;
++Beg;
}
else
{
SourceFile.read(&ch,CharSize);
DestFile.write(&ch,CharSize);
++Address;
}
}
//源文件中可能还有剩余的内容
while(SourceFile.read(&ch,CharSize))DestFile.write(&ch,CharSize);
}
template<class T>
bool Modify<T>::ModifyInfoUnit::operator<(const Modify<T>::
ModifyInfoUnit& rhs) const
{
return Address<rhs.Address;
}
//定义排序原则,应该是一个const成员函数。
template<class T>
void Modify<T>::ModifyInfoUnit::ReadFrom(istream& IS)
{
IS>>Address>>NewValue>>ByteNumber;
if(ByteNumber<1ByteNumber>Modify<T>::MaxByte)
ByteNumber=Modify<T>::MaxByte;
}