没看明白 不知道输入输出
程序代码:
/*stophin*/ #include <stdio.h> #include <stdlib.h> #include <conio.h> #include <iostream> using namespace std; #define M 100 //最大输入字符元素个数 #define N 80 //元素表中最大元素个数 #define NL 0 //无任何元素属性 #define CR 1 //关键字属性 #define ST 2 //字符串属性 #define BR 3 //括号属性 #define ER 4 //错误的属性 //用于创建表达式元素链表 struct exp { exp():pre(NULL),signum(0),attrib(NL),elenum(0),quonum(0),next(NULL) //构造函数 { sig[0]='\0'; } struct exp *pre; //前驱结点 char sig[N]; //结点数据 int signum; //结点数据个数 int attrib; //结点属性标识 int elenum; //标记个数,可用于标记括号对数 int quonum; //标记个数,可用于标记引号对数 struct exp *next; //后继结点 void insig(char c,int at=ST) //向结点数据写入字符,并做一些标记 { if (signum>=N) //如果写满了,则不再写入,并标记属性错误 { attrib=ER; return; } if (at==BR) //如果是写入括号内的内容,则统计括号个数 { if (c=='(') elenum++; else if (c==')') elenum--; } if (at==ST) //如果是写入字符,则标记是否有括号和引号,有则置1 { if (!elenum&&c=='(') elenum=1; else if (elenum&&c==')') elenum=0; if (!quonum&&c=='\"') quonum=1; else if (quonum&&c=='\"') quonum=0; } sig[signum++]=c; //写入数据 sig[signum]='\0'; attrib=at; //设置写入数据的属性 return; } }; typedef struct exp E; void freelink(E **ph) //释放结点 { E * p = *ph; E * q ; while(NULL != p ) { q = p->next ; free(p); p = q; } *ph=NULL; return; } void viewlink(E *ph) //打印节点 { while(ph!=NULL) { cout<<ph->sig<<"■"; ph=ph->next; } cout<<endl; return; } E *creat(char *expr) //创建文字元素 { E *head=NULL,*pre=NULL,*last=NULL,*old=NULL; int i=0; int l=strlen(expr); //获取文字元素长度 if (expr[i]!='\0') { head=new E; //创建头结点 if (!head) { printf("0293 创建字串链表头结点时内存空间分配失败!\n"); return NULL; } old=last=head; while (i<l) { if (expr[i]==' ') //略去前面的空格 { i++; continue; } pre=new E; if (!pre) { printf("0294 为 \"%c\" 创建字串链表时内存空间分配失败!\n",expr[i]); pre=old; } //核心-------------------------------------------------------------- if (expr[i]=='(') //如果是开括号 { do //则一直写入,并统计括号匹配情况 { if (expr[i]!=' ') pre->insig(expr[i],BR); i++; //直到括号完全匹配,或者遇到关键字停止,同样关键字要满足一些条件 //该条件与下面的"其余情况"中的if条件相差无几,详见下面的说明 if (!pre->elenum||(expr[i]=='i')&&(i<=l-1&&expr[i+1]=='n')&&(i&&(expr[i-1]==' '||expr[i-1]==')'||expr[i-1]=='\"'))&&(i<=l-2&&expr[i+2]==' '||expr[i+2]=='('||expr[i+2]=='\"')) { break; } }while(expr[i]!='\0'); i--; } else if (expr[i]=='\"') //如果是引号 { do //则一直写入 { pre->insig(expr[i]); i++; if (expr[i]=='\"') //直到遇到下一个引号停止 { pre->insig(expr[i]); break; } }while(expr[i]!='\0'); } else if ((expr[i]=='i')&&(i<=l-1&&expr[i+1]=='n')) //如果是关键字,则写入逗号,并标记关键字属性 { // pre->insig(expr[i++],CR); // pre->insig(expr[i],CR); pre->insig(',',CR); i++; } else //其余情况 { do //则一直写入,并标记是否有引号和括号 { if (expr[i]!=' '||pre->quonum) //如果有引号则引号中的字符不能略去空格 pre->insig(expr[i]); i++; //这里容错机制比较复杂 //首先在引号和括号未完成时不能跳出,即使遇到关键字,因为引号或括号中的"in"应该只是字符串或者变量之类的 //如果上述满足,则考虑是否是关键字,关键字前后必须有空格,或者"前面是闭括号或引号"并且"后面是开括号或引号" //否则,认为是函数名之类的,形如 ")in(" 是关键字,而 "fin(" 不是关键字 if (!pre->elenum&&!pre->quonum&&(expr[i]=='i')&&(i<=l-1&&expr[i+1]=='n')&&(i&&(expr[i-1]==' '||expr[i-1]==')'||expr[i-1]=='\"'))&&(i<=l-2&&expr[i+2]==' '||expr[i+2]=='('||expr[i+2]=='\"')) break; }while(expr[i]!='\0'); i--; } //-------------------------------------------------------------- if (pre!=old) { last->next=pre; pre->pre=last; last=pre; old=last; i++; } else { freelink(&head); break; } } } else { return NULL; } return head; } void getres(char *res,E * exp) { E *p=exp->next; int i=0; strcpy(res,"is_in("); //要生成is_in(is_in(A,B),is_in(C,D)) //则已经生成了 (A , B) , (C , D) //只要加上is_in(就行了 //先将(A , B)以及(C , D)联合,再将联合后的加个外壳is_in(进行最后联合 while(p!=NULL) { i=0; p->elenum=0; //这里有一个假设,即如果一个节点中的字符串括号是匹配的, //则不需要加is_in(,比如(a) in b生成is_in((a),b),而不是is_in(is_in(a),b) //而如果不匹配(一般来说应该是开括号多于闭括号),则将不匹配数目 //作为即将加上的is_in(数目,但is_in(的数目也受到连续开括号数目的限制 //如((a)in b)in c //得到((a) , b) , c //a的括号不匹配,所以应该加一个is_in(,即is_in((a) //而b的括号也不匹配,但由于b的是闭括号,因此没有加任何东西(看下面循环里面的解释) //这个假设将应用于带括号的算术表达式中 while(p->sig[i]!='\0') //检测括号匹配,开括号为正,闭括号为负 { if (p->sig[i]=='(') p->elenum++; if (p->sig[i]==')') p->elenum--; i++; } if (p->elenum<0) //如果闭括号多,则将负值改为正,以配合下面的递减操作 p->elenum=-p->elenum; i=0; while(p->elenum--&&p->sig[i]!='\0') //如果括号不匹配,则进行加is_in(操作 { if (p->sig[i]=='(') //这里要求开括号必须是字符开头连续的,否则退出循环,例如 b) 一进来就进入break了 strcat(res,"is_in("); else break; i++; } strcat(res,p->sig+i); //将加完is_in(后剩下的部分添加进结果 p=p->next; } strcat(res,")"); return; } void link(char *str) { char* res=new char[2*M]; cout<<str<<"\n"; E *expre=creat(str); viewlink(expre); getres(res,expre); cout<<res<<endl; cout<<endl; freelink(&expre); delete res; return; } int main() { char input1[M]="fun1(a1 ,\"in or not in\", \"((( (((((\") in fun2(\"(( (\\\"(in (\' ((\")"; char input2[M]="(A1 + A2) in (B1+B2)"; char input3[M]="(((( A1 + A2 )* (A3 + A4))/A5) in (B1+B2))in d"; char input4[M]="fun1llinij(\"((( A1 + A2 )* (A3 + A4))/A5)\") in fun2(\"if A in B\")"; char input5[M]="\"(A1)\" in ((A1)(B2))"; char input6[M]="A in join(B1, B2)"; char input7[M]="(a in b))in((c in d)in(e in f))"; char input8[M]="(r in((ain in b)in(((c in d)in(e in f))in g)))in h"; char input9[M]="((A)in B) in (C in D)"; link(input1); link(input2); link(input3); link(input4); link(input5); link(input6); link(input7); link(input8); link(input9); getch(); return 0; }
我做的基于链表的处理程序,静大大看看可行不?正则表达式我不是太懂,所以只能硬做。我利用以前做的一个字符计算器的字符处理函数,加上一些自己写的处理函数做成的,应该还有很多BUG,但是这里9个例子都是没有问题的。做的时候就是边做边调,有问题就添条件,添语句,修修补补做出来的,所以说不出核心思想来,详细说明在注释里面,看看结果吧>>>