#include<stdio.h>
#include<iostream.h>
#include"HString.cpp"




#define MaxLecNum 500 //假设只对500篇论文建关键词索引表
#define MaxKeyNum 2500   //索引表的最大容量
#define MaxLineLen 300   //一行的最大长度
#define MaxWordNum 50    //关键词的最大长度
#define MaxWordLen 30    //每行(即一篇论文)最多关键词数
#define IN 1  //在单词内
#define OUT 0  //在单词外


typedef struct
{
    char item[MaxWordNum][MaxWordLen];  //关键词串的数组
    int last;     //词表的长度
}WordListType;   //词表类型(顺序表)

typedef int ElemType;  //定义链表的数据元素为整形

typedef int Status;


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

typedef struct
{
    HString key;  //关键词
    LinkList bnolist;   //存放论文号索引的链表(本题中行号即为论文号,如第一行就是第一篇论文)
}IdxTermType;    //索引项类型

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

int WordNum;      //每篇论文关键词数目
char line[MaxLineLen];
char Word[MaxWordNum][MaxWordLen];

WordListType wdlist;   //词表
IdxListType idxlist;    //索引表

void InitIdxList(IdxListType &idxlist);  //初始化操作,置索引表idxlist为空表

void ExtractKeyWord();    //调用ExtraLineWord提取关键词到词表,并把论文号存入bno

void ExtraLineWord();    //每行提取关键词到词表wlist;

Status InsIdexList(IdxListType *idxlist,ElemType bno);  //将论文号为bno的论文关键词插入索引表idxlist

void PutText(FILE *fp,IdxListType idxlist); //将生成的索引表idxlist输出

void GetWord(int i,HString *wd);  //用wd返回词表wlist中的第i个关键词

Status Locate(IdxListType idxlist,HString wd,int b);  //在索引表idxlist中查询是否存在与wd相等的关键词,若存在,返回其在索引表中的们置,且b取值为TRUE,否则返回插入位置,且b为FALSE

void InsertNewKey(IdxListType *idxlist,int i,HString wd); //在索引表idxlist的第i项上插入新关键词wd,并初始话论文号索引的链表为空表

Status InsertBook(IdxListType *idxlist,int i,int bno);  //在索引表idxlist的第i项插入论文号为bno的索引

Status InsIdxList(IdxListType &idxlist,int bno);

void InitList(LinkList &h)
{
    h=(LinkList)malloc(sizeof(LNode));
    if(!h)exit(0);
    h->next=NULL;
}

Status MakeNode(LNode &p,int bno)
{

    
    p.data=bno;
    p.next=NULL;
    return OK;
}

Status Append(LinkList *h,LNode p)
{
    LNode *q,*p1;
    q=(*h)->next;
    p1=(LNode*)malloc(sizeof(LNode));
    if(!p1)return ERROR;
    p1->data=p.data;
    p1->next;
    if(q==NULL)
    {
        (*h)->next=p1;
        return OK;
    }
    while(q->next){q=q->next;}
    q->next=p1;
    return OK;
}

Status ListInsert(WordListType &wh,int len,char wd[])
{
    int i,j;
    char *p;
    p=wd;
    for(i=0;*p;i++,*p++);
    j=i+1;
    for(i=0;i<j;i++)
        wh.item[len][i]=wd[i];

    wh.last++;
    return OK;
}

Status ListLength(WordListType&wh)
{
    return wh.last;
}

void main()
{
    int LecNo=0;
    FILE *fp1,*fp2;
    if((fp1=fopen("KeyWord.txt","r"))==NULL)
    {
        cout<<"文件打失败"<<endl;
        exit(0);
    }
    if((fp2=fopen("LecIdx.txt","w"))==NULL)exit(0);
    InitIdxList(idxlist);   //初始化索引表idxlist为空表
    while(LecNo<6)
    {
        cout<<LecNo<<"、";
        fgets(line,MaxLineLen,fp1);  //从文件读入一行
        cout<<line<<endl;
        ExtractKeyWord();   //提取关键词到词表,并把论文号存入bno
        LecNo++;   //论文号加一,下一个循环读下一行
        InsIdxList(idxlist,LecNo);   //将论文号为LecNo的关键词插入索引表
    }
    PutText(fp2,idxlist);
}

void InitIdxList(IdxListType &idxlist)
{
    idxlist.last=0;
}

void InitWordList(WordListType &wh)
{
    wh.last=0;
}

void ExtractKeyWord()
{
    int i;
    ExtraLineWord();
    InitWordList(wdlist);
    cout<<"词表:"<<endl;
    for(i=0;i<=WordNum;i++)
    {
        ListInsert(wdlist,ListLength(wdlist),Word[i]);
        cout<<wdlist.item[i]<<"  ";
    }
    cout<<endl;
}

void ExtraLineWord()
{
    char *lp;
    int state=OUT,WordIndex;
    char c;
    lp=line;

    WordNum=-1;
    WordIndex=0;
    while(*lp!='\0')
    {
        c=*lp;
        if(c>='A'&&c<='Z'||c>='a'&&c<='z')
        {
            if(state==OUT)
            {
                state=IN;
                ++WordNum;
                WordIndex=0;
            }
            Word[WordNum][WordIndex]=c;
            ++WordIndex;
        }
        else
        {
            if(state==IN)
            {
                Word[WordNum][WordIndex]='\0';
            }
            state=OUT;
        }
        lp++;
    }
}



Status InsIdxList(IdxListType &idxlist,int bno)
{
    int i,j,d;
    d=FALSE;
    HString wd;
    wd.ch=NULL;
    for(i=0;i<wdlist.last;i++)
    {
        GetWord(i,&wd);
        j=Locate(idxlist,wd,d);
        if(!d)InsertNewKey(&idxlist,j,wd); //插入新的索引项
        if(!InsertBook(&idxlist,j,bno)) return ERROR;  //插入论文号索引
    }
    return OK;
}

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

}

int Locate(IdxListType idxlist,HString wd,int b)
{
    int i,m;
    if(!idxlist.last)
    {
        b=FALSE;
        return 0;
    }
    for(i=idxlist.last-1;m=StrCompare(idxlist.item[i].key,wd),m>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;
}

Status InsertBook(IdxListType *idxlist,int i,int bno)
{
    LNode *p;
    p=(LinkList)malloc(sizeof(LNode));
    if(!p)return ERROR;
    if(!MakeNode(*p,bno))return ERROR; //分配失败
    Append(&idxlist->item[i].bnolist,*p); //插入新的论文号
    return OK;
}

void PutText(FILE *fp2,IdxListType idxlist)
{
    int i;
    LNode *p;
    for(i=0;i<idxlist.last;i++)
    {
        cout<<idxlist.item[i].key.ch<<endl;
        fprintf(fp2,"%s",idxlist.item[i].key.ch);
        p=idxlist.item[i].bnolist->next;
        while(p)
        {
            fprintf(fp2,"%d\t",p->data);
            p=p->next;
        }
        fprintf(fp2,"\n");
    }
}