struct nm
{
char title[100];
struct text *ln;
struct text *la;
int section;
int count;
struct nm next;
};
/*
存储未关闭存废讨论的结构,ln是分割线、section以前的内容,la是以后的内容。title为标题,section为章节编号,count为标题中的等号数。
*/
struct text
{
char *line;
struct text *next;
};
struct nm *fetchtitle()
{
/*
这个函数从存储存废讨论页面源码的结构中获取未关闭的讨论,储存到一个链表。为方便起见,这里假设文件"a.txt"存储着页面源码。每次循环从文件中读入一个字符,根据读入
的字符判断位置status,无需回溯。status的含义:
-1:位于页面大标题之前 -2:位于大标题左边的等号中 -3:位于大标题中间 -4:位于大标题右边的等号中 0:位于正文已关闭的存废讨论文本中 1:位于提删项目标题左边的等号中
2:位于提删项目标题中间,尚未读到 "[[" 3:位于提删标题中的内链里 4:已读完内链,尚未读到右边的等号 5:位于提删项目标题右边的等号中
6:读完提删标题,确定不是关注度的标题,正检查有无delh 7:未关闭存废讨论的正文部分
在读取存废讨论正文的时候,还需要注意分割线和section标签,其上、下内容应分开存储。
*/
int status=-1; //读取页面的状态
int nota=0;//关注度状态
int section=0;//分割线状态
int lf=0;//换行
const char *not="notability",*sec="<section",*del="{{delh|",*DEL="{{DELH|";//需要匹配的字符串
const int notl=strlen(not),secl=strlen(sec),dell=strlen(del);//它们的长度
int notc=0,secc=0,delc=0;//进行匹配时的位置
char title [500];//存储页面标题
int titlec=0;//读取标题的位置
struct nm *head=0,*temp=0,*pre=0;
struct text *temp1=0,*pre1=0,*temp2=0,*pre2=0;
char ch=0;//读入的字符
int leq=0,req=0;//用于检查等号是否匹配
int deq=0;//大标题中等号的个数
int bra=0;//匹配括号
char buff[10*1024]={0};//一行
int buffc;//行中的位置
int countsec=-2;//section number
int i;
FILE *f;
f=fopen("a.txt","r+");
while(!feof(f))
{
if(ch=='\n') lf=1;
else lf=0;
ch=fgetc(f);
switch(status)
{
case -1:
if(ch=='='&&lf)
{
status=-2;
leq++;
}
break;
case -2:
if(ch=='=')
{
leq++;
}
else status=-3;
break;
case -3:
if(ch=='=')
{
req=0;req++;
status=-4;
}
break;
case -4:
if(ch=='=')
{
req++;
}
else
{
countsec++;
if(leq!=req) return -1;//左右括号不匹配
deq=leq;
leq=req=0;
status=0;
}
break;
case 0:
if(ch=='='&&lf)
{
status=1;
leq=0;
leq++;
}
break;
case 1:
if(ch=='=')
{
leq++;
}
else {
status=2;
bra=0;
if(ch=='[') bra++;
}
break;
case 2:
switch(bra)
{
case 0:if(ch=='[') bra=1;
else bra=0;
break;
case 1:if(ch=='[') bra=0;
titlec=0;
status=3;
break;
}
if(notc==notl)
{
notc=0;
if(nota==0) nota=1;
else return -2;//关注度嵌套,神经病
}
else if(not[notc]==ch)
{
notc++;
}
else notc=0;//根据kmp算法,不存在回溯的可能性
if(ch=='=') {status=5;req=0;req++;}
break;
case 3:
if(!(ch==':'&&titlec==0))
{
if(ch!=']')
{
title[titlec]=ch;
titlec++;
title[titlec]=0;
}
else status=4;
}
break;
case 4:
if(ch=='=')
{
status=5;
req=0;
req++;
}
break;
case 5:
if(ch=='=')
{
req++;
}
else
{
countsec++;
if(leq!=req)
return -1;
if(nota==0)
{
status=6;
}
else if(nota==1)
{
nota=2;
status=0;
}
else
{
if(leq>=2+deq) status=6;
else
{
nota=0;
status=6;
}
}
}
break;
case 6:
if(ch!='\n'&&ch!=' ')
{
if(lf&&!delc)
{
if(ch!='{') {status=7;}
else
{
delc++;
}
}
else if(delc<dell)
{
if(ch!=del[delc]&&ch!=DEL[delc])
{
status=7;
}
else delc++;
}
else if(delc==dell)
{
status=0;
delc=0;
}
}
if(status==7)
{
if(!head)
{
temp=(struct nm*)malloc(sizeof(struct nm));
head=pre=temp;
temp->next=0;
}
else
{
pre=temp;
temp=(struct nm*)malloc(sizeof(struct nm));
temp->next=0;
pre->next=temp;
}
temp->section=countsec;
temp->count=leq;
strcpy(temp->title,title);
temp->la=0;
temp->ln=0;
buffc=0;
buff[buffc]=0;
section=0;
if(delc)
{
for(i=0;i<delc;i++)
{
buff[buffc]=del[i];
buffc++;
buff[buffc]=0;
}
delc=0;
}
buff[buffc]=ch;
buffc++;
buff[buffc]=0;
}
break;
case 7:
if(lf)
{
if(section)
{
if(!temp->la)
{
temp->la=(struct text *)malloc(sizeof(struct text));
pre2=temp2=temp->la;
temp2->next=0;
temp2->line=(char *)malloc(buffc+5);
strcpy(temp2->line,buff);
}
else
{
pre2=temp2;
temp2=(struct text *)malloc(sizeof(struct text));
temp2->next=0;
pre2->next=temp2;
temp2->line=(char *)malloc(buffc+5);
strcpy(temp2->line,buff);
}
}
else
{
if(!temp->ln)
{
temp->ln=(struct text *)malloc(sizeof(struct text));
pre1=temp1=temp->ln;
temp1->next=0;
temp1->line=(char *)malloc(buffc+5);
strcpy(temp1->line,buff);
}
else
{
pre1=temp1;
temp1=(struct text *)malloc(sizeof(struct text));
temp1->next=0;
pre1->next=temp1;
temp1->line=(char *)malloc(buffc+5);
strcpy(temp1->line,buff);
}
}
buffc=0;
buff[buffc]=0;
}
if(ch!='='||!lf)
{
if(!section)
{
if(lf&&ch=='-') section=1;
else if(lf&&!secc&&ch=='<')
{
secc++;
}
else if(secc<secl)
{
if(ch==sec[secc])
{
secc++;
}
else secc=0;
}
else if(secc==secl)
{
section=1;
secc=0;
}
}
buff[buffc]=ch;
buffc++;
buff[buffc]=0;
}
else
{
leq=0;
leq++;
status=1;
}
break;
}
}
fclose(f);
if(buffc>1) //如果没有读完一行,就没东西了,需要把buff里面的内容写入。
{
buffc--; //在这个例子中,存储存废讨论源码的介质是文件,末尾有一个结束符需要删去。
buff[buffc]=0;
if(section)
{
if(!temp->la)
{
temp->la=(struct text *)malloc(sizeof(struct text));
pre2=temp2=temp->la;
temp2->next=0;
temp2->line=(char *)malloc(buffc+5);
strcpy(temp2->line,buff);
}
else
{
pre2=temp2;
temp2=(struct text *)malloc(sizeof(struct text));
temp2->next=0;
pre2->next=temp2;
temp2->line=(char *)malloc(buffc+5);
strcpy(temp2->line,buff);
}
}
else
{
if(!temp->ln)
{
temp->ln=(struct text *)malloc(sizeof(struct text));
pre1=temp1=temp->ln;
temp1->next=0;
temp1->line=(char *)malloc(buffc+5);
strcpy(temp1->line,buff);
}
else
{
pre1=temp1;
temp1=(struct text *)malloc(sizeof(struct text));
temp1->next=0;
pre1->next=temp1;
temp1->line=(char *)malloc(buffc+5);
strcpy(temp1->line,buff);
}
}
buffc=0;
buff[buffc]=0;
}
return head;
}
int closeafd(struct nm *afdlist,int n,int action,char *target,char *comment,struct nm **newhead,int notability)
{
int flag=0,res;
struct nm *temp,*pre;
struct text *tx,*txp;
*newhead=afdlist;
if(!afdlist) return -1;
pre=temp=afdlist;
flag=0;
while(temp)
{
if(temp->section>n) return -2;
if(temp->section==n)
{
flag=1;
break;
}
pre=temp;
temp=temp->next;
}
if(!flag) return -2;
res=check(temp->title);
if(res==1) return -3;
if(action==1)
{
res=check(target);
if(res==1) return -4;
}
switch(action)
{
case 0:removetemp(temp->title,1);
break;
case 1:redirect(temp->title,target,notability);
break;
case 2:removetemp(temp->title,0);
break;
case 3:removetemp(temp->title,0);
break;
}
addtalk(temp->title,action);
closingdebate(temp,action,comment);
if(temp==afdlist) *newhead=temp->next;
else pre->next=temp->next;
tx=temp->ln;
while(tx)
{
txp=tx;
tx=tx->next;
free(txp);
}
tx=temp->la;
while(tx)
{
txp=tx;
tx=tx->next;
free(txp);
}
free(temp);
return 0;
}