全部实现代码如下:
--------------------------------------------------------------------------------------
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();
     
      return 0;
}
-----------------------------------------------------------------------------------------------
first.h

#ifndef FIRSTH1
#define FIRSTH1

// #include  
// #include
// #include
#include
#define Max 3         

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

typedef struct Start
{
      int st_sec;
      int st_hour;
      int st_mday;
      int st_min;
      int st_mon;
      int st_year;
}start;

typedef struct borrow   
{
      char borrow_book_num[10];
      start lend_t;
}BO;

typedef struct reader           
{
      char reader_num[10];
      char reader_name[10];
      int right;        //MY读者最多借书本数
      BO borrow[Max]; 
      struct reader * next;
}RD;
//BK *h_book;             
//RD *h_reader;         

int Menu();                             
void Menu_select();             
void Init();                           
void Init_reader();           
void Init_book();               
void Insert_New_Book();     
void Insert_New_Reader(); 
void del_old_book();           
void del_old_reader();       
void book_not_enough();     
int Find();                             
void Find_Select();           
void Find_Reader();           
void Find_Book_contral(); 
int  Find_Book_select(); 
void Find_Book();                 
void Borrow_Book();             
void Return_Book();             
void about();                         
int Print();                           
void Print_Select();         
void Print_book();             
void Print_reader();         
void Save();                           
void Save_Reader();           
void Save_Book();               
void Load();                           
void Load_Reader();           
void Load_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;
      int sn=-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()
{
      char i='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);
       
    case 1:Insert_New_Book();break; 
    case 2:Insert_New_Reader();break;
    case 3:Find_Select();break;
    case 4:Borrow_Book();break;
    case 5:Return_Book();break;
    case 6:about();break;
    case 7:del_old_book();break;
    case 8:del_old_reader();break;
    case 9:Print_Select();break;
    case 10: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;
                  goto end;
          }

        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() 
{
      int sn;
      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;
    case 2:Find_Book_contral();break;
    case 3:Find_Reader();break;
    default:printf("\n错误!");exit(0);
    }
  }
}//"Find_Select()"end

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

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

void Find_Book() 
{
      BK *p=NULL;
      char find_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;
      char find_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;
      char bo_num[10],rea_num[10];
      int i=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按任意键返回....");
            goto END;
      }
      printf("总共能借%d本,已借%d本\n",Max, q->right+1 );
      if(q->right>=Max) 
      {
            printf("\n不好意思,借书数目已满!不能借书!\n按任意键返回....");
            goto END;
      }

      else if(0 != q->right ) //else if(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");
                        goto END;
                  }
                    for(j=0; j
                  if(strcmp(q->borrow[j].borrow_book_num,"0")==0)             
                  {
                        time_t timep;
                        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);
                        goto END;
                  }//"if(strcmp(q->borrow[i].borrow_book_num,"0")==0)"end
            }//"for(i=0;i
      }//"else if(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;
      int i,j,find=0,day=0;
      char return_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");
            goto End_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_t timep;
                  //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;
      char del_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;
      char del_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() 
{
      int sn;
      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;
    case 2:Print_book();break;
    case 3: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

void Print_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;
      int i=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,HString S);
  Status StrEmpty(HString S);
  int StrCompare(HString S,HString T);
  int StrLength(HString S);
  void ClearString(HString &S);
  void Concat(HString &T,HString S1,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,int pos,HString T);
  Status StrDelete(HString &S,int pos,int len);
  Status Replace(HString &S,HString T,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,HString S)
 { // 初始条件:串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];
   return S.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,HString S1,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,int pos,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,int pos,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,HString T,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];   //词表(字符串)指针数组
    int last;   //词的数量
};

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

struct IdxListType    //索引表类型(有序表)
{
    IdxTermType item[MaxKeyNum+1];   //索引项数组类型
    int last;  //关键词的个数
};

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,int i,HString wd);
void InsertBook(IdxListType &idxlist, int i, int bno);
void InsIdxList(IdxListType &idxlist , int bno);
void PutText(FILE *f , IdxListType idxlist);
void algo43_main(void);

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

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

struct BookListType // 书目表类型(有序表)
{
    BookTermType item[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)
{
    int i,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,int i,HString wd)
{
    int j=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, int bno)
{
    Link p;
    MakeNode(p , bno);   //分配结点 bo2-6.cpp
    p->next=NULL;
    Append(idxlist.item[i].bnolist , p);  //插入新的书号索引 bo2-6.cpp
}

//将新书号为bno的关键词插入索引表
void InsIdxList(IdxListType &idxlist , int bno)
{
    int i=0,j=0;
    Status b;
    HString wd;
    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)
{
    int i=0,j=0;
    Link p;
    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; // 任何时间最多打开一个文件
    IdxListType idxlist; // 索引表
    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(struct book),f);  //fread(buf,1,sizeof(struct book),f);
    while(!feof(f))
    {
        strcpy(buf,bookinfo.book_name);
        ExtractKeyWord(BookNo);
        InsIdxList(idxlist,BookNo);
        fread(&bookinfo,1,sizeof(struct book),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];    //词表(字符串)指针数组
      int last;    //词的数量
};

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

struct IdxListType      //索引表类型(有序表)
{
      IdxTermType item[MaxKeyNum+1];    //索引项数组类型
      int last;  //关键词的个数
};

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,int i,HString wd);
void InsertBook(IdxListType &idxlist, int i, int bno);
void InsIdxList(IdxListType &idxlist , int bno);
void PutText(FILE *f , IdxListType idxlist);
void algo43_main(void);

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

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

struct BookListType // 书目表类型(有序表)
{
      BookTermType item[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 not open!\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 open Book.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,ElemType e)
 { // 分配由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,Link h,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,Link h,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,Link s)
 { // 将指针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所指结点中数据元素的值
   return p->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
   return p->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(LinkList L,void(*visit)(ElemType))
 { // 依次对L的每个数据元素调用函数visit()
   Link p=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

//函数结果状态代码
#define TRUE       1
#define FALSE      0
#define OK         1
#define ERROR      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
---------------------------------------------------------------------------------------------
    看完代码我自己都怀疑当初是这么实现的,代码繁多。不过回想起来,一个个功能的按部就班的实现也就成了这个摸样。

Logo

快速构建 Web 应用程序

更多推荐