小型图书馆管理系统(C语言实现)

来源:互联网 发布:淘宝网 服务中心 编辑:程序博客网 时间:2024/05/29 15:00
全部实现代码如下:
--------------------------------------------------------------------------------------
main.cpp

#include "c1.h"
typedef int ElemType;
#include "c2-5.h"
#include "c4-2.h"
#include "algo4-3.h"
#include "first.h"

void first_main() 
{
    FILE*fp_book,*fp_reader;
   if((fp_book=fopen("Book.txt","r+"))==NULL&&(fp_reader=fopen("Reader.txt","r+"))==NULL)
    {
      about();    
      Init();
    }
    else
     Load();
      printf("\t读者及图书信息加载完毕。\n");

      //algo43_main();
       printf("\t关键词检索表更新完毕。\n");
    }

   Menu_select();
}//end"first_main()"


int main(void)
{
   first_main();
   
    return0;
}
-----------------------------------------------------------------------------------------------
first.h

#ifndef FIRSTH1
#define FIRSTH1

// #include  
// #include
// #include
#include
#define Max3     

typedef structbook   
{
    charbook_num[10];
    charbook_name[20];
   int book_kc;    //MY库存总量
   int book_xc;   //MY现存数量
    struct book*next;
}BK;

typedef struct Start
{
    intst_sec;
    intst_hour;
    intst_mday;
    intst_min;
    intst_mon;
    intst_year;
}start;

typedef struct borrow  
{
    charborrow_book_num[10];
    startlend_t;
}BO;

typedef struct reader      
{
    charreader_num[10];
    charreader_name[10];
    intright;    //MY读者最多借书本数
    BOborrow[Max]; 
    structreader * next;
}RD;
//BK*h_book;       
//RD*h_reader;     

intMenu();               
voidMenu_select();       
voidInit();              
voidInit_reader();      
voidInit_book();        
voidInsert_New_Book();   
void Insert_New_Reader(); 
voiddel_old_book();      
voiddel_old_reader();    
voidbook_not_enough();   
intFind();               
voidFind_Select();      
voidFind_Reader();      
void Find_Book_contral(); 
int  Find_Book_select(); 
voidFind_Book();         
voidBorrow_Book();       
voidReturn_Book();       
voidabout();             
intPrint();              
voidPrint_Select();     
voidPrint_book();       
voidPrint_reader();     
voidSave();              
voidSave_Reader();      
voidSave_Book();        
voidLoad();              
voidLoad_Reader();      
voidLoad_Book();        

#endif
-------------------------------------------------------------------------------------------------
first.cpp

#include "c1.h"
#include "algo4-3.h"
#include "first.h"

//函数及结构体申明在first.h中

BK*h_book;       
RD*h_reader;     

int Menu()
{
//int sn;
    intsn=-1;
 printf("\n\t\t图书管理系统主菜单\n");
 printf("==========================================================\n");
 printf("*\t0----退出系统         6----关于系统   \t*\n");
 printf("*\t1----新书入库         7----旧书出库   \t*\n");
 printf("*\t2----增新读者         8----注销读者   \t*\n");  
 printf("*\t3----查询图书/读者    9----输出全部信息\t*\n");  
 printf("*\t4----借书登记        10----库存不足图书\t*\n");
 printf("*\t5----还书管理        11----保存当前信息\t*\n");    
 printf("==========================================================\n");
 printf("请选择相应代码:"); 
 for(;;) 
 {
    fflush(stdin);  
  scanf("%d",&sn);
   getchar();
  if(sn<0||sn>11)
     printf("\n错误!请重新输入:");
   else break;
 }
  return sn;
}//"Menu()"end

void Menu_select()
{
    chari='n';
  for(;;) 
 {
   switch(Menu())
   {
    case 0:
           //char i='n';
           printf("是否保存当前更改 y/n?");
          scanf("%c",&i);
          getchar();

          if( i=='y')
          {
               system("cls");   
               Save();
              printf("\n\n\t文件保存成功!\n"); 
              printf("\n\n\tGoodBye!\n");
               getchar();
          }
          else
               printf("\n\n\t放弃文件保存!\n");

          getchar();
          exit(0);
    
   case1:Insert_New_Book();break; 
   case2:Insert_New_Reader();break;
   case3:Find_Select();break;
   case4:Borrow_Book();break;
   case5:Return_Book();break;
   case 6:about();break;
   case7:del_old_book();break;
   case8:del_old_reader();break;
   case9:Print_Select();break;
   case10:book_not_enough();break;
   case 11:Save(); Load();
        printf("\n文件保存成功!按任意键进行下步操作....");
        getchar(); system("cls");break;
  default:printf("\n输入错误,请重新输入!"); break;   
   }
  }//"switch(Menu())"
}//"Menu_select()"end


void Init() 
  
   Init_reader();
   Init_book();
}//"Init()" end

void Init_reader()
{
    RD *p0=NULL;
    int i;
    printf("\n读者初始化开始,请输入读者信息..\n包括编号.姓名..\n");
    p0=(RD *)malloc(sizeof(RD));
    h_reader=p0;

    printf("\n请输入读者的信息:\n");
    printf("ReaderNo.:");           
    scanf("%s",p0->reader_num);
    getchar();
    printf("ReaderName:");          
    gets(p0->reader_name);
    p0->right=0;
    for(i=0;i
    strcpy(p0->borrow[i].borrow_book_num,"0"); 

    p0->next=NULL;
    p0=NULL;
    printf("\n读者信息初始化完毕!按任意键继续下一步操作..\n");

    getchar();
    system("cls");
}//"Init_reader()" end

void Init_book() 
{
    BK*p0=NULL;
   printf("\n图书初始化开始,请输入图书信息..\n包括编号.书名.数量..\n");
    p0=(BK*)malloc(sizeof(BK));
   h_book=p0;

   printf("\n请输入图书信息:\n");
   printf("BookNo.:");           
   scanf("%s",p0->book_num);
   getchar();
   printf("BookName:");          
   gets(p0->book_name);
   printf("Number:");            
   scanf("%d",&p0->book_kc);
   getchar();

   p0->book_xc=p0->book_kc;    
   p0->next=NULL;
   p0=NULL;
   printf("\n图书信息初始化完毕!按任意键继续下一步操作..\n");

   getchar();
   system("cls");
}//"Init_book()" end


void Insert_New_Reader() 
{
    RD*p=NULL,*p0=NULL,*p1=NULL,*p2=NULL;
    int i;
   p=p1=p2=h_reader;
   printf("\n增加新读者模块...\n");
   printf("\n请输入新读者信息..\n包括编号.姓名..\n");
    p0=(RD*)malloc(sizeof(RD));    
 re_input_reader:                    
     printf("ReaderNo.:");
     scanf("%s",p0->reader_num);

     while(strcmp(p0->reader_num,p2->reader_num)!=0&&p2->next!=NULL) 
        p2=p2->next;

     if(strcmp(p0->reader_num,p2->reader_num)==0)    
      {
        printf("\n此编号读者已存在!请重新输入\n");
         goto re_input_reader;
      }

     printf("ReaderName:");
     scanf("%s",p0->reader_name);
     p0->right=0; 

      for(i=0;i
     strcpy(p0->borrow[i].borrow_book_num,"0");

     while(strcmp(p->reader_num,p0->reader_num)!=0&&p->next!=NULL)
                               
           p1=p;p=p->next;     
      }
       if(strcmp(p0->reader_num,p->reader_num)<=0) 
        {
           if(p==h_reader) h_reader=p0;
           else p1->next=p0;
           p0->next=p;
        }
        else
        {
           p->next=p0;
           p0->next=NULL;
        }

     p=NULL;p0=NULL;p1=NULL;p2=NULL;
     printf("\n新读者增加完毕!按任意键继续下一步操作..\n");
     getchar();
     system("cls");

}//"Insert_New_Book()" end

void Insert_New_Book()
{
    BK*p=NULL,*p0=NULL,*p1=NULL,*p2=NULL; 
   p=p1=p2=h_book;
   printf("\n新书入库模块...\n");
   printf("\n请输入新书信息..\n包括编号.书名.数量..\n");

    p0=(BK*)malloc(sizeof(BK));

      printf("BookNo.:");
     scanf("%s",p0->book_num);   
      getchar();

     while(strcmp(p0->book_num,p2->book_num)!=0&&p2->next!=NULL)
        p2=p2->next;
     if(strcmp(p0->book_num,p2->book_num)==0) 
      {
        printf("\n此编号图书已存在!!直接入库!\n");
          printf("Number:");
         scanf("%d",&p0->book_kc);    
          getchar();
        p2->book_kc+=p0->book_kc;
         p2->book_xc+=p0->book_kc;
          gotoend;
      }

    printf("BookName:");  
     gets(p0->book_name);
     printf("Number:");
    scanf("%d",&p0->book_kc);     
     getchar();
       p0->book_xc=p0->book_kc; 

       while(strcmp(p->book_num,p0->book_num)!=0&&p->next!=NULL) 
        {
           p1=p; p=p->next;
        }
       if(strcmp(p0->book_num,p->book_num)<=0)
        {
           if(p==h_book) h_book=p0;
           else p1->next=p0;
           p0->next=p;
        }
        else
        {
           p->next=p0;
           p0->next=NULL;
        }

       end:
     algo43_main(); //生成关键字索引表,在algo4-3.cpp中定义
     p=NULL;p0=NULL;p1=NULL;p2=NULL;
     printf("\n新书入库完毕!按任意键继续下一步操作..\n");
     getchar();
     system("cls");    
}//"Insert_New_Book()" end

int Find() 
{
    intsn;
   printf("\n\t\t打印全部信息菜单\n");
   printf("===============================================\n");
   printf("*\t0----返回上级    1----关于系统 \t*\n");   
   printf("*\t                                \t*\n");
   printf("*\t2----查找图书    3----查找读者  \t*\n");
   printf("===============================================\n");
   printf("请选择相应代码:");
 for(;;)  
  {
     fflush(stdin);
     scanf("%d",&sn);
     getchar();
    if(sn<0||sn>3)
        printf("\n错误!请重新输入:");
     else break;
  }
  return sn;
}//"Find()" end
   
void Find_Select() 
{
   system("cls");
   for(;;)          
 {
  switch(Find()) 
  {
   case 0:system("cls");Menu_select(); break; 
   case 1:about();break;
   case2:Find_Book_contral();break;
   case3:Find_Reader();break;
  default:printf("\n错误!");exit(0);
   }
  }
}//"Find_Select()"end

int Find_Book_select()
{
    intsn;
   printf("\n\t\t打印全部信息菜单\n");
   printf("=================================================\n");
    printf("*\t0----返回上级        \n");   //MY  1 这条应该改成 关于查询系统 或是 查询帮助
   printf("*\t                                \t*\n");
    printf("*\t1----编号查询        2----关键字查询\t*\n");
   printf("=================================================\n");
   printf("请选择相应代码:");
   for(;;)  
    {
      fflush(stdin);
      scanf("%d",&sn);
      getchar();
      if(sn<0||sn>3)
         printf("\n错误!请重新输入:");
       elsebreak;
    }
  return sn; 
}//"Find_Book_select()"end

void Find_Book_contral()
{
   system("cls");
   for(;;)          
    {
       switch(Find_Book_select() ) 
       {
       case0:system("cls"); Find_Book_select(); break; 
       case1:Find_Book();break;
       case2:algo44_main();break; //algo44_main()algo4-4.cpp中定义
      default:printf("\n错误!");exit(0);
       }
    }
}//"Find_Book_contral()"end

void Find_Book() 
{
    BK*p=NULL;
    charfind_book[10]; 
   p=h_book;
   printf("\n图书查询模块\n");
   printf("\n请输入你要查询图书编号:");
   scanf("%s",find_book);
   getchar(); 

    while(strcmp(p->book_num,find_book)!=0&&p->next)
       p=p->next;

    if(strcmp(p->book_num,find_book)==0)   
    {
      printf("\n图书编号:%s的信息为:\n",find_book);
      printf("\nBookNo.\t\tBookName\t\t\tXianCun \tKuCun\n");
      printf("%s\t\t%s\t\t=\t\t=\n",p->book_num,p->book_name,p->book_xc,p->book_kc);
    }
     else
       printf("\n此图书编号不存在,请核对!按任意键返回...");

   p=NULL;                                        
    getchar();system("cls");
}//"Find_Book()"end

void Find_Reader() 
{
    RD*p=NULL;
    int i;
    charfind_reader[10];
   p=h_reader;
   printf("\n查询模块\n");
   printf("\n请输入你要查询读者编号:");
   scanf("%s",find_reader);
   getchar();

    while(strcmp(p->reader_num,find_reader)!=0&&p->next)
       p=p->next;
    if(strcmp(p->reader_num,find_reader)==0)
    {
     printf("\n读者编号:%s的信息为:\n",find_reader);

     printf("ReaderNo.\tReaderName"); 

      for(i=0;i
        printf("\tBorrowBookNum%d",i+1);   
      printf("\n");

     printf("%s\t\t%s",p->reader_num,p->reader_name);
      for(i=0;i
       printf("\t\t%7s",p->borrow[i].borrow_book_num);
      printf("\n");
    }

    else
       printf("\n此图书编号不存在,请核对!按任意键返回...");
   p=NULL;
    getchar();system("cls");
}//"Find_Reader()"end

void Borrow_Book() 
{
    BK*p=NULL;  RD *q=NULL;
    charbo_num[10],rea_num[10];
    inti=0,j=0;
    p=h_book;q=h_reader;
   printf("\n借书模块...\n");
   printf("\n请输入借书的读者编号:");
   scanf("%s",rea_num);
   getchar();

   while(q->next!=NULL&&strcmp(rea_num,q->reader_num)!=0) 
       q=q->next;

    if(q->next==NULL&&strcmp(rea_num,q->reader_num)!=0)  
    {
       printf("\n错误!此读者编号不存在!按任意键返回..\n");
       goto END;
    }
       
   printf("\n请输入你要借的书的编号:"); 
   scanf("%s",bo_num);
   getchar();

   while(strcmp(bo_num,p->book_num)!=0&&p->next!=NULL) 
      p=p->next;

   if(p->next==NULL&&strcmp(bo_num,p->book_num)!=0)
    {
       printf("\n错误!此图书编号不存在!按任意键返回..\n");
       goto END;
    }

   if(p->book_xc<=0)    
    {
      printf("\n抱歉,此书已借完!请等待新书的到来!!\n按任意键返回....");
       gotoEND;
    }
   printf("总共能借%d本,已借%d本\n",Max, q->right+1 );
   if(q->right>=Max) 
    {
      printf("\n不好意思,借书数目已满!不能借书!\n按任意键返回....");
       gotoEND;
    }

    else if(0 !=q->right ) //elseif(strcmp(q->borrow[0].borrow_book_num,"0")!=0)    
    {
      for(i=0;i
       {
         if(strcmp(q->borrow[i].borrow_book_num,bo_num)==0)
          {
            printf("\n抱歉!同一个读者不能同借两本相同的书!\n");
             gotoEND;
          }
          for(j=0; j
         if(strcmp(q->borrow[j].borrow_book_num,"0")==0)       
          {
             time_ttimep;
             char*wday[]={"星期天","星期一","星期二","星期三","星期四","星期五","星期六"};
             struct tm*pt=NULL;
            time(&timep);
            pt=localtime(&timep);
            printf("借书时间:\n");
               printf("\t%d年d月d日",(1900+pt->tm_year),(1+pt->tm_mon),pt->tm_mday);
             printf("%s\n\td:d:d\n",wday[pt->tm_wday],pt->tm_hour,pt->tm_min,pt->tm_sec);
            
            q->borrow[j].lend_t.st_year=(1900+pt->tm_year);  //year
              q->borrow[j].lend_t.st_mon=(1+pt->tm_mon);    //month
            q->borrow[j].lend_t.st_mday=pt->tm_mday;  //day
            //q->borrow[q->right].lend_t->st_wday  星期省略
            q->borrow[j].lend_t.st_hour=pt->tm_hour;  //hour
               q->borrow[j].lend_t.st_min=pt->tm_min;    //minute
               q->borrow[j].lend_t.st_sec=pt->tm_sec;    //second
               
              strcpy(q->borrow[j].borrow_book_num,bo_num);  
             q->right++;
            p->book_xc--;
              printf("\n读者编号%s借书完毕!按任意键继续下步操作..",q->reader_num);
             gotoEND;
         }//"if(strcmp(q->borrow[i].borrow_book_num,"0")==0)"end
      }//"for(i=0;i
    }//"elseif(strcmp(q->borrow[0].borrow_book_num,"0")!=0)"end

   else
   {
      time_t timep;
      char*wday[]={"星期天","星期一","星期二","星期三","星期四","星期五","星期六"};
      struct tm *pt=NULL;
     time(&timep);
     pt=localtime(&timep);
      printf("借书时间:\n");
     printf("%d年d月d日",(1900+pt->tm_year),(1+pt->tm_mon),pt->tm_mday);
      printf("%s\nd:d:d\n",wday[pt->tm_wday],pt->tm_hour,pt->tm_min,pt->tm_sec);
     
     q->borrow[q->right].lend_t.st_year=(1900+pt->tm_year);  //year
     q->borrow[q->right].lend_t.st_mon=(1+pt->tm_mon);    //month
     q->borrow[q->right].lend_t.st_mday=pt->tm_mday;  //day
     //q->borrow[q->right].lend_t->st_wday  星期省略
     q->borrow[q->right].lend_t.st_hour=pt->tm_hour;  //hour
     q->borrow[q->right].lend_t.st_min=pt->tm_min;    //minute
     q->borrow[q->right].lend_t.st_sec=pt->tm_sec;    //second
               
      strcpy(q->borrow[q->right++].borrow_book_num,bo_num);
      p->book_xc--;
      printf("\n读者编号%s借书完毕!按任意键继续下步操作..",q->reader_num);
    
   }//"else"end

     END:
       p=NULL;
      q=NULL;
       getchar();system("cls");
}//"Borrow_Book()"end
   
void Return_Book() 
{
    BK*p=NULL;  RD *q=NULL;
    inti,j,find=0,day=0;
    charreturn_book_num[10],return_reader_num[10];
    p=h_book;q=h_reader;
   printf("\n还书模块...\n");
   printf("\n请输入要还书的读者编号:"); 
   scanf("%s",return_reader_num);
   getchar();
   while(q->next!=NULL&&strcmp(return_reader_num,q->reader_num)!=0)
       q=q->next;
    if(q->next==NULL&&strcmp(return_reader_num,q->reader_num)!=0)
    {
       printf("\n错误!此读者编号不存在!按任意键返回..\n");
       goto End_return_book;
    }
       
   printf("\n请输入还书的编号:");
   scanf("%s",return_book_num);
   getchar();

   while(p->next!=NULL&&strcmp(return_book_num,p->book_num)!=0)
      p=p->next;

   if(p->next==NULL&&strcmp(return_book_num,p->book_num)!=0)
    {
      printf("\n错误!此图书编号不存在!按任意键返回..\n");
       gotoEnd_return_book;
    }

      for(i=0;i
      if(strcmp(return_book_num,q->borrow[i].borrow_book_num)==0)   
       {
         find++;     

           printf("借书时间:\n");
         printf("\t%d年d月d日",q->borrow[i].lend_t.st_year,q->borrow[i].lend_t.st_mon,q->borrow[i].lend_t.st_mday);
         printf("\n\td:d:d\n",q->borrow[i].lend_t.st_hour,q->borrow[i].lend_t.st_min,q->borrow[i].lend_t.st_sec);

          time_ttimep;
          //char*wday[]={"星期天","星期一","星期二","星期三","星期四","星期五","星期六"};
          struct tm*pt=NULL;
         time(&timep);
         pt=localtime(&timep);
         printf("还书时间:\n");
         printf("\t%d年d月d日",(1900+pt->tm_year),(1+pt->tm_mon),pt->tm_mday);
         printf("\n\td:d:d\n",pt->tm_hour,pt->tm_min,pt->tm_sec);
         
          day=((1900+pt->tm_year) -q->borrow[i].lend_t.st_year)*365;  //year
          day+=((1+pt->tm_mon) -q->borrow[i].lend_t.st_mon)*30;    //month
          day+=(pt->tm_mday -q->borrow[i].lend_t.st_mday);        //day
          day=(pt->tm_hour -q->borrow[i].lend_t.st_hour ) +day*24;   //hour
          day=(pt->tm_min -q->borrow[i].lend_t.st_min ) +day*60;    //minute
          day=( pt->tm_sec -q->borrow[i].lend_t.st_sec ) +day*60;    //second
         printf("共借阅:%d秒\n",day);

           strcpy(q->borrow[i].borrow_book_num,"0");
         p->book_xc++;
         q->right--;
               
          printf("\n编号%s的读者还书完毕!按任意键继续下步操作..",return_reader_num);
       }

  if(strcmp(return_book_num,q->borrow[Max-1].borrow_book_num)!=0&&find==0)  
    printf("\n错误!此读者未借此书!按任意键返回..\n");   

   End_return_book:
       p=NULL;
      q=NULL;
       getchar();system("cls");
}//"Return_Book()"end

void del_old_book() 
{
    BK*p=NULL,*q=NULL;
    chardel_num[10];
   p=h_book;
   printf("\n旧书出库模块\n");
   printf("\n请输入要出库的图书编号:");
   scanf("%s",del_num);
   getchar();

   while(strcmp(p->book_num,del_num)!=0&&p->next!=NULL)
    { q=p;p=p->next; }

   if(strcmp(p->book_num,del_num)==0)
    {
     if(p->book_kc!=p->book_xc)
         printf("\n抱歉,此图书未归还或数据出错,不能出库!按任意键返回...");
      else
                 
         if(p==h_book)
             h_book=p->next;
          else
            q->next=p->next;

      free(p);
      printf("\n编号为%s的图书删除完毕!按任意键继续...",del_num);
      }
    }
    else
        printf("\n你输入的图书编号不存在!按任意键返回...");
   p=NULL;
   q=NULL;
   getchar();system("cls");
}//"del_old_book()"end

void del_old_reader() 
{
    RD*p=NULL,*q=NULL;
    chardel_num[10];
   p=h_reader;
   printf("\n删除旧读者模块\n");
   printf("\n请输入要删除的读者编号:");
   scanf("%s",del_num);
   getchar();

   while(strcmp(p->reader_num,del_num)!=0&&p->next!=NULL)
    { q=p;p=p->next; }

   if(strcmp(p->reader_num,del_num)==0)
    {
     if(strcmp(p->borrow[0].borrow_book_num,"0")!=0)
         printf("\n抱歉,此读者还有图书没有归还,不能删除其信息!\n按任意键继续...");

       else
       {
         if(p==h_reader)
            h_reader=p->next;
          else
            q->next=p->next;
         free(p);

         printf("\n编号为%s的读者删除完毕!按任意键继续...",del_num);
       }
    }
    else
        printf("\n你输入的读者编号不存在!按任意键返回...");
   p=NULL;
   q=NULL;
   getchar();system("cls");

}//"del_old_reader()"end

int Print() 
{
    intsn;
   printf("\n\t\t打印全部信息菜单\n");
   printf("=================================================\n");
   printf("*\t0----返回上级    1----关于系统  \t*\n");
   printf("*\t                                \t*\n");
   printf("*\t2----打印图书    3----打印读者  \t*\n");
   printf("=================================================\n");
   printf("请选择相应代码:");
  for(;;) 
  {
     fflush(stdin);
     scanf("%d",&sn);
     getchar();
     //fflush(stdin);
    if(sn<0||sn>3)
        printf("\n错误!请重新输入:");
     else break;
  }
  return sn;
}//"Print()"end

void Print_Select()
{
   system("cls");  
   for(;;) 
 {
  switch(Print())
  {
   case 0:system("cls");Menu_select(); break; 
   case 1:about();break;
   case2:Print_book();break;
   case3:Print_reader();break;
     default:printf("\n错误!");exit(0);
   }
  }
}//"Print_Select()"end

void Print_book()
{
    BK*p=NULL;
   p=h_book;

   printf("\n库存图书信息如下:\n\n");
   printf("BookNo.\t\tBookName\t\t\tXianCun\tKuCun\n"); 

   while(p!=NULL) 
    {
      printf("%s\t\t%s\t\t=\t\t=\n",p->book_num,p->book_name,p->book_xc,p->book_kc);
      p=p->next;
    }

   p=NULL;
   printf("\n图书信息打印完毕!按任意键继续下一步操作..");
   getchar();
   system("cls");
}//"Print_book()"end

voidPrint_reader()     
{
    RD*p=NULL;
    int i;
   p=h_reader;

   printf("\n库存读者信息如下:\n\n");
   printf("ReaderNo.\tReaderName");     
   for(i=0;i
      printf("\tBorrowBookNum%d",i+1);
   printf("\n");
   while(p!=NULL)  
    {
      printf("%s\t\t%s",p->reader_num,p->reader_name);
      for(i=0;i
      printf("\t\t%7s",p->borrow[i].borrow_book_num);
      printf("\n");
      p=p->next;
    }
   p=NULL;
   printf("\n读者信息打印完毕!按任意键继续下一步操作..");
   getchar();
   system("cls");
}//"Print_reader()"end

void about()  
{
   system("cls");
   printf("\n\n\n\t\t\t关 于 本 系 统 的 说 明\n");
   printf("\n\t\t1.本系统为模拟小型图书馆而设计,界面采用数字选择界面.\n");
   printf("\n\t\t2.系统初始化时提示用户输入两组信息.\n");
   printf("\n\t\t3.初始化完毕后每个读者的借书权限为3本.\n\n\t\t4.读者借书后会在其信息中记录所借书号,未借者书号均为0.\n");
   printf("\n\t\t5.由于时间等原因,系统的其他功能还不健全,望大家见谅!");
   printf("\n\n\t\t6.建议:双击可执行文件后,在任务栏那点右键-->属性-->颜色\n\n\t\t 设置屏幕文字为:深蓝色(第10个) 屏幕背景为:淡绿色(第12个)");
   printf("\n\n\t\t 具体方法请参看文件夹内Word文档.\n\n\t\t7.系统如有其他问题,请联系作者!");
   printf("\n\n\t\t  E-mail:99688385@qq.com");
   printf("\n\n\n\t\t阅 读 完 毕, 按 任 意 键 继 续 ...");

    getchar();system("cls");
}//"about()"end

void book_not_enough() 
{
    BK*p=NULL;
    inti=0;
   p=h_book;
   while(p!=NULL)
    {
      if(p->book_xc==0) 
       {
         i++; 
         printf("\n库存不足的图书有:\n");
         printf("\nBookNumber\t\tBookName\n");
         printf("%s\t\t\t%s\n",p->book_num,p->book_name);
       }
      p=p->next;
    }

   if(p==NULL&&i==0)
      printf("\n暂时没有库存不足的图书!");
   p=NULL;
    getchar();system("cls");
}//"book_not_enough()"end



void Save() 
{
   Save_Reader();
   Save_Book();
}//"Save()"end

void Save_Reader()
{
    FILE*fp_reader=NULL;
    RD*p=NULL,*p0=NULL;
   p=h_reader;
   if((fp_reader=fopen("Reader.txt","wb"))==NULL)
    {
      printf("\n文件保存失败!\n请重新启动本系统...\n");
      exit(0);
    }
   while(p!=NULL)
    {
      if(fwrite(p,sizeof(RD),1,fp_reader)!=1) 
         printf("\n写入文件失败!\n请重新启动本系统!\n");
       p0=p;
      p=p->next;
      free(p0);   
           // Bug 当book.txt 和reader.txt都存在但都为空时,加载信息为空会出现bug,具体原因不解
    }

   h_reader=NULL;  
   fclose(fp_reader);
   fp_reader=NULL; 
   p=NULL;
   p0=NULL;
}//"Save_Reader()"end

void Save_Book()
{
    FILE*fp_book=NULL; 
    BK*p=NULL,*p0=NULL;
   p=h_book;   //(全局指针)
   if((fp_book=fopen("Book.txt","wb"))==NULL) // 此处必须用wb将文件全部更新
    {
      printf("\n文件保存失败!\n请重新启动本系统...\n");
      exit(0);
    }
   while(p!=NULL)
    {
      if(fwrite(p,sizeof(BK),1,fp_book)!=1)
         printf("\n写入文件失败!\n请重新启动本系统!\n");
       p0=p;
      p=p->next;
      free(p0);
    }

   p=NULL;
   p0=NULL;
   h_book=NULL;
   fclose(fp_book);
   fp_book=NULL;
}//"Save_Book()"end

void Load() 
{
   Load_Reader();
   Load_Book();
}//"Load()"end

void Load_Reader()
{
   RD*p1=NULL,*p2=NULL,*p3=NULL;
   FILE *fp=NULL;

  fp=fopen("Reader.txt","rb");
   p1=(RD*)malloc(sizeof(RD));
  fread(p1,sizeof(RD),1,fp);
   h_reader=p3=p2=p1;
   while(!feof(fp)) 
   p1=(RD*)malloc(sizeof(RD));
     fread(p1,sizeof(RD),1,fp);
     p2->next=p1;
     p3=p2;
     p2=p1;
   }
  p3->next=NULL;
   free(p1);
   p1=NULL;
   p2=NULL;
   p3=NULL;
   fclose(fp);
   fp=NULL;
}//"Load_Reader()"end


void Load_Book()
{
    BK*p1=NULL,*p2=NULL,*p3=NULL;
    FILE*fp=NULL;

   fp=fopen("Book.txt","rb");  
    p1=(BK*)malloc(sizeof(BK));
   fread(p1,sizeof(BK),1,fp);
   h_book=p3=p2=p1;
   while(! feof(fp))
   p1=(BK*)malloc(sizeof(BK));
     fread(p1,sizeof(BK),1,fp);
     p2->next=p1;
     p3=p2;
     p2=p1;
   }
   p3->next=NULL;
   free(p1);
   p1=p2=p3=NULL;
   fclose(fp);
   fp=NULL;
}//"Load_Book()"end
-------------------------------------------------------------------------------------------------
c4-2.h

#ifndef C4H
#define C4H

 // c4-2.h 串的堆分配存储
 struct HString
 {
   char *ch; //若是非空串,则按串长分配存储区,否则ch为NULL
   int length; // 串长度
 };

 //bo4-2.cpp function
 void StrAssign(HString &T,char*chars);
 void StrCopy(HString &T,HStringS);
 Status StrEmpty(HString S);
 int StrCompare(HString S,HString T);
 int StrLength(HString S);
 void ClearString(HString&S);
 void Concat(HString &T,HStringS1,HString S2);
 Status SubString(HString &Sub,HString S,int pos,int len);
 void InitString(HString&T);
 int Index(HString S,HString T,int pos);
 Status StrInsert(HString &S,intpos,HString T);
 Status StrDelete(HString &S,intpos,int len);
 Status Replace(HString &S,HStringT,HString V);// 此函数与串的存储结构无关
void StrPrint(HString T);

#endif
------------------------------------------------------------------------------------------
bo4-2.cpp

#include "c1.h"
typedef int ElemType;
#include "c2-5.h"
#include "c4-2.h"
#include "algo4-3.h"

 // bo4-2.cpp串采用堆分配存储结构(由c4-2.h定义)的基本操作(14个)。
//函数及结构体申明在c4-2.h中

 #define DestroyString ClearString //DestroyString()与ClearString()作用相同

 void StrAssign(HString &T,char*chars)
 { // 生成一个其值等于串常量chars的串T
   int i,j;
   if(T.ch)
    free(T.ch); // 释放T原有空间
   i=strlen(chars); //求chars的长度i
   if(!i)
   { // chars的长度为0
    T.ch=NULL;
    T.length=0;
   }
   else
   { // chars的长度不为0
    T.ch=(char*)malloc(i*sizeof(char)); // 分配串空间
    if(!T.ch) // 分配串空间失败
      exit(OVERFLOW);
    for(j=0;j
      T.ch[j]=chars[j];
    T.length=i;
   }
 }

 void StrCopy(HString &T,HStringS)
 { // 初始条件:串S存在。操作结果:由串S复制得串T
   int i;
   if(T.ch)
    free(T.ch); // 释放T原有空间
  T.ch=(char*)malloc(S.length*sizeof(char)); // 分配串空间
   if(!T.ch) // 分配串空间失败
    exit(OVERFLOW);
   for(i=0;i
    T.ch[i]=S.ch[i];
   T.length=S.length;
 }

 Status StrEmpty(HString S)
 { // 初始条件:串S存在。操作结果:若S为空串,则返回TRUE,否则返回FALSE
  if(S.length==0&&S.ch==NULL)
    return TRUE;
   else
    return FALSE;
 }

 int StrCompare(HString S,HString T)
 { //若S>T,则返回值>0;若S=T,则返回值=0;若S<0
   int i;
   for(i=0;i
    if(S.ch[i]!=T.ch[i])
      return S.ch[i]-T.ch[i];
   returnS.length-T.length;
 }

 int StrLength(HString S)
 { // 返回S的元素个数,称为串的长度
   return S.length;
 }

 void ClearString(HString&S)
 { // 将S清为空串
   free(S.ch);
   S.ch=NULL;
   S.length=0;
 }

 void Concat(HString &T,HStringS1,HString S2)
 { // 用T返回由S1和S2联接而成的新串
   int i;
   if(T.ch)
    free(T.ch); // 释放旧空间
  T.length=S1.length+S2.length;
   T.ch=(char*)malloc(T.length*sizeof(char));
   if(!T.ch)
    exit(OVERFLOW);
   for(i=0;i
    T.ch[i]=S1.ch[i];
   for(i=0;i
    T.ch[S1.length+i]=S2.ch[i];
 }

 Status SubString(HString &Sub,HString S,int pos,int len)
 { // 用Sub返回串S的第pos个字符起长度为len的子串。
   //其中,1≤pos≤StrLength(S)且0≤len≤StrLength(S)-pos+1
   int i;
  if(pos<1||pos>S.length||len<0||len>S.length-pos+1)
    return ERROR;
   if(Sub.ch)
    free(Sub.ch); // 释放旧空间
   if(!len) // 空子串
   {
    Sub.ch=NULL;
    Sub.length=0;
   }
   else
   { // 完整子串
    Sub.ch=(char*)malloc(len*sizeof(char));
    if(!Sub.ch)
      exit(OVERFLOW);
    for(i=0;i<=len-1;i++)
      Sub.ch[i]=S.ch[pos-1+i];
    Sub.length=len;
   }
   return OK;
 }

 void InitString(HString &T)
 { // 初始化(产生空串)字符串T。另加
   T.length=0;
   T.ch=NULL;
 }

 int Index(HString S,HString T,int pos) //算法4.1
 { // T为非空串。若主串S中第pos个字符之后存在与T相等的子串,
   //则返回第一个这样的子串在S中的位置,否则返回0
   int n,m,i;
   HString sub;
   InitString(sub);
   if(pos>0)
   {
    n=StrLength(S);
    m=StrLength(T);
    i=pos;
    while(i<=n-m+1)
    {
      SubString(sub,S,i,m);
      if(StrCompare(sub,T)!=0)
        ++i;
      else
        return i;
    }
   }
   return 0;
  }

 Status StrInsert(HString &S,intpos,HString T) // 算法4.4
 { // 1≤pos≤StrLength(S)+1。在串S的第pos个字符之前插入串T
   int i;
  if(pos<1||pos>S.length+1) //pos不合法
    return ERROR;
   if(T.length) //T非空,则重新分配空间,插入T
   {
    S.ch=(char*)realloc(S.ch,(S.length+T.length)*sizeof(char));
    if(!S.ch)
      exit(OVERFLOW);
    for(i=S.length-1;i>=pos-1;--i) // 为插入T而腾出位置
      S.ch[i+T.length]=S.ch[i];
    for(i=0;i
      S.ch[pos-1+i]=T.ch[i]; // 插入T
    S.length+=T.length;
   }
   return OK;
 }

 Status StrDelete(HString &S,intpos,int len)
 { // 从串S中删除第pos个字符起长度为len的子串
   int i;
   if(S.length
    return ERROR;
  for(i=pos-1;i<=S.length-len;i++)
    S.ch[i]=S.ch[i+len];
   S.length-=len;
  S.ch=(char*)realloc(S.ch,S.length*sizeof(char));
   return OK;
 }

 Status Replace(HString &S,HStringT,HString V) // 此函数与串的存储结构无关
 { // 初始条件:串S,T和V存在,T是非空串
   //操作结果:用V替换主串S中出现的所有与T相等的不重叠的子串
   int i=1; //从串S的第一个字符起查找串T
   if(StrEmpty(T)) // T是空串
    return ERROR;
   do
   {
    i=Index(S,T,i); // 结果i为从上一个i之后找到的子串T的位置
    if(i) // 串S中存在串T
    {
      StrDelete(S,i,StrLength(T)); // 删除该串T
      StrInsert(S,i,V); // 在原串T的位置插入串V
      i+=StrLength(V); // 在插入的串V后面继续查找串T
    }
   }while(i);
   return OK;
 }

 void StrPrint(HString T)
 { // 输出T字符串。另加
   int i;
   for(i=0;i
    printf("%c",T.ch[i]);
   printf("\n");
 }

--------------------------------------------------------------------------------
c4-3.h

#ifndef ALGO43H
#define ALGO43H

#include "c2-5.h"
#include "c4-2.h"
typedef int ElemType;
//bo2-6.cpp function
void MakeNode(Link &p,ElemType e);
void FreeNode(Link &p);
void InitList(LinkList &L);
void ClearList(LinkList &L);
void DestroyList(LinkList &L);
void InsFirst(LinkList &L,Link h,Link s); //形参增加L,因为需修改L
Status DelFirst(LinkList &L,Link h,Link&q); // 形参增加L,因为需修改L
void Append(LinkList &L,Link s);
Position PriorPos(LinkList L,Link p);
Status Remove(LinkList &L,Link&q);
void InsBefore(LinkList &L,Link&p,Link s);
void InsAfter(LinkList &L,Link&p,Link s);
void SetCurElem(Link p,ElemType e);
ElemType GetCurElem(Link p);
Status ListEmpty(LinkList L);
int ListLength(LinkList L);
Position GetLast(LinkList L);
Position GetHead(LinkList L);
Position NextPos(Link p);
Status LocatePos(LinkList L,int i,Link &p);
Position LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType));
void ListTraverse(LinkList L,void(*visit)(ElemType));
void OrderInsert(LinkList &L,ElemType e,int(*comp)(ElemType,ElemType));
Status LocateElem(LinkList L,ElemType e,Position&q,int(*compare)(ElemType,ElemType));


//algo4-3.cpp
#define MaxKeyNum 25 //索引表的最大容量(关键词的最大数目)
#define MaxLineLen 52 //数目串(也是一个书目中的关键词)的最大数目
#define MaxNoIdx 10
 
struct WordLisType//一个书目的词表(顺序表)和非索引词表(有序表)共用类型
{
    char*item[MaxNoIdx];  //词表(字符串)指针数组
    intlast;   //词的数量
};

struct IdxTermType  //索引项类型
{
    HStringkey;   //关键词(堆分配类型,c4-2.h)
    LinkListbnolist;  //存放书号索引的链表(c2-5.h)
};

structIdxListType   //索引表类型(有序表)
{
    IdxTermTypeitem[MaxKeyNum+1];  //索引项数组类型
    intlast;  //关键词的个数
};

void InitIdxList(IdxListType &idxlist);
void ExtractKeyWord(int &BookNo);
void GetWord(int i, HString &wd);
int Locate(IdxListType &idxlist, HString wd, Status&b);
void InsertNewKey(IdxListType &idxlist,inti,HString wd);
void InsertBook(IdxListType &idxlist, int i, intbno);
void InsIdxList(IdxListType &idxlist , intbno);
void PutText(FILE *f , IdxListType idxlist);
void algo43_main(void);

//algo4-4.cpp
#define MaxBookNum 10 // 假设只对10个书名建索引表
#define MaxKeyNum 25 // 索引表的最大容量(关键词的最大数目)

struct BookTermType // 书目项类型
{
    charbookname[MaxLineLen+1]; // 书名串(包括'\0')
    int bookno;// 书号
};

struct BookListType // 书目表类型(有序表)
{
    BookTermTypeitem[MaxBookNum]; // 书目项数组类型
    int last; //书目的数量
 };

void algo44_main();

#endif
---------------------------------------------------------------------------------
algo4-3.cpp

#include "c1.h"
typedef int ElemType;
#include "c2-5.h"
#include "c4-2.h"
#include "algo4-3.h"
#include "first.h"

//函数及结构体申明在algo4-3.h中

//全局变量
BK  bookinfo;//BK * bookinfo=NULL;
char buf[MaxLineLen+1];  
WordLisType wdlist,noidx;

//初始化操作,置索引表idxlist为空表,且在idxlist.item[0]设一空串
void InitIdxList(IdxListType&idxlist)     
{
   idxlist.last=0;
   InitString(idxlist.item[0].key);  //初始化[0]单元,函数在bo2-4.cpp中
   InitList(idxlist.item[0].bnolist); //初始化[0]单元,函数在bo2-6.cpp中
}

void ExtractKeyWord(int &BookNo)
{
    inti,l,f=1;  //f是字符串buf结束标志0:结束  1:未结束
    char*s1=NULL,*s2=NULL;
    for(i = 1; i<= wdlist.last; i++)
    {
      free(wdlist.item[i]);  //释放上一个书目在词表wdlist的存储空间
      wdlist.item[i]=NULL;
    }
   wdlist.last=0;  // 初始化词表wdlist的词数量
    BookNo=atoi(bookinfo.book_num);
       
   s1=buf;//s1=&buf[4];  
   while(f)  //提取书名关键词到词表wdlist
    {
      s2=strchr(s1, ' ');  //s2指向s1后的第一个空格,如没有,返回NULL
      if(!s2)   //到串尾(没空格)
       {
         s2=strchr(s1,'\0');//s2=strchr(s1,'\12'); 
           //s2指向buf的最后一个字符(回车符10) MY应该改为'\0'(串结束标志),gets不保存回车符
          f=0;
       }
      l=s2-s1;   //单词长度
       if(s1[0]>= 'A' && s1[0]<= 'Z')  //单词首写字母为大写
       //写入词表
         wdlist.item[wdlist.last]=(char*)malloc((l+1)*sizeof(char));  
           //生成串空间(包括‘\0’)
          for(i = 0; i< l; i++)
            wdlist.item[wdlist.last][i]=s1[i];  //写入词表
         wdlist.item[wdlist.last][l]=0;  // 串结束符‘\0’== 0
          for(i =0; i< noidx.last&&(l=strcmp(wdlist.item[wdlist.last],noidx.item[i]))>0 ;i++)
                //查找是否为非索引词
         if(!l)   //是非索引词
          {
            free(wdlist.item[wdlist.last]);  //从词表中删除该词
            wdlist.item[wdlist.last]=NULL;
          }
          else
            wdlist.last++;   //词表长度加1
       }
      s1=s2+1;  //s1移动到下一个单词的首字符处
    };
   s1=NULL;s2=NULL;
}

//用wd返回词表wdlist中的第i个关键词
void GetWord(int i, HString &wd)
{
   StrAssign(wd,wdlist.item[i]);  //生成关键字字符串 bo2-4.cpp
}

//在索引表idxlist中查询是否存在与wd相等的关键词。若存在,则返回其在索引表中的位置,且b取值TRUE;否则返回插入的位置,且b取值FALSE
int Locate(IdxListType &idxlist, HString wd, Status&b)
{
    int i,m;
    for(i=idxlist.last; (m =StrCompare(idxlist.item[i].key , wd)) > 0;--i)
        //bo4-2.cpp
    if (m == 0)  //finded
    {
        b = TRUE;
       return i;
    }
    else
    {
        b = FALSE;
       return i+1;
    }
}


//索引表idxlist的第i项上插入关键词wd,并初始化书号索引的链表为空表
void InsertNewKey(IdxListType &idxlist,inti,HString wd)
{
    intj=0;
    for (j =idxlist.last; j >= i; --j) //后移索引项
    {
      idxlist.item[j+1] = idxlist.item[j];
    }
   InitString(idxlist.item[i].key);  //bo4-2.cpp
    StrCopy(idxlist.item[i].key , wd);  //串拷贝插入新的索引项bo2-4.cpp
   InitList(idxlist.item[i].bnolist);   //初始化书号索引表为空表 bo2-6.cpp
   idxlist.last++;
}

//在索引表idxlist的第i项中插入书号为bno的索引
void InsertBook(IdxListType &idxlist, int i, intbno)
{
    Linkp;
    MakeNode(p ,bno);   //分配结点 bo2-6.cpp
   p->next=NULL;
   Append(idxlist.item[i].bnolist , p);  //插入新的书号索引bo2-6.cpp
}

//将新书号为bno的关键词插入索引表
void InsIdxList(IdxListType &idxlist , intbno)
{
    inti=0,j=0;
    Statusb;
    HStringwd;
   InitString(wd);
    for(i = 0;i< wdlist.last ; i++)
    {
       GetWord(i,wd);
       j =Locate(idxlist , wd , b);
       if(!b)
       {
         InsertNewKey(idxlist , j ,wd);
       }
      InsertBook(idxlist , j , bno);
    }
}

//将生成的索引表idxlist输出到文件f
void PutText(FILE *f , IdxListType idxlist)
{
    inti=0,j=0;
    Linkp;
    fprintf(f,"%d\n" , idxlist.last);
    for (i = 1;i <= idxlist.last; i++)
    {
       for(j = 0; j< idxlist.item[i].key.length; j++)
          fprintf(f,"%c", idxlist.item[i].key.ch[j]);
       fprintf(f,"\n%d\n",idxlist.item[i].bnolist.len);
   
       p =idxlist.item[i].bnolist.head;
       for(j = 1; j<= idxlist.item[i].bnolist.len; j++)
       {
          p =p->next;
          fprintf( f,"%d ", p->data);
       }
       fprintf(f,"\n");
    }//end"for(i = 1; ...)"
}

void algo43_main(void)
{
    FILE *f; //任何时间最多打开一个文件
    IdxListTypeidxlist; // 索引表
    int BookNo;// 书号变量
    int k;

   if(!(f=fopen("NoIdx.txt","r"))) // 打开非索引词文件
    {
      printf("Can't open the NoIdx.txt file");
      exit(OVERFLOW);
    }
   fscanf(f,"%d",&noidx.last); // 读取非索引词个数
   for(k=0;k
    {
      fscanf(f,"%s",buf);
       if((noidx.item[k]=(char*)malloc((strlen(buf)+1)*sizeof(char)))==NULL)
       {
         printf("分配失败!");
         exit(1);
       }
      strcpy(noidx.item[k],buf);   //Bug  buf的值赋不到noidx.item[k]中
    }
    fclose(f);// 关闭非索引词文件


   if(!(f=fopen("Book.txt","r"))) // 打开书目文件
    {
      printf("Can't open the Book.txt file");
      exit(FALSE);
    }
   InitIdxList(idxlist); // 设索引表idxlist为空,并初始化[0]单元
   fread(&bookinfo,1,sizeof(structbook),f);  //fread(buf,1,sizeof(structbook),f);
   while(!feof(f))
    {
       strcpy(buf,bookinfo.book_name);
       ExtractKeyWord(BookNo);
      InsIdxList(idxlist,BookNo);
      fread(&bookinfo,1,sizeof(structbook),f);    
    }
   fclose(f);
   f=NULL;  
   

   if(!(f=fopen("BookIdx.txt","w"))) // 打开书名关键词索引文件
    {
       printf("Can't open the BookIdx.txt file");
      exit(INFEASIBLE);
    }
   PutText(f,idxlist); // 将生成的索引表idxlist输出到书名关键词索引文件
    fclose(f);// 关闭书名关键词索引文件
}

---------------------------------------------------------------------------------
algo4-3.h  //algo4-3.cpp中使用的相关宏定义,bo2-6.cpp中的函数申明
#ifndef ALGO43H
#define ALGO43H

#include "c2-5.h"
#include "c4-2.h"
typedef int ElemType;
//bo2-6.cpp function
void MakeNode(Link &p,ElemType e);
void FreeNode(Link &p);
void InitList(LinkList &L);
void ClearList(LinkList &L);
void DestroyList(LinkList &L);
void InsFirst(LinkList &L,Link h,Link s); //形参增加L,因为需修改L
Status DelFirst(LinkList &L,Link h,Link&q); // 形参增加L,因为需修改L
void Append(LinkList &L,Link s);
Position PriorPos(LinkList L,Link p);
Status Remove(LinkList &L,Link&q);
void InsBefore(LinkList &L,Link&p,Link s);
void InsAfter(LinkList &L,Link&p,Link s);
void SetCurElem(Link p,ElemType e);
ElemType GetCurElem(Link p);
Status ListEmpty(LinkList L);
int ListLength(LinkList L);
Position GetLast(LinkList L);
Position GetHead(LinkList L);
Position NextPos(Link p);
Status LocatePos(LinkList L,int i,Link &p);
Position LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType));
void ListTraverse(LinkList L,void(*visit)(ElemType));
void OrderInsert(LinkList &L,ElemType e,int(*comp)(ElemType,ElemType));
Status LocateElem(LinkList L,ElemType e,Position&q,int(*compare)(ElemType,ElemType));


//algo4-3.cpp
#define MaxKeyNum 25 //索引表的最大容量(关键词的最大数目)
#define MaxLineLen 52 //数目串(也是一个书目中的关键词)的最大数目
#define MaxNoIdx 10
 
struct WordLisType//一个书目的词表(顺序表)和非索引词表(有序表)共用类型
{
    char*item[MaxNoIdx];  //词表(字符串)指针数组
    intlast;   //词的数量
};

struct IdxTermType  //索引项类型
{
    HStringkey;   //关键词(堆分配类型,c4-2.h)
    LinkListbnolist;  //存放书号索引的链表(c2-5.h)
};

structIdxListType   //索引表类型(有序表)
{
    IdxTermTypeitem[MaxKeyNum+1];  //索引项数组类型
    intlast;  //关键词的个数
};

void InitIdxList(IdxListType &idxlist);
void ExtractKeyWord(int &BookNo);
void GetWord(int i, HString &wd);
int Locate(IdxListType &idxlist, HString wd, Status&b);
void InsertNewKey(IdxListType &idxlist,inti,HString wd);
void InsertBook(IdxListType &idxlist, int i, intbno);
void InsIdxList(IdxListType &idxlist , intbno);
void PutText(FILE *f , IdxListType idxlist);
void algo43_main(void);

//algo4-4.cpp
#define MaxBookNum 10 // 假设只对10个书名建索引表
#define MaxKeyNum 25 // 索引表的最大容量(关键词的最大数目)

struct BookTermType // 书目项类型
{
    charbookname[MaxLineLen+1]; // 书名串(包括'\0')
    int bookno;// 书号
};

struct BookListType // 书目表类型(有序表)
{
    BookTermTypeitem[MaxBookNum]; // 书目项数组类型
    int last; //书目的数量
 };

void algo44_main();

#endif
---------------------------------------------------------------------------------
algo4-4.cpp   
//根据algo4-3.cpp产生的文件,索引查询图书

#include "c1.h"
typedef int ElemType;
#include "c2-5.h"
#include "c4-2.h"
#include "algo4-3.h"
#include "first.h"


//结构体定义和函数声明放在algo4-3.h中
 void algo44_main()
 {
   FILE *f; // 任何时间最多打开一个文件
   IdxListType idxlist; //索引表
   BookListType booklist; //书目表
   char buf[MaxLineLen+5]; //当前书目串(包括书号和'\0')
   HString ch; // 索引字符串
   int BookNo; // 书号
   Link p; // 链表指针
   int i,j,k,flag=1; //flag是继续查询的标志

   InitString(ch); //初始化HString类型的变量
  if(!(f=fopen("BookIdx.txt","r"))) // 打开书名关键词索引表文件
   {
      printf("BookIdx.txt can notopen!\n");
      exit(OVERFLOW);
   }
  fscanf(f,"%d",&idxlist.last); // 书名关键词个数
   for(k=0;k
   {
     fscanf(f,"%s",buf);
     i=0;
     while(buf[i])
          buf[i++]=tolower(buf[i]); // 字母转为小写
     InitString(idxlist.item[k].key);
     StrAssign(idxlist.item[k].key,buf);
     InitList(idxlist.item[k].bnolist); // 初始化书号链表,bo2-6.cpp

     fscanf(f,"%d",&i);
     for(j=0;j
     {
         fscanf(f,"%d",&BookNo);
         MakeNode(p,BookNo); // 产生新的书号结点,bo2-6.cpp
         p->next=NULL; // 给书号结点的指针域赋值
         Append(idxlist.item[k].bnolist,p); // 在表尾插入新的书号结点,bo2-6.cpp
     }
   }
   fclose(f);

   if(!(f=fopen("Book.txt","r")))// 打开书目文件
    
      printf("Can not openBook.txt\n");
      exit(FALSE);
   }
   i=0;
  while(fgets(buf,MaxLineLen,f))
   { // 把书目文件的内容拷到booklist中
      booklist.item[i].bookno=atoi(buf); // 前几位数字为书号
      strcpy(booklist.item[i++].bookname,&buf[4]); //将buf由书名开始的字符串拷贝到booklist中
   }
   booklist.last=i;

   while(flag)
   {
      printf("请输入书目的关键词(一个):");
      scanf("%s",buf);
      i=0;
      while(buf[i])
           buf[i++]=tolower(buf[i]); // 字母转为小写
      StrAssign(ch,buf);
      i=0;
      do
      {
          k=StrCompare(ch,idxlist.item[i++].key); // bo4-2.cpp
     }while(k&&i<=idxlist.last);
      if(!k) // 索引表中有此关键词
      {
          p=idxlist.item[--i].bnolist.head->next; //p指向索引表中此关键词相应链表的首元结点
          while(p)
         {
              j=0;
              while(jdata!=booklist.item[j].bookno) // 在booklist中找相应的书号
              j++;
              if(j
                 printf("=%s",booklist.item[j].bookno,booklist.item[j].bookname);
              p=p->next; // 继续向后找
         }
    }
    else
        printf("没找到\n");
        printf("继续查找请输入1,退出查找请输入0:");
        scanf("%d",&flag);
       //getchar();
   }
   fclose(f);
   f=NULL;
   getchar();system("cls");
 }


//调整algo44_main()函数的一些地方以适应book.txt文件数据的存放模式

---------------------------------------------------------------------------------
bo2-6.cpp   //链表的各种操作函数

#include "c1.h"
typedef int ElemType;
#include "c2-5.h"
#include "c4-2.h"
#include "algo4-3.h"

// bo2-6.cpp 具有实用意义的线性链表(存储结构由c2-5.h定义)的24个基本操作

//函数及结构体申明在algo4-3.h中

 void MakeNode(Link &p,ElemTypee)
 { // 分配由p指向的值为e的结点。若分配失败,则退出
  p=(Link)malloc(sizeof(LNode));
   if(!p)
    exit(ERROR);
  p->data=e;
 }

 void FreeNode(Link &p)
 { // 释放p所指结点
   free(p);
   p=NULL;
 }

 void InitList(LinkList &L)
 { // 构造一个空的线性链表L
   Link p;
   p=(Link)malloc(sizeof(LNode));// 生成头结点
   if(p)
   {
    p->next=NULL;
    L.head=L.tail=p;
    L.len=0;
   }
   else
    exit(ERROR);
 }

 void ClearList(LinkList &L)
 { // 将线性链表L重置为空表,并释放原链表的结点空间
   Link p,q;
   if(L.head!=L.tail) //不是空表
   {
    p=q=L.head->next;
    L.head->next=NULL;
    while(p!=L.tail)
    {
      p=q->next;
      free(q);
      q=p;
    }
    free(q);
    L.tail=L.head;
    L.len=0;
   }
 }

 void DestroyList(LinkList&L)
 { // 销毁线性链表L,L不再存在
   ClearList(L); // 清空链表
   FreeNode(L.head);
   L.tail=NULL;
   L.len=0;
 }

 void InsFirst(LinkList &L,Linkh,Link s) // 形参增加L,因为需修改L
 { // h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前
  s->next=h->next;
  h->next=s;
   if(h==L.tail) // h指向尾结点
    L.tail=h->next; // 修改尾指针
   L.len++;
 }

 Status DelFirst(LinkList &L,Linkh,Link &q) // 形参增加L,因为需修改L
 { // h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。
   //若链表为空(h指向尾结点),q=NULL,返回FALSE
  q=h->next;
   if(q) // 链表非空
   {
    h->next=q->next;
    if(!h->next) // 删除尾结点
      L.tail=h; // 修改尾指针
    L.len--;
    return OK;
   }
   else
    return FALSE; // 链表空
 }

 void Append(LinkList &L,Links)
 { //将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的
   //一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新的尾结点
   int i=1;
  L.tail->next=s;
  while(s->next)
   {
    s=s->next;
    i++;
   }
   L.tail=s;
   L.len+=i;
 }

 Position PriorPos(LinkList L,Link p)
 { //已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置。若无前驱,则返回NULL
   Link q;
  q=L.head->next;
   if(q==p) // 无前驱
    return NULL;
   else
   {
    while(q->next!=p) // q不是p的直接前驱
      q=q->next;
    return q;
   }
 }

 Status Remove(LinkList &L,Link&q)
 { // 删除线性链表L中的尾结点并以q返回,改变链表L的尾指针指向新的尾结点
   Link p=L.head;
   if(L.len==0) // 空表
   {
    q=NULL;
    return FALSE;
   }
  while(p->next!=L.tail)
    p=p->next;
   q=L.tail;
  p->next=NULL;
   L.tail=p;
   L.len--;
   return OK;
 }

 void InsBefore(LinkList &L,Link&p,Link s)
 { // 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之前,
   // 并修改指针p指向新插入的结点
   Link q;
   q=PriorPos(L,p); //q是p的前驱
   if(!q) // p无前驱
    q=L.head;
  s->next=p;
  q->next=s;
   p=s;
   L.len++;
 }

 void InsAfter(LinkList &L,Link&p,Link s)
 { // 已知p指向线性链表L中的一个结点,将s所指结点插入在p所指结点之后,
   // 并修改指针p指向新插入的结点
   if(p==L.tail) // 修改尾指针
    L.tail=s;
  s->next=p->next;
  p->next=s;
   p=s;
   L.len++;
 }

 void SetCurElem(Link p,ElemType e)
 { // 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值
  p->data=e;
 }

 ElemType GetCurElem(Link p)
 { // 已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值
   returnp->data;
 }

 Status ListEmpty(LinkList L)
 { // 若线性链表L为空表,则返回TRUE,否则返回FALSE
   if(L.len)
    return FALSE;
   else
    return TRUE;
 }

 int ListLength(LinkList L)
 { // 返回线性链表L中元素个数
   return L.len;
 }

 Position GetHead(LinkList L)
 { // 返回线性链表L中头结点的位置
   return L.head;
 }

 Position GetLast(LinkList L)
 { // 返回线性链表L中最后一个结点的位置
   return L.tail;
 }

 Position NextPos(Link p)
 { //已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置。若无后继,则返回NULL
   returnp->next;
 }

 Status LocatePos(LinkList L,int i,Link&p)
 { //返回p指示线性链表L中第i个结点的位置,并返回OK,i值不合法时返回ERROR。i=0为头结点
   int j;
  if(i<0||i>L.len)
    return ERROR;
   else
   {
    p=L.head;
    for(j=1;j<=i;j++)
      p=p->next;
    return OK;
   }
 }

 Position LocateElem(LinkList L,ElemType e,Status(*compare)(ElemType,ElemType))
 { // 返回线性链表L中第1个与e满足函数compare()判定关系的元素的位置,
   // 若不存在这样的元素,则返回NULL
   Link p=L.head;
   do
    p=p->next;
  while(p&&!(compare(p->data,e)));// 没到表尾且没找到满足关系的元素
   return p;
 }

 void ListTraverse(LinkListL,void(*visit)(ElemType))
 { // 依次对L的每个数据元素调用函数visit()
   Linkp=L.head->next;
   int j;
  for(j=1;j<=L.len;j++)
   {
    visit(p->data);
    p=p->next;
   }
   printf("\n");
 }

 void OrderInsert(LinkList&L,ElemType e,int (*comp)(ElemType,ElemType))
 { // 已知L为有序线性链表,将元素e按非降序插入在L中。(用于一元多项式)
   Link o,p,q;
   q=L.head;
  p=q->next;
  while(p!=NULL&&comp(p->data,e)<0)// p不是表尾且元素值小于e
   {
    q=p;
    p=p->next;
   }
   o=(Link)malloc(sizeof(LNode));// 生成结点
   o->data=e; //赋值
   q->next=o; //插入
  o->next=p;
   L.len++; // 表长加1
   if(!p) // 插在表尾
    L.tail=o; // 修改尾结点
 }

 Status LocateElem(LinkList L,ElemType e,Position&q,int(*compare)(ElemType,ElemType))
 { //若升序链表L中存在与e满足判定函数compare()取值为0的元素,则q指示L中
   //第一个值为e的结点的位置,并返回TRUE;否则q指示第一个与e满足判定函数
   //compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式)
   Link p=L.head,pp;
   do
   {
    pp=p;
    p=p->next;
  }while(p&&(compare(p->data,e)<0));//没到表尾且p->data.expn  if(!p||compare(p->data,e)>0) //到表尾或compare(p->data,e)>0
   {
    q=pp;
    return FALSE;
   }
   else // 找到
   {
    q=p;
    return TRUE;
   }
 }

---------------------------------------------------------------------------------
c1.h   //常用头文件、宏等的定义

#ifndef HEAD1
#define HEAD1

#include
#include
#include   //malloc()等
#include   //INT_MAX等
#include   //FOF(=^Z或F6),NUll
#include   //atoi()
#include     //eof()
#include    //floor(),ceil(),abs()
#include //exit()
#include //cout,cin

//函数结果状态代码
#defineTRUE      1
#defineFALSE     0
#defineOK        1
#defineERROR     0
#define INFEASIBLE -1
//#define OVERFLOW -2 因为在math.h中已定义OVERFLOW的值为3,故去掉此行

typedef int Status;  //Status是函数的类型,其值是函数结果状态代码,如OK等
typedef int Boolean; //Boolean是布尔类型,其值是TRUE或FALSE

#endif
---------------------------------------------------------------------------------
c2-5.h
   //链表结点的相关定义

#ifndef C2H
#define C2H

typedef int ElemType;
 // c2-5.h 带头结点的线性链表类型
 typedef struct LNode // 结点类型
 {
   ElemType data;
   LNode *next;
 }*Link,*Position;

 struct LinkList // 链表类型
 {
   Link head,tail; //分别指向线性链表中的头结点和最后一个结点
   int len; //指示线性链表中数据元素的个数
 };

#endif
---------------------------------------------------------------------------------------------
   看完代码我自己都怀疑当初是这么实现的,代码繁多。不过回想起来,一个个功能的按部就班的实现也就成了这个摸样。

原创粉丝点击