第四章(5).建立词索引表

来源:互联网 发布:python是用来做什么的 编辑:程序博客网 时间:2024/06/13 01:28

#include < stdio.h >
#include < stdlib.h >
#include < string.h >

#define  TRUE   1
#define  FALSE   0
#define  OK    1
#define  ERROR   0
#define  OVERFLOW  -1

#define  MaxBookNum  1000    //假设只对1000本书建立索引表
#define  MaxKeyNum  2500    //索引表的最大容量
#define  MaxLineLen  500     //书目串的最大长度
#define  MaxWordNum  10     //词表的最大容量
typedef  int  ElemType ; //定义链表数据元素类型为整型(书号类型)

typedef struct
{
 char *ch;
 int length;
}HString;

typedef struct LNode
{
 ElemType data;
 struct LNode *next;
}LNode,*LinkList;

void InitList(LinkList *L) ;
void PrintList(LinkList L) ;
ElemType GetElem(LinkList L, int i, ElemType *e) ;
int LocateElem(LinkList L,ElemType e) ;
void DestroyList(LinkList L) ;

void InitString(HString *T) ;
void StrAssign( HString *T, char *cha) ;
void StrCopy( HString *T , HString S ) ;
void StrPrint(HString T, FILE *fp) ;
void ClearString(HString *T) ;
int StrCompare(HString S,HString T) ;

//--------------------------------------------------------//

typedef struct {
 char item[ 20 ][ 20 ] ; //字符串的数组
 int  last ;    //词表的长度
} WordListType ;    //词表类型(顺序表)

typedef struct {
 HString  key ;   //关键词
 LinkList bnolist ;  //存放书号索引的链表
} IdxTermType ;     //索引项类型

typedef struct {
 IdxTermType item[ MaxKeyNum + 1 ] ;
 int   last ;
} IdxListType ;     //索引表类型(有序表)

//主要变量
char buf[ 256 ] ;   //书目串缓冲区
WordListType wdlist ;   //词表
HString oftenwords[ 7 ] ;  //常用词表


//---------------------Basic Operation---------------------//

void InitIdxList( IdxListType *idxlist ) ;    //初始化,置索引表idxlist为空表,且在idxlist.item[0]设一空串
void GetLine( FILE *fp ) ;        //从文件中读入一个书目信息到书目串缓冲区buf
void ExtractKeyWord( ElemType *bno ) ;     //从书目串缓冲区提取书名关键词到词表wdlist,书号存入bno
int InsIdxList( IdxListType *idxlist , ElemType bno ) ; //将书号为bno的书名关键词按词典顺序插入索引表idxlist
void PutText( FILE *fp , IdxListType idxlist ) ;  //将生成的索引表idxlist输入到文件中

//---------------------For Insert--------------------------//

void GetWord( int i , HString *wd ) ;     //用wd返回词表wdlist中第i个关键词
int Locate( IdxListType idxlist , HString wd , int *b );//在索引表idxlist中插叙是否存在与wd相等关键词.若存在,则返回其在索引表中的位置,且b取TREUE;否则返回插入位置,且b取值FALSE.
void InsertNewKey( IdxListType *idxlist , int i , HString wd ) ;//在索引表idxlist的第i项上插入新关键词wd,并初始化书号索引的链表为空表
int InsertBook( IdxListType *idxlist , int i , int bno ) ; //在索引表idxlist的第i项中插入书号为bno的索引

void OftenWords( ) ;
int IsOftWords( char *temp ) ;
int MakeNode( LinkList *p , ElemType bno ) ;
void Appand( LinkList bnolist , LinkList p ) ;

//---------------------For Query---------------------------//

void ExtractyWord( int BookNum[ ] , char words[ ] ) ;
void ExtractyName( char name[ ] , WordListType *namewords ) ;
void FindtheSame( int BookNum[ ] , int Num[ ] ) ;
void Query( FILE *fp , char *name ) ;     //从关键词索引表中查找是否包含某本书

//-------------------------------------------------------//

#include "head.h"

void InitIdxList( IdxListType *idxlist )
{
 (*idxlist).last = 1 ;
 InitString( &(*idxlist).item[ 0 ].key ) ;

 (*idxlist).item[ 0 ].bnolist = ( LinkList )malloc( sizeof( LNode ) ) ;
 (*idxlist).item[ 0 ].bnolist->next = NULL ;
}

void GetLine( FILE *fp )
{
 buf[ 256 ] = ' ' ;
 fgets( buf , 256 , fp ) ;
}

void OftenWords( )      //构造常用词表
{
 int i ;
 for( i = 0 ; i < 7 ; ++ i )
 {
  InitString( (oftenwords+i) ) ;
 }
 StrAssign( &(oftenwords[ 0 ]) , "an" ) ;
 StrAssign( &(oftenwords[ 1 ]) , "a" ) ;
 StrAssign( &(oftenwords[ 2 ]) , "to" ) ;
 StrAssign( &(oftenwords[ 3 ]) , "of" ) ;
 StrAssign( &(oftenwords[ 4 ]) , "the" ) ;
 StrAssign( &(oftenwords[ 5 ]) , "The" ) ;
 StrAssign( &(oftenwords[ 6 ]) , "and" ) ;
 
}

int IsOftWords( char *temp )   //判断是否为常用词表
{
 int i ;
 for( i = 0 ; i < 7 ; ++ i )
 {
  if( !strcmp( oftenwords[ i ].ch , temp ) )
   return OK ;
 }
 return ERROR ;
}

void ExtractKeyWord( ElemType *bno )
{
 char temp[ 20 ] ;
 int j , i = 0 ;
 
 wdlist.last = 0 ;
 while( buf[ i ] != '\0' && buf[ i ] != '\n' && buf[ i ] != ' ' )
 {
  j = 0 ;
  while( buf[ i ] != ' ' && buf[ i ] != '\0' && buf[ i ] != '\n' )
  {
   temp[ j ] = buf [ i ] ;
   ++ i ;
   ++ j ;
  }
  temp[ j ] = '\0' ;
  if( 0 == wdlist.last  )
  {
   *bno = atoi( temp ) ;
   wdlist.last ++ ;
  } 
  else
  {
   if( !IsOftWords( temp ) )
   {
    strcpy( wdlist.item[ wdlist.last - 1 ] , temp ) ;
    wdlist.last++ ;
   }
  }
  ++ i ;
 }
 wdlist.last-- ;
}

int InsIdxList( IdxListType *idxlist , ElemType bno )
{
 int i , j , b ;
 HString wd ;
 for( i = 0 ; i < wdlist.last ; ++ i )
 {
  GetWord( i , &wd ) ;
  j = Locate( *idxlist , wd , &b ) ;
  if( !b )
   InsertNewKey( idxlist , j , wd ) ;  //插入新的索引项
  if( !InsertBook( idxlist , j , bno ) )  //插入书号索引
   return OVERFLOW ;
 }
 return OK ;
}

void PutText( FILE *fp , IdxListType idxlist )
{
 int i ;
 LinkList p ;
 for( i = 1 ; i < idxlist.last ; ++ i )   //0号空置
 {
  StrPrint( idxlist.item[ i ].key , fp ) ;
  p = idxlist.item[ i ].bnolist->next ;
  while( p )
  {
   printf( "%d " , p->data ) ;
   fprintf( fp , "%d " , p->data ) ;
   p = p->next ;
  }
  printf( "\n" ) ;
  fprintf( fp , "%c " , '\n' ) ;
 }
}

//------------------------For Insert------------------------------//

void GetWord( int i , HString *wd )
{
 char *p = *( wdlist.item + i ) ;      //取词表中第i个字符串
 StrAssign( wd , p ) ;         //生成关键字字符串
}

int Locate( IdxListType idxlist , HString wd , int *b )
{
 int i , m ;
 for( i = idxlist.last - 1 ; ( m = StrCompare( idxlist.item[ i ].key , wd ) ) > 0 ; -- i ) ;
 if( m == 0 )   //找到
 {
  *b = TRUE ;
  return i ;
 }
 else
 {
  *b = FALSE ;
  return i + 1 ;  //返回插入的位置
 }
}

void InsertNewKey( IdxListType *idxlist , int i , HString wd )
{
 int j ;
 for( j = (*idxlist).last - 1 ; j >= i ; -- j )  //后移索引项
  (*idxlist).item[ j + 1 ] = (*idxlist).item[ j ] ;
 //插入新的索引项
 StrCopy( &(*idxlist).item[ i ].key , wd ) ;   //串赋值
 InitList( &(*idxlist).item[ i ].bnolist ) ;   //初始化书号索引表为空表
 ++ (*idxlist).last ;
}

int MakeNode( LinkList *p , ElemType bno )
{
 *p = ( LinkList )malloc( sizeof( LNode ) ) ;
 if( !( *p ) )
  return ERROR ;
 ( *p )->data = bno ;
 return OK ;
}

void Appand( LinkList bnolist , LinkList p )
{
 p->next = bnolist->next ;
 bnolist->next = p ;
}

int InsertBook( IdxListType *idxlist , int i , int bno )
{
 LinkList p ;
 if( !MakeNode( &p , bno ) )       
  return ERROR ;         //分配失败
 Appand( (*idxlist).item[ i ].bnolist , p ) ;  //插入新的书号索引
 return OK ;
}

//--------------------------For Query-----------------------------------//

void ExtractyWord( int BookNum[ ] , char words[ ] )
{
 int i = 0 , j = 0 , k = 0 ;
 char temp[ 5 ] ;
 while( buf[ i ] != ':' )      //key word
 {
  words[ i ] = buf[ i ] ;
  ++ i ;
 }
 words[ i ] = '\0' ;
 
 while( buf[ i ] != '\n' )
 {
  j = 0 ;
  i++ ;
  while( buf[ i ] != ' ' && buf[ i ] != '\n' )
  {
   temp[ j ] = buf[ i ] ;
   ++ j ; ++ i ;
  }
  temp[ j ] = '\0' ;
  BookNum[ k ] = atoi( temp ) ;
  ++ k ;
 }
}

void ExtractyName( char name[ ] , WordListType *namewords )
{
 int i = 0 , j = 0 ;
 (*namewords).last = 0 ;
 while( name[ i ] != '\0' )
 { 
  j = 0 ;
  while( name[ i ] != ' ' && name[ i ] != '\0' )
  {
   (*namewords).item[ (*namewords).last ][ j ] = name[ i ] ;
   ++ i ; ++ j ;
  }
  (*namewords).item[ (*namewords).last ][ j ] = '\0' ;
  ++ (*namewords).last ;
  if( name[ i ] == '\0' )
   break ;
  else
   ++ i ;
 }
}

void FindtheSame( int BookNum[ ] , int Num[ ] )
{
 int k , j = 0 ;
 for( k = 0 ; k < 10 ; ++ k )  //也可以设法把BookNum[]的长度传近来
 {
  if( BookNum[ k ] )
  {
   j = 0 ;
   while( Num[ j ] && j < 10 )
   {
    if( BookNum[ k ] == Num[ j ] )
     break ;
    ++ j ;
   }
   if( !Num[ j ] || j >= 10 )
    BookNum[ k ] = 0 ;
  }
 }
}

void Query( FILE *fp , char *name )
{
 char words[ 20 ] ;
 WordListType namewords ;
 int i , times = 0 , j = 0 ;
 int BookNum[ 10 ] = { 0 }, Num[ 10 ] = { 0 };

 ExtractyName( name , &namewords ) ;
 while( !feof( fp ) )
 {
  j = 0 ;
  GetLine( fp ) ;
  ExtractyWord( Num , words ) ;

  for( i = 0 ; i < namewords.last ; ++ i )
  {
   if( !strcmp( words , namewords.item[ i ] ) )
   { //存储书号
    if( 0 == times )   //第一次,保留所有书号
    {
     while( Num[ j ] )
     {
      BookNum[ j ] = Num[ j ] ;
      ++ j ;
     }
     times++ ;
    }
    else      //后续次,保留相同的书号,不同的书号则置为0
    {
     FindtheSame( BookNum , Num ) ;
    }
   }
  } // for
 } // while
 //判断并锁定书号
 j = 0 ;
 while( !BookNum[ j ] && j < 10 )
  j ++ ;
 if( j >= 10 )
  printf( "Can't find that book!" ) ;
 else
  printf( "Oh, Find the book you want! The Number is :%d\n" , BookNum[ j ] ) ;
}

//----------------------------------------------------------------//

int main( )
{
 FILE *fi , *fo , *fp ;
 IdxListType idxlist ;
 ElemType bno ;

 if( !( fi = fopen( "书目文件.txt" , "r" ) ) || !( fo = fopen( "关键词索引文件.txt" , "w") ) )
 { //注意:“书目文件”的最后一条字符串后面要多打一个空格!
  printf( "Cannot Open the file!\n" ) ;
  exit( 0 ) ;
 }
 OftenWords( ) ;
 InitIdxList( &idxlist ) ;
 while( !feof( fi ) )
 {
  GetLine( fi ) ;
  ExtractKeyWord( &bno ) ;
  InsIdxList( &idxlist , bno ) ;
 }
 PutText( fo , idxlist ) ;

 fclose( fi ) ;
 fclose( fo ) ;


 if( !( fp = fopen( "关键词索引文件.txt" , "r") ) )
 {
  printf( "Cannot Open the file!\n" ) ;
  exit( 0 ) ;
 }
 Query( fp , "Numerical Analysis" ) ;
 fclose( fp ) ;

 return 0 ;
}

 
0 0