#include"iostream"
#include<string>
#include<stdlib.h>
#include<iomanip> //使用setw所要必须包含的头文件
#include<fstream>//文件输入输出的时候一定要包含这个头文件
using namespace std;
string sb="d://book.txt"; //原来开始的时候老是文件打开失败,我把“d:/book.bat"改成
string sr="d://reader.txt";//"d://book.bat"竟然就好了,后面换成我习惯的txt文件了
fstream file_book;
fstream file_reader;
void input_reader();//对input_reader()函数的声明
void borrow_book();//对borrow_book()函数的声明。
void return_book();//对return_book()函数的声明。
class reader
{
public:
reader():number(0)
{
char *p="";
strcpy(readername,p);
strcpy(bookname[0],p);
strcpy(bookname[1],p);
strcpy(bookname[2],p);
strcpy(bookname[3],p);
strcpy(booknumber[0],p);
strcpy(booknumber[1],p);
strcpy(booknumber[2],p);
strcpy(booknumber[3],p);
}
~reader()
{
}
friend void input_reader();//对友元函数的声明
friend void show_reader();
friend void borrow_book();//将借书行为作为reader的一个友元
friend void return_book();//将还书行为作为reader的一个友元
private:
int number; //借阅证编号
char readername[10];//读者姓名
char bookname[4][10];//所借阅的书的名称
char booknumber[4][10];//所借阅的书的编号
};
void input_newbook();//对input_newbook()函数的声明
class book
{
public:
book():number(0),edition(0),price(0)
{
char *p="";
strcpy(bookname,p);
strcpy(author,p);
strcpy(press,p);
strcpy(numbers_of_allcopys[0],p);
strcpy(numbers_of_allcopys[1],p);
strcpy(numbers_of_allcopys[2],p);
strcpy(numbers_of_allcopys[3],p);
strcpy(numbers_of_nowcopys[0],p);
strcpy(numbers_of_nowcopys[1],p);
strcpy(numbers_of_nowcopys[2],p);
strcpy(numbers_of_nowcopys[3],p);
}
~book()
{
}
friend void show_book();
friend void input_newbook();//对友元的声明
friend void borrow_book();//将借书行为声明为book类的友元
friend void return_book();//将还书行为作为book的友元。
private:
int number;//书的序号
char bookname[10]; //书的名字
char author[10]; //书的作者
int edition; //书的版本
char press[10]; //书的作者
double price; //书的价格
char numbers_of_allcopys[4][10];//所有的这本书的编号
char numbers_of_nowcopys[4][10];//在馆的这本书的编号
static int count;//记录有多少种书。
};
int book::count=0 ; //书的种数初始化为0;
void input_newbook()
{
char ch;//用来使操作暂停
double jiage;
int banbenhao;
int a;//用来保存所找到书的记录号
int b;//用来作为用户指定记录号的输入缓存
bool tag=false;//用来表示是否在书库中找到这个书名
book book1,book2;
char s3[10],s4[10],s5[10];
cout<<"请输入所要添加的新书的名字"<<endl;
cin>>s3;
cout<<"请输入所要添加的新书的作者"<<endl;
cin>>s4;
cout<<"请输入所要添加的新书的出版社"<<endl;
cin>>s5;
cout<<"请输入所要添加的新书的版本号"<<endl;
cin>>banbenhao;
//只有书名,作者,出版社,版本号都一样才能确定是同一本书的copy
file_book.open(sb.c_str (),ios_base::in |ios_base::out);//以读模式打开文件
if(!file_book)
{
cout<<"用于存放新书的文件d://book.txt"<<"打开失败"<<endl;
file_book.clear ();
cin>>ch;
return ;
}
file_book.seekg (0);
file_book.read (reinterpret_cast<char *>(&book1),sizeof(book));
while(!file_book.eof ())
{
if((!strcmp(book1.bookname,s3))&&(!strcmp(book1.author,s4))&&(!strcmp(book1.press,s5))&&(book1.edition ==banbenhao ))
{ a=book1.number ;
tag=true;
break;
}//内if结束
file_book.read (reinterpret_cast<char *>(&book1),sizeof(book));
}//while结束
file_book.clear ();
bool tag2=false;//用来标志这条用户指定新书的编号的记录是否是空白
char s6[10];
if(tag==true)
{
int i=0;
while(book1.numbers_of_allcopys [i]!=""&&i<=3)
{ i++;}
if(i>3)
{
cout<<"这本书已经存在,并且已经有四本,不能添加新书!"<<endl;
file_book.close ();
return;
}
else
{
cout<<"这个书名已经存在,请输入新的书的编号"<<endl;
cin>>s6;
strcpy(book1.numbers_of_allcopys [i],s6);
int j=0;
for(;j<=3&&strcmp(book1.numbers_of_nowcopys [j],"");j++);
strcpy(book1.numbers_of_nowcopys[j],s6);
}
file_book.clear ();
file_book.seekp((book1.number -1)*sizeof(book));
file_book.write (reinterpret_cast<const char *>(&book1),sizeof(book));
}//if(tag==true)结束
else
{
cout<<"/n这个书名在书库中不存在/n"<<"请输入书要放入的记录号"<<endl;
cin>>b;
while(tag2==false)//当用户指定的书的记录号重复时,即指定记录已经非空时
{
file_book.clear ();
file_book.seekg ((b-1)*sizeof(book));
file_book.read (reinterpret_cast<char *>(&book1),sizeof(book));
if(book1.number ==0)
{
tag2=true;
break;
}
if(tag2==false)
{
cout<<"指定记录号非空,请重新指定"<<endl;
cin>>b;
}
}//while循环结束
cout<<"请输入这本书的价格"<<endl;
cin>>jiage;
cout<<"请输入这本书的编号"<<endl;
char s7[10];
cin>>s7;
strcpy(book2.author,s4);
strcpy(book2.bookname,s3);
book2.number =b;
book2.edition =banbenhao;
strcpy(book2.press,s5);
book2.price =jiage;
++book::count ;//增加书的种数
strcpy(book2.numbers_of_allcopys[0],s7);
strcpy(book2.numbers_of_nowcopys[0],s7);
file_book.clear ();
file_book.seekp ((b-1)*sizeof(book));
file_book.write (reinterpret_cast<const char *>(&book2),sizeof(book));
}//else结束
cout<<"新书"<<s3<<"被添加入库成功"<<endl;
file_book.close ();
}
void input_reader()
{
char ch;//用来使操作暂停
bool tag=false;
reader reader1;
char s1[10];
cout<<"请输入你的姓名"<<endl;
cin>>s1;
file_reader.open(sr.c_str (),ios_base::in);//以读模式打开文件
if(!file_reader)
{
cout<<"打开文件文件失败"<<endl;
file_reader.clear ();
return;
}
file_reader.seekg (0);
file_reader.read (reinterpret_cast<char *>(&reader1),sizeof(reader));
int count=1;
while( !file_reader.eof ()) //这一段读取并验证的代码没有问题,那么问题出在新增的reader代码中
{
if(!strcmp(reader1.readername,s1))
{
cout<<"你已经有了一个借阅证,一个人只可以办理一个借阅证"<<endl;
file_reader.close ();
cin>>ch;
return; //如果已经有了一个借阅证,退出
}
file_reader.read (reinterpret_cast<char *>(&reader1),sizeof(reader));
}
file_reader.clear ();//关键地方就在这里,因为退出while循环时导致file_reader文件流错误,如果不调用
//clear的话,即使调用close,再重新open这个file_reader文件流,也不能解决这个问题。
//这个文件流的错误类似与cin和cout等,如果输入的类型错误,或者读取到了文件尾部
//它就会返回false,这个时候就要用clear恢复这个流。
reader reader2;
//后面还有将reader2存入file_reader的操作没有完成
int bianhao=0;
cout<<"请输入你申请的借阅证号"<<endl;
cin>>bianhao;
while(1)
{
file_reader.seekg ((bianhao-1)*sizeof(reader));
file_reader.read (reinterpret_cast<char *>(&reader2),sizeof(reader));
if(reader2.number ==0)
{
file_reader.clear ();
cout<<"这是一个空白记录可以使用"<<endl;
reader2.number =bianhao;
strcpy(reader2.readername ,s1);
file_reader.close ();
file_reader.open (sr.c_str (),ios::in|ios::out);
file_reader.seekp(0);
file_reader.seekp ((bianhao -1)*sizeof(reader));//现在问题很明显是出在修改记录上
file_reader.write (reinterpret_cast<const char *>(&reader2),sizeof(reader2));
file_reader.clear ();
file_reader.close ();
cout<<"图书证办理成功:"<<endl;
cout<<"姓名:"<<s1<<"/t"<<"图书证号"<<bianhao<<endl;
cout<<"现在检验是否输入到文件中:"<<endl;
file_reader.open (sr.c_str (),ios::in);
file_reader.seekg ((bianhao-1)*sizeof(reader));
reader reader4;
file_reader.read (reinterpret_cast<char *>(&reader4),sizeof(reader));
cout<<reader4.number <<reader4.readername ;
file_reader.close ();
cin>>ch;
return;
}
else
{
cout<<"所申请借阅证号已被使用,请重新输入"<<endl;
cin>>bianhao;
}
}
file_reader.close ();
cin>>ch;
}
void show_reader()//这个函数工作正常,说明读取不存在问题
{
char ch;
reader reader1;
file_reader.open (sr.c_str (),ios_base::in);
if(!file_reader)
{
cout<<"文件打开失败,请重新操作"<<endl;
file_reader.clear();
return ;
}
file_reader.seekg (0);
file_reader.read (reinterpret_cast<char *>(&reader1),sizeof(reader));
while(!file_reader.eof ())
{
if(reader1.number !=0)
{
cout<<"读者证号"<<reader1.number<<setw(3)<<"读者姓名"<<reader1.readername<<setw(3)<<"第一本书名"<<reader1.bookname[0]<<setw(3)<<"第一本书号"<<reader1.bookname [0]
<<setw(3)<<"第二本书名"<<reader1.bookname [1]<<setw(3)<<"第二本书号"<<reader1.booknumber [1]<<setw(3)<<"第三本书名"<<reader1.bookname [2]<<setw(3)<<"第三本书号"<<reader1.booknumber [2]
<<setw(3)<<"第四本书名"<<reader1.bookname [3]<<setw(3)<<"第四本书号"<<reader1.booknumber [3]<<endl;
}
file_reader.read (reinterpret_cast<char *>(&reader1),sizeof(reader));
}//while结束
file_reader.clear ();
file_reader.close ();
cin>>ch;
}
void show_book()
{
char ch;
file_book.open (sb.c_str (),ios::in);
if(!file_book)
{
cout<<"文件打开失败,请重新操作"<<endl;
file_book.clear();
return;
}
file_book.seekg (0);
book bk;
file_book.read (reinterpret_cast<char *>(&bk),sizeof(book));
while(!file_book.eof ())
{
if(bk.number !=0)
{
cout<<"记录号"<<bk.number <<"书名"<<bk.bookname <<"作者"<<bk.author <<"版本号"<<bk.edition
<<"这本书总的copys的编号"<<bk.numbers_of_allcopys [0]<<bk.numbers_of_allcopys [1]<<bk.numbers_of_allcopys [2]
<<bk.numbers_of_allcopys [3]<<"现在库存的copys的编号"<<bk.numbers_of_nowcopys [0]
<<bk.numbers_of_nowcopys [1]<<bk.numbers_of_nowcopys [2]<<bk.numbers_of_nowcopys [3]<<endl;
}
file_book.read (reinterpret_cast<char *>(&bk),sizeof(book));
}
file_book.clear ();
file_book.close ();
cin>>ch;
}
void borrow_book()
{
char ch;//用来缓冲输出结果
int num=0;//用来输入借阅证号
char name[10]; //用来输入读者名字
bool tag3=false;//用来标志是否找到这个借阅证和读者
reader rd1;
cout<<"请输入你的借阅证号"<<endl;
cin>>num;
cout<<"请输入你的姓名"<<endl;
cin>>name;
file_reader.open (sr.c_str (),ios::in |ios::out);
if(!file_reader)
{
cout<<"文件打开失败,请重新操作"<<endl;
file_reader.clear();
return ;
}
file_reader.seekg(0);
file_reader.read (reinterpret_cast<char *>(&rd1),sizeof(reader));
while(!file_reader.eof ())
{
if(rd1.number ==num&&(!strcmp(rd1.readername,name)))
{ tag3=true;
break;
}
file_reader.read (reinterpret_cast<char *>(&rd1),sizeof(reader));
}
file_reader.clear ();
if(tag3==false)
{
cout<<"没有这个借阅证和读者的信息,请先办理借阅证再来借书"<<endl;
file_reader.close ();
cin>>ch;
return;
}
bool tag6=false;//用来标志借阅证是否已经借满
if(tag3==true) //用来检测这本借阅证是否已经借满
{
for(int i=0;i<4;i++)
{
if(!strcmp(rd1.bookname[i],""))
tag6=true;
}
}
if(tag6==false)
{
cout<<"你的借阅证已经借满4本书,不能再借书"<<endl;
file_reader.close ();
cin>>ch;
return;
}
cout<<"请输入你要借的书名"<<endl;
char p1[10];//用来输入书名
cin>>p1;
file_book.open (sb.c_str (),ios::in|ios::out);
if(!file_reader)
{
cout<<"文件打开失败,请重新操作"<<endl;
file_reader.clear();
return;
}
book bk1;
file_book.seekg(0);
file_book.read (reinterpret_cast<char *>(&bk1),sizeof(book));
bool tag4=false;//用来标志是否找到要借的这本书
bool tag5=false;//用来标志这本书是否有库存
int ix=0; //用来记录是那个copy还在书库的序号
char p2[10];//用来保存那个被借的书的编号
while(!file_book.eof ())
{
if(!strcmp(bk1.bookname,p1))
{
tag4=true;
for(;ix<4;ix++)
{
if(strcmp(bk1.numbers_of_nowcopys [ix],""))
{
tag5=true;
strcpy(p2,bk1.numbers_of_nowcopys [ix]);//将这个copy的序号保存,后面要修改reader的借书记录
strcpy(bk1.numbers_of_nowcopys [ix],"");//将这个库存copy的序号清空
file_book.clear();
file_book.seekp ((bk1.number -1)*sizeof(book));
file_book.write (reinterpret_cast<const char *>(&bk1),sizeof(book));
break;
}
}//内while的结束
}//外if的结束
file_book.read (reinterpret_cast<char *>(&bk1),sizeof(book));
}//外while结束
file_book.clear ();
file_book.close ();
if(tag4==true &&tag5==false)
{
cout<<"不好意思,你所要借的书已经全部借出"<<endl;
cin>>ch;
return ;
}
if(tag4==false)
{
cout<<"不好意思,你所要借的书在图书馆没有"<<endl;
cin>>ch;
return;
}
//现在继续修改读者信息即可,借阅的读者信息在rd1中
int j=0;
for(;j<4;j++)
{
if(!strcmp(rd1.bookname [j],""))
break;
}
strcpy(rd1.bookname[j] ,p1);
strcpy(rd1.booknumber[j],p2);
file_reader.seekp ((rd1.number -1)*sizeof(reader));
file_reader.write (reinterpret_cast<const char *>(&rd1),sizeof(reader));
cout<<"借书成功,你所借的书名为:"<<bk1.bookname <<"书的编号为:"<<p2<<endl;
file_reader.clear ();
file_reader.close ();
}
void return_book()
{
cout<<"请输入你的借阅证号和读者姓名"<<endl;
char ch;//用来缓冲输出
char p1[10];//用来输入读者姓名
int num1=0;//用来输入借阅证号
reader rd1;
book bk1;
bool tag1=false;//用来标志是否有这个借阅证
bool tag2=false;//用来标志是否有这本书
bool tag3=false;//用来标志是否有这本书的这个编号
cin>>num1;
cin>>p1;
file_reader.open (sr.c_str (),ios::in|ios::out);
if(!file_reader)
{
cout<<"文件打开失败,请重新操作"<<endl;
file_reader.clear();
return ;
}
file_reader.seekg (0);
file_reader.read (reinterpret_cast<char *>(&rd1),sizeof(reader));
while(!file_reader.eof ())
{
if(!strcmp(rd1.readername ,p1)&& rd1.number ==num1)
{
tag1=true;
break;
}
file_reader.read (reinterpret_cast<char *>(&rd1),sizeof(reader));
}
file_reader.clear ();
if(tag1==false)
{
cout<<"没有这个借阅证"<<endl;
file_reader.close ();
cin>>ch;
return;
}
cout<<"请输入要还的书的书名和编号"<<endl;
char p2[10];//用来输入书的书名;
char p3[10];//用来输入书的编号;
int ix=0;
cin>>p2>>p3;
file_book.open (sb.c_str (),ios::in|ios::out);
if(!file_book)
{
cout<<"文件打开失败,请重新操作"<<endl;
file_book.clear();
return ;
}
file_book.seekg (0);
file_book.read (reinterpret_cast<char *>(&bk1),sizeof(book));
while(!file_book.eof ())
{
if(!strcmp(bk1.bookname ,p2))
{
tag2=true;
for(;ix<4;ix++)
{
if(!strcmp(bk1.numbers_of_allcopys [ix],p3))
tag3=true;
}
}
file_book.read (reinterpret_cast<char *>(&bk1),sizeof(book));
}//while的结束
file_book.clear ();
if(tag2==false||tag3==false)
{
cout<<"图书馆没有借出此书,是否输入有误"<<endl;
cin>>ch;
return ;
}
bool tag4=false;//用来标志是否这个读者确实借了这本书
int ix2=0;//标记着这是读者借的第几本书
for(ix2=0;ix2<4;ix2++)
{
if(!strcmp(rd1.bookname[ix2],p2)&&!strcmp(rd1.booknumber[ix2],p3))
{
tag4=true;
break;
}
}
if(tag4==false)
{
cout<<"你没有借这本书,是否输入有误"<<endl;
return;
}
//现在就是修改这两个文件了,本书的资料在bk1中,本读者的资料在rd1中。
strcpy(rd1.bookname[ix2],"");
strcpy(rd1.booknumber[ix2],"");
file_reader.clear();
file_reader.seekp((rd1.number-1)*sizeof(reader));
file_reader.write(reinterpret_cast<const char *>(&rd1),sizeof(reader));
file_reader.close();
file_book.clear();
for(int ix3=0;ix3<4;ix3++)
{
if(!strcmp(bk1.numbers_of_nowcopys[ix3],""))
strcpy(bk1.numbers_of_nowcopys[ix3],p3);
}
file_book.clear();
file_book.seekp((bk1.number-1)*sizeof(book));
file_book.write(reinterpret_cast<const char *>(&bk1),sizeof(book));
file_book.close();
cout<<"还书成功,谢谢"<<endl;
}
void menu()
{
char ch;
int xuanze;
bool tag3=false;//用来标志是否找到了这个读者的借阅证信息
cout<<"***************************欢迎进入图书管理系统**************************"<<endl;
cout<<" 1.新书入库 "<<endl;
cout<<" 2.新办图书证 "<<endl;
cout<<" 3.借书 "<<endl;
cout<<" 4.还书 "<<endl;
cout<<" 5.输出所有的读者信息 "<<endl;
cout<<" 6.输出所有书本的信息 "<<endl;
cout<<"******************************请按键选择*********************************"<<endl;
cin>>xuanze;
while(xuanze>6 ||xuanze<1)
{
cout<<"没有这个选项,请重新选择"<<endl;
cin>>xuanze;
}
switch(xuanze)
{case 1:
input_newbook();
break;
case 2:
input_reader();
break;
case 3:
borrow_book();
break;
case 4:
return_book();
break;
case 5:
show_reader();
break;
case 6:
show_book();
break;
//后面还有其他的选项操作没有完成
}//switch的结束
system("cls");
cout<<"是否退出本图书管理系统:是(Y/y),否(N/n)"<<endl;
cin>>ch;
while(!(ch=='y'||ch=='Y'||ch=='n'||ch=='N'))
{
cin>>ch;
}
if(ch=='y'||ch=='Y')
return;
else
menu();
}
int main()
{
char ch;
file_book.open (sb.c_str (),ios_base::in );
file_book.seekg (0,ios_base::end );
int length1=file_book.tellg();
file_book.close ();
if(length1==0)//说明文件book.txt为空,要初始化文件;
{
book blankbook;
file_book.open (sb.c_str (),ios_base::out );
file_book.seekp(0);
for(int ix=0;ix<100;ix++)
file_book.write (reinterpret_cast<const char *>(&blankbook),sizeof(book));
file_book.close ();
}
file_reader.open (sr.c_str (),ios_base::in);
file_reader.seekg (0,ios_base::end );
int length2=file_reader.tellg();
file_reader.clear ();
file_reader.close ();
if(length2==0)//说明文件reader.txt为空,要初始化文件;
{
reader blankreader;
file_reader.open (sr.c_str (),ios_base::out);
file_reader.seekp(0);
for(int ix=0;ix<100;ix++)
file_reader.write (reinterpret_cast<const char *>(&blankreader),sizeof(reader));
file_reader.close ();
}
menu();
cin>>ch;
return 0;
}
/*程序总结:
(1)最大的收获在于我搞清楚了不能用顺序存储文件来做这个程序,必须用随机存储文件,而且存入文件的每个对象还必须占用相同的大小,
否则就没有办法随机访问和修改,由于不能用顺序文件,所以我必须放弃重载book类和reader类的》和《操作符来进行文件读取的方式,也必须放弃在类的数据成员中使用vector和pair以及string的方式,因为例如:int a=1,b=232,string s1="afg",s2="sfaf af a ",即使它们都占用相同的字节大小,但是存储在文件中的时候,它们所占的大小也不同。所以必须在类的数据成员中使用固定大小的数组。这给操作带来了一定的麻烦。
(2)在对文件进行修改写入的时候,不能用ios_base::app,否则写入的东西在文件的尾部
要用ios_base::out,但是使用它却会导致原文件记录丢失,文件总是只能保留最新的那个记录。
现在要进行修改。。。。解决方法是:
file_reader.open (sr.c_str (),ios::in|ios::out);
使用ios::in和ios::out同时打开这个文件,对它进行写入。
(3)因为退出while循环时导致file_reader文件流错误,如果不调用
clear的话,即使调用close,再重新open这个file_reader文件流,也不能解决这个问题。
这个文件流的错误类似与cin和cout等,如果输入的类型错误,或者读取到了文件尾部
它就会返回false,这个时候就要用clear恢复这个流。这个错误导致了文件没有办法写入。
*/