简单图书管理系统

#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恢复这个流。这个错误导致了文件没有办法写入。

 

 

 */ 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值