-
优点:可以自定义显示行数,使交互界面更加美观
-
缺点:随着设定行数减小,出错的可能性增大(建议30以上),是不完美版本
#include<stdio.h>
#include<string.h>
#include<malloc.h>
#include<stdlib.h>
#include<conio.h>
#define OK 1
#define ERROR -1
#define OVERFLOW -2
#define MAX 1000
typedef int Status;
//-----串的堆式顺序存储结构-----
typedef struct{
char *ch;
int length;
}HString;
//初始化
Status InitString(HString &s){
s.ch=NULL;
s.length;
return OK;
}
//判空
Status StrEmpty(HString &T){
if(T.length==0&&T.ch==NULL) return OK;
else return ERROR;
}
//串赋值
Status StrAssign(HString &T,char *str){
int i,j;
InitString(T);
i=strlen(str);
if(!i) return ERROR;
else{
T.ch=(char*)malloc(i*sizeof(char));
if(!T.ch)
exit(OVERFLOW);
for(j=0;j<i;j++){
T.ch[j]=str[j];
T.length=i;
}
}
}
//清空串
Status ClearStr(HString &s){
if(s.ch){
free(s.ch);
s.ch=NULL;
}
s.length=0;
return OK;
}
//打印串
void StrPrint(HString &s){
int i;
if(StrEmpty(s)==OK)
printf("%d为空串!",&s);
for(i=0;i<s.length;i++){
printf("%c",s.ch[i]);
printf(" ");
}
}
//BF算法实现串匹配
Status BF(HString S,HString T,int pos){
int j=0,i;
i=pos-1;
while(i<S.length&&j<T.length){
if(S.ch[i]==T.ch[j]){
i++;
j++;
}
else{
i=i-j+1;
j=0;
}
}
if(j>=T.length){
return i-T.length; //此处如果模式串在1位,则i-T.length=0,返回值易冲突,所以ERROR定义不能为0,应为负数
} //(i-T.length+1)=temp+1表示模式串在主串中的起始位置
else
return ERROR;
}
//显示串匹配成功的信息的功能函数
Status SucceedDisplay(HString S,HString T,int temp,int pos,int Lnum){
int count=0,count1=0,count2=0,e=0,numone=0,numtwo=0,num3=0,x=0,i=0,j=0,r=0,m=0,n=0,o=0,loc=0,p=0,q=0,u=0,v=0,w=0,y=0,flag=0,num=0;
printf("匹配成功!\n");
count=S.length/Lnum;
e=temp; //第一次产生的空块数
loc=temp+1; //记录模式串出现的起始位置
//主串主体输出
while(count>0){
if(count==S.length/Lnum) printf("主串:*********\n");
if(count==S.length/Lnum) printf("模式串:*******\n");
count--; //计数器
numone++;
for(i=(numone-1)*Lnum;i<numone*Lnum;i++){
printf("%c",S.ch[i]); //-----------------------输出主串
printf(" ");
}
printf("\n");
if(n==333){
pos=x+1+T.length; //当前模式串起始位+T.length=pos(下一次开始匹配位置)
temp=BF(S,T,pos); //上一次的temp=BF(S,T,pos)执行了,所以补一次更新temp值再进入下一轮模式串生成循环
e=temp-x-T.length; //新的temp-上一次的temp-T.length=“新产生的空块数”
}
if(n==666){
w=e-u; //w表示“待输出剩余空块数”
//空块数规避
while(w>=Lnum){ //待输出空块数w在新一行又超过了Lnum,
num3++; //计数器,记录输出剩余空块数输出行数
printf("\n");
if(count>0&&w>=Lnum){
w=w-Lnum*num3;
count--; //计数器
numone++;
for(i=(numone-1)*Lnum;i<numone*Lnum;i++){
printf("%c",S.ch[i]); //-----------------------输出主串
printf(" ");
}
printf("\n");
}
}
if(w<Lnum){ //输出不足Lnum的“输出空块数”或“剩余待输出空块数”
for(i=0;i<w;i++){
printf(" "); //在当轮主串下方,生成上一轮处在换行处的空块数的后半部分
}
}
v=w+T.length; //换行处的空块数的后部分(小于Lnum时的w)+T.length,v值还会反过来影响下一轮模式串生成循环
//模式串规避
if(v<Lnum){
for(i=0;i<T.length;i++){
printf("%c",T.ch[i]);
printf(" ");
}
temp=BF(S,T,pos); //上一次的temp=BF(S,T,pos)执行了,所以补一次更新temp值再进入下一轮模式串生成循环
e=temp-x-T.length; //新的temp-上一次的temp-T.length=“新产生的空块数”
}
else{ //“剩余待输出空块数+T.length”>Lnum
for(i=0;i<w;i++){
printf(" ");
}
y=T.length-(T.length-Lnum+w); //待输出模式串前部分
for(i=0;i<y;i++){
printf("%c",T.ch[i]);
printf(" ");
}
if(count>0){
count--; //计数器
numone++;
for(i=(numone-1)*Lnum;i<numone*Lnum;i++){
printf("%c",S.ch[i]); //输出主串
printf(" ");
}
printf("\n");
}
if(count>0){
for(i=0;i<T.length-(Lnum-w);i++){ //待输出模式串后部分
printf(" ");
}
temp=BF(S,T,pos); //上一次的temp=BF(S,T,pos)执行了,所以补一次更新temp值再进入下一轮模式串生成循环
e=temp-x-T.length; //新的temp-上一次的temp-T.length=“新产生的空块数”
}
}//else if(v>=Lnum)
}//if(n==666)
if(n==999){
o=T.length-m; //o为上一轮模式串后部分长度,o值还会反过来影响下一轮模式串生成循环
for(i=0;i<o;i++){
printf("%c",T.ch[i]); //在当轮主串下方,生成上一轮处在换行处的模式串的后半部分
printf(" ");
}
temp=BF(S,T,pos); //上一次的temp=BF(S,T,pos)执行了,所以补一次更新temp值再进入下一轮模式串生成循环
e=temp-x-T.length; //新的temp-上一次的temp-T.length=“新产生的空块数”
}
//模式串主体输出
if(temp!=ERROR){
n=0; //重置n的值,供下一次使用
if(e>=Lnum){
while(e>=Lnum){ //e>Lnum,情况一
printf("\n");
count--; //计数器
numone++;
for(i=(numone-1)*Lnum;i<numone*Lnum;i++){
printf("%c",S.ch[i]); //-----------------------输出主串
printf(" ");
}
printf("\n");
e=e-50;
if(e<Lnum){
for(i=0;i<e;i++){
printf(" ");
}
}
}
}
else{
while(temp!=ERROR){
//模式串单行输出
if(e+T.length<Lnum){ //预测输出后长度并判断,在此之前空格和模式串没有输出过
count1=e+T.length+v+o; //特别记录进入这里的空块数和模式串长度的和
v=0;o=0; //重置v,o的值,下一次使用
while(count1<Lnum&&flag==0&&temp!=ERROR){//e<Lnum且前轮(e+T.length)+下轮空块数与模式串长度(e+T.length)<Lnum,情况二
x=temp; //暂存旧的temp的值,下一次使用
for(i=0;i<e;i++){
printf(" "); //产生空块
}
StrPrint(T);
numtwo++; //记录循环次数
pos=temp+1+T.length; //当前模式串起始位+T.length=pos(下一次开始匹配位置)
//产生新的temp
temp=BF(S,T,pos);
e=temp-x-T.length; //新的temp-上一次的temp-T.length=“新产生的空块数”
count2=count1+e; //累计'前轮'输出后当行的(空块数和模式串长度)的总和+下一轮的空块数
count1=count1+e+T.length;//累计'下一轮'输出后当行的(空块数和模式串长度)的总和
if(count2>=Lnum||count1>=Lnum&&temp!=ERROR){
if(count1=Lnum) num=3;
if(count2>Lnum) num=2;
else num=1;
flag=1;
}
}
flag=0; //重置flag,保证下次循环
}
switch(num){
case 3:
if(temp!=ERROR){ //累计'前轮'输出后当行的(空块数和模式串长度)的总和=Lnum,情况五
for(i=0;i<e;i++){
printf(" ");
}
for(i=0;i<T.length;i++){
printf("%c",T.ch[i]);
}
pos=temp+1+T.length; //当前模式串起始位+T.length=pos(下一次开始匹配位置)
numtwo++; //记录循环次数
printf("\n");
n=333;
}
break;
case 2:
if(temp!=ERROR){//e<Lnum且前轮(e+T.length)+下轮空块数e>Lnum,情况三
u=Lnum-(count2-e); //"当前行应输出的空块数"=Lnum-上一轮的(空块数和模式串长度)的总和
for(i=0;i<u;i++){
printf(" ");
}
pos=temp+1+T.length; //当前模式串起始位+T.length=pos(下一次开始匹配位置)
numtwo++; //记录循环次数
printf("\n");
n=666; //媒介开关,启动在下一模式串行输出当轮剩余空块的后部分
}
break;
case 1:
if(temp!=ERROR){//e<Lnum且前轮(e+T.length)+下轮空块数与模式串长度(e+T.length)>Lnum,情况四
for(i=0;i<e;i++){
printf(" "); //产生空块
}
m=Lnum-count2;
if(m==0) printf("\n");
else{
for(i=0;i<m;i++){
printf("%c",T.ch[i]); //输出处在换行处模式串的前部分
}
printf("\n");
}
pos=temp+1+T.length; //当前模式串起始位+T.length=pos(下一次开始匹配位置)
numtwo++; //记录循环次数
n=999; //媒介开关,启动在下一模式串行输出模式串的后部分
}
break;
}
x=temp; //暂存旧的temp的值,下一次使用
temp=ERROR; //跳出模式串生成循环去主串生成循环
}//while(temp!=ERROR)
}//else
}//if(temp!=ERROR)
}//while(count>0)
printf("\n模式串在主串中的起始位置:第%d位",loc); //temp+1表示位置,loc=temp+1
printf("\n模式串在主串中的出现次数:共%d次",numtwo);
if(temp==ERROR){
printf("\n匹配结束!\n");
return 0;
}
}
//显示串匹配失败的信息的功能函数
Status fail(){
printf("匹配失败!\n");
printf("模式串在主串中不存在!\n");
return 0;
}
void main(){
HString S,T;
int temp,pos,Lnum;
int flag=1,choice=1,q=0,i=0;
InitString(S);InitString(T);
printf("\n*******************本程序通过串的BF算法模式匹配,实现查询功能********************\n\n");
printf("请输入存入主串的字符串:");
char str1[MAX];gets(str1);
StrAssign(S,str1);
printf("请输入存入模式串的字符串:");
char str2[MAX];gets(str2);
StrAssign(T,str2);
while(choice){
printf("请输入起始匹配的位置(第一位为1):");
scanf("%d",&pos);
if(pos==0||pos>S.length)
printf("输入不合法!");
else
choice=0;
}
printf("请输入每行显示字数:");
scanf("%d",&Lnum);
while(flag){
printf("\n匹配结果:");
temp=BF(S,T,pos);
if(temp==ERROR){
flag=fail();
}
else{
flag=SucceedDisplay(S,T,temp,pos,Lnum);
}
getch();
printf("\n程序已退出!\n");
}
ClearStr(S);
ClearStr(T);
}