#2
九转星河2017-03-23 00:43
公测一下这个~~~
检查表达式是否正确是实现四则混合运算的基础~ 这段代码只是完善了检查表达式是否合法的功能~暂时还没有检查出BUG(除了前导0这个问题可以忽略)~~~ 程序代码: #include<stdio.h> #include<stdlib.h> #include<ctype.h> #include<string.h> #define LEN_Node sizeof (Node) #define LEN_Single sizeof (Single) typedef enum COM { NUMBER, //数字 SINGLE, //运算符号(加减乘除) ADD, //加号 SUB, //减号 MUL, //乘号 DIV, //除法 POINT, //小数点 LEFT_PARENTHESES, //左括号 RIGHT_PARENTHESES, //右括号 WAIT_USE, //等待使用(对于小数点处理) CAN_USE, //可以使用 CANNOT_USE, //不能使用 OK, //正常 ERROR, //出错 }COM; typedef struct Single //运算符号 { char c; //符号标记 int level; //符号运算优先等级 }Single; Single single[]={'(',1,')',1,'*',2,'/',2,'+','3','-',3,'.',4}; typedef struct Single_Style { COM num; //检查能否使用数字 COM add; //加法状态 COM sub; //减法状态 COM mul; //乘法状态 COM div; //除法状态 COM point; //小数点状态 COM left_parentheses; //左括号状态 COM right_parentheses; //右括号状态 }Single_Style; Single_Style com={0}; typedef struct Node { char c; struct Node* next; }Node,*PNode; char Num_Buff[100]={0}; //数据缓冲空间 PNode New_Node(PNode head,int size); //创建一个头节点 PNode Init(PNode head); //创建一个表达式 COM Find_Single(char c,char*ch ,int* level); //查找是否存在符号 void Single_CAN_USE(); //运算符可以使用 void Single_CANNOT_USE(); //运算符不可以使用 COM Check(PNode head); //检查表达式输入是否合法 void Print(PNode p); //输出数据 int main() { PNode head=NULL; head=New_Node(head,LEN_Node); head=Init(head); if (Check(head)==ERROR) { puts("输入表达式有误!"); exit(0); } Print(head); return 0; } PNode New_Node(PNode p,int Size) //创建一个头节点 { p=(PNode)malloc(Size); if (p==NULL) { puts("创建失败!"); exit(0); } memset(p,0,Size); return p; } PNode Init(PNode head) //创建一个表达式 { PNode p=head; char ch=0; while (p->next) //把指针移到尾部 p=p->next; puts("请输入表达式:"); while ((ch=getchar())!='\n') { p=p->next=New_Node(p,LEN_Node); p->c=ch; } return head; } void Print(PNode p) //输出数据 { puts("输入表达式如下:"); for (;p=p->next;printf("%c",p->c)); puts(""); } int Find_Single(char c,char*ch ,int* level) //查找是否存在符号 { int i=0; if (isdigit(c)) return NUMBER; //返回数字 for (i=0;c!=single[i].c&&i<sizeof(single)/sizeof(*single);++i); if (i==sizeof(single)/sizeof(*single)) //如果找不到运算符号,则显示出错 return ERROR; *ch=single[i].c; *level=single[i].level; switch (single[i].c) { case '(': return LEFT_PARENTHESES; case ')': return RIGHT_PARENTHESES; case '+': return ADD; case '-': return SUB; case '*': return MUL; case '/': return DIV; case '.': return POINT; default : return ERROR; } } void Single_CAN_USE() { com.add=CAN_USE; //可以使用加法 com.sub=CAN_USE; //可以使用减法 com.mul=CAN_USE; //可以使用乘法 com.div=CAN_USE; //可以使用除法 } void Single_CANNOT_USE() { com.add=CANNOT_USE; //不可以使用加法 com.sub=CANNOT_USE; //不可以使用减法 com.mul=CANNOT_USE; //不可以使用乘法 com.div=CANNOT_USE; //不可以使用除法 com.point=CAN_USE; com.left_parentheses=CAN_USE; //可以使用左括号 com.right_parentheses=CANNOT_USE;//不可以使用右括号 } COM Check(PNode head) { PNode p=head; COM cc=0; int parentheses=0; //判断括号是否合理,初始记录括号数目为0 int point=WAIT_USE; //判断小数点是否合理 char ch=0; char t_ch=0; //暂存单元 int level=0; //运算符优先等级记录(初始化暂不需要) com.num=CAN_USE; com.add=CAN_USE; //初始化加号可以用 com.sub=CAN_USE; //初始化减号可以用 com.mul=CANNOT_USE; //初始化乘号可以用 com.div=CANNOT_USE; //初始化除号可以用 com.point=WAIT_USE; //初始化小数点等待使用 com.left_parentheses=CAN_USE; //初始化左括号可以使用 com.right_parentheses=CANNOT_USE; //初始化右括号不可以使用 while (p=p->next) //判断所有字符输入都是合法数据 { switch (Find_Single(p->c,&ch,&level)) { case NUMBER: //数字 if (com.num==CANNOT_USE) return ERROR; Single_CAN_USE(); //运算符号可以使用 if (com.point==WAIT_USE) com.point=CAN_USE; com.right_parentheses=CAN_USE; //数字后面可以跟右括号 break; case ADD: if (com.add==CANNOT_USE) return ERROR; Single_CANNOT_USE(); //不可以连续使用运算符号 com.point=WAIT_USE; //小数点可以等待使用 com.sub=CAN_USE; //加号后面可以跟减号 com.num=CAN_USE; //符号右边可以使用数字 break; case SUB: if (com.sub==CANNOT_USE) return ERROR; Single_CANNOT_USE(); //不可以连续使用运算符号 com.point=WAIT_USE; com.add=CAN_USE; //可以使用加号 com.num=CAN_USE; break; case MUL: if (com.mul==CANNOT_USE) return ERROR; case DIV: if (com.div==CANNOT_USE) return ERROR; Single_CANNOT_USE(); //如果遇到乘除运算符号,则该符号不能连续使用 com.point=WAIT_USE; com.num=CAN_USE; break; case POINT: if (com.point==CAN_USE) { Single_CANNOT_USE(); //小数点后面不能直接跟运算符号 com.left_parentheses=CANNOT_USE; //左括号不能使用 com.right_parentheses=CANNOT_USE; //右括号不能使用 com.point=CANNOT_USE; } else return ERROR; break; case LEFT_PARENTHESES: if (com.left_parentheses==CANNOT_USE) return ERROR; ++parentheses; //记录括号标记个数+1 Single_CANNOT_USE(); //不可以使用运算符号 com.right_parentheses=CANNOT_USE; //右括号不能使用 com.add=CAN_USE; //重置可以使用加号 com.sub=CAN_USE; //重置可以使用减号 break; case RIGHT_PARENTHESES: if (com.right_parentheses==CANNOT_USE) return ERROR; --parentheses; //记录括号标记个数-1 if (parentheses<0) //如果括号标记小于0 return ERROR; Single_CAN_USE(); //可以使用运算符号 com.num=CANNOT_USE; //右括号右端不能使用数字 break; case ERROR: return ERROR; default : return ERROR; } t_ch=p->c; //记录暂存单元 } cc=Find_Single(t_ch,&ch,&level); if (t_ch!='\0'&&cc!=NUMBER&&cc!=RIGHT_PARENTHESES) //考虑尾数不是数字和右括号的情况 return ERROR; if (parentheses!=0) //如果括号不匹配 return ERROR; return OK; } [此贴子已经被作者于2017-3-23 05:26编辑过] |
现在需要一个程序来判断该表达式是否合法~
表达式运算符只有'+','-''*','/','(',')'和小数点'.'
数字以十进制0-9的形式输入~
所谓合法就是指能在编译器正常通过编译的表达式~
例如:
1+2+3---合法
2.2+3*4---合法
-5+6*(4+1)/3+2---合法(最前一位可以是负号)
((4+3)+2---非法(左右括号不匹配)
4.65**2--非法(运算符号问题)
.45+1和45.和5.666.7---非法(小数点不合法)
45+22+ ---非法(最后一个运算符号找不到数字匹配)
56#33 ---非法(含有非法运算符)
777+()/3 ---非法(括号内容不能为空)
12+(34)3 ---非法(括号右端必须跟运算符)
PS:3+-4或者3-+4也是合法表达式,但3--4和3++4就是非法表达式了(不能正常通过编译)~
总之~能通过编译器编译的常量表达式都是合法表达式~
否则就不是合法表达式~
输入一串字符串,判断该表达式是否是合法表达式(字符串长度在100以内)~
感觉要考虑的情况很多的样子~看看有没有高手能给些高见?~感觉数据结构很冷清啊~还是发在人气较旺的C论坛比较好~希望有高手能做出来~~~
[此贴子已经被作者于2017-3-22 23:03编辑过]