#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 "bookinfo.txt"
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 ;
}