EvaluateExpression 2.0
2020-02-17 10:07
393 查看
因为char类型越界了,表达式求值都是int类型的,所以我的策略就是定义两种类型的栈,OPTR是运算符栈,指向char类型,OPND是运算数栈,指向int类型,最后EvaluateExpression函数返回的是表达式求值的结果,返回的是int类型,所以就算返回168,也是可以存储的,不会溢出,但是不能都是char类型的,然后用int类型的接受,因为那样,char类型本身就会溢出,使用int后还是错误的数据。
#include<stdio.h> #include<stdlib.h> #define OVERFLOW -2 #define OK 1 #define ERROR 0 #define TRUE 1 #define FALSE 0 #define STACK_INIT_SIZE 100 #define STACKINCREMENT 10 typedef char cElemType; typedef int ElemType; typedef int Status; typedef int OperandType; typedef char OperatorType; typedef struct { ElemType *base; ElemType *top; int stacksize; }SqStack; typedef struct { cElemType *base; cElemType *top; int stacksize; }cSqStack; Status InitStack(SqStack *S) { (*S).base=(ElemType *)malloc(STACK_INIT_SIZE*sizeof(ElemType)); if(!(*S).base) exit(OVERFLOW); (*S).top=(*S).base; (*S).stacksize=STACK_INIT_SIZE; return OK; } Status InitcStack(cSqStack *S) { (*S).base=(cElemType *)malloc(STACK_INIT_SIZE*sizeof(cElemType)); if(!(*S).base) exit(OVERFLOW); (*S).top=(*S).base; (*S).stacksize=STACK_INIT_SIZE; return OK; } Status Gettop(SqStack S,ElemType *e) { if(S.top==S.base) return ERROR; *e=*(S.top-1); return OK; } Status cGettop(cSqStack S,cElemType *e) { if(S.top==S.base) return ERROR; *e=*(S.top-1); return OK; } OperandType GetTop(SqStack S) { ElemType e; Gettop(S,&e); return e; } OperatorType cGetTop(cSqStack S) { cElemType e; cGettop(S,&e); return e; } Status Push(SqStack *S,ElemType e) { if(((*S).top-(*S).base)>=(*S).stacksize) { (*S).base=(ElemType *)realloc((*S).base,(STACK_INIT_SIZE+STACKINCREMENT)*sizeof(ElemType)); if(!(*S).base) exit(OVERFLOW); (*S).stacksize+=STACKINCREMENT; (*S).top=(*S).base+(*S).stacksize; } *((*S).top++)=e; return OK; } Status cPush(cSqStack *S,cElemType e) { if(((*S).top-(*S).base)>=(*S).stacksize) { (*S).base=(cElemType *)realloc((*S).base,(STACK_INIT_SIZE+STACKINCREMENT)*sizeof(cElemType)); if(!(*S).base) exit(OVERFLOW); (*S).stacksize+=STACKINCREMENT; (*S).top=(*S).base+(*S).stacksize; } *((*S).top++)=e; return OK; } Status Pop(SqStack *S,ElemType *e) { if((*S).base==(*S).top) return ERROR; *e=*(--(*S).top); return OK; } Status cPop(cSqStack *S,cElemType *e) { if((*S).base==(*S).top) return ERROR; *e=*(--(*S).top); return OK; } Status In(char c) //只会对字符进行判断 应该不会越界 { switch(c) { case '+': case '-': case '*': case '/': case '(': case ')': case '#': return TRUE; break; default: return FALSE; break; } } OperandType Operate(OperandType a,OperatorType c,OperandType b) { int x,y; //0的ascii码是48 //这是错误的写法 如果是数字0-9那么没有问题 但是这里是可能14 20就不能这样了 //x=a-'0'; //y=b-'0'; x=a-48; y=b-48; //直接用数字是没有问题的 switch(c) { case '+': return x+y+48; break; case '-': return x-y+48; break; case '*': return x*y+48; break; case '/': return x/y+48; break; } } OperatorType Precede(OperatorType e1,OperatorType e2) //数据结构p53页表格 { OperatorType f; switch(e2) { case '+': case '-': if(e1=='('||e1=='#') f='<'; else f='>'; break; case '*': case '/': if(e1=='*'||e1=='/'||e1==')') f='>'; else f='<'; break; case '(': if(e1==')') { printf("括号匹配错误\n"); exit(-1); } else f='<'; break; case ')': switch(e1) { case '(': f='='; break; case '#': printf("输出了错误的括号\n"); exit(-1); break; default: f='>'; break; } break; //刚开始这里忘记了break case '#': switch(e1) { case '#': f='='; break; case '(': printf("括号匹配错误\n"); exit(-1); break; default: f='>'; break; } break; //case中的break只跳出小switch,在这种情况下会继续向大switch下比较 } return f; } OperandType EvaluateExpression(char *exp) { cSqStack OPTR; //运算符栈 InitcStack(&OPTR); cPush(&OPTR,'#'); SqStack OPND; //运算数栈 InitStack(&OPND); char ch; int i=0; ch=exp[i++]; OperandType a,b; //运算数类型 OperatorType c,e; //运算符类型 while(ch!='#'||cGetTop(OPTR)!='#') //刚开始这里符号错误处理成了&&根本进不了循环 直接返回的就是#的ascii码是35 //GetTop(OPTR)!='#'是避免第一个数输入的就是运算符 { if(!In(ch)) { Push(&OPND,ch); ch=exp[i++]; } else { switch(Precede(cGetTop(OPTR),ch)) { case '<': cPush(&OPTR,ch); ch=exp[i++]; break; case '=': cPop(&OPTR,&e); ch=exp[i++]; break; case '>': //这里没有输入字符,保留的是刚刚的字符 cPop(&OPTR,&c); Pop(&OPND,&b); Pop(&OPND,&a); Push(&OPND,Operate(a,c,b)); //这个地方顺序不能反 比如5-6哈 存进去是5 6 出来应该是6 5 break; } } } return GetTop(OPND); } //#include<stdio.h> //int main() //{ // char c=168; // printf("%d",c-48); // return 0; //} // //-136 //Process returned 0 (0x0) execution time : 0.196 s //Press any key to continue. // //分析如下: //c语言的char类型只有一个字节,默认的char是有符号字符型,取值范围是-128~127 //定义char是168的话,越界了,会做如下处理 //168是正数,原码是10101000,而计算机是按照补码形式计算存储的,正数的补码等于原码,所以存在计算机里的是10101000 //计算机在读取的时候,最高位被当作符号位,因为最高位是1,所以就是负数,又因为补码形式计算存储,求原值求原码 //负数的原码等于补码的补码,所以就是符号位不变,其他位取反末位加一,11011000,最高位1换算成-号,结果就是-88 //在输出的时候又是c-48,所以结果就是-88-48=-136 // //#include<stdio.h> //int main() //{ // char c=128; // printf("%d",c); // return 0; //} // //-128 //Process returned 0 (0x0) execution time : 1.562 s //Press any key to continue. // //分析如下: // //那么-128,其原码为1 (符号位)10000000,符号位不变,其他位求反后末尾加一,求得补码为1(符号位) 10000000,由于char类型一个字节,只能存储8位,存储后为10000000 // //读取时,因为首位是1,为负数,所以其他位按位求反再加一,结果为10000000,为128,所以为-128 // //128是正数,补码等于原码为10000000,存储在计算机中,因为这个等于-128的补码,所以输出为-128 // //总结: // //1.把原本的数转换成二进制,求取补码,溢出后截取符合的位数,存储在计算机中 // //2.读取的时候,按照最高位是符号位,再根据对应的符号,对数值进行相应的处理,读取数据 int main() { int n; char *exp="3*(7-2)*8*9-7#"; //因为我输入的时候输入完#号后没有结果,所以我采用的这种方法,只需要将函数中的ch=getchar();换成ch=exp[i++] n=EvaluateExpression(exp); printf("作为示例,%s 的计算结果为:%d\n",exp,n-48); return 0; //char *exp = "(2+3)*4*6#"; //这个的输出结果一直都是-136,奇奇怪怪 //我当时的想法就是120+48后是168 超过了128范围 所以出错了 //char *exp="3*(7-2)*9#"; //这个结果是-121 本来结果应该是135 135+|-121|=256 //char *exp="3*(7-2)*8#"; //这个结果是-136 本来结果是120 120+|-136|=256 //据我验证 128后就不能输出 在此之前是加上了48 所以超过80 就输出错误 输出的是 原本的答案-256 //char *exp="9*9#" 就是81-256=-175 } //#include<stdio.h> //int main() //{ // int a=168; // printf("%c",a); // return 0; //} //127的ascii码 在控制台输出时我没有看到 但是复制粘贴输出结果的时候出现了这个 太神奇了吧 // //Process returned 0 (0x0) execution time : 1.412 s //Press any key to continue. //128的ascii码 我居然在控制台看到了这样原封不动的样子 //€ //Process returned 0 (0x0) execution time : 0.105 s //Press any key to continue. //129的时候就没有输出了 //Process returned 0 (0x0) execution time : 0.099 s //Press any key to continue. 测试结果: 作为示例,3*(7-2)*8*9-7# 的计算结果为:1073 Process returned 0 (0x0) execution time : 1.379 s Press any key to continue.
- 点赞 1
- 收藏
- 分享
- 文章举报
相关文章推荐
- 「Codeforces」742D Arpa's weak amphitheater and Mehrdad's valuable Hoses (背包、并查集)
- Beginning Lua with WoW Addons - The TOC File
- Unable to evaluate expression using this context
- Lua中的迭代器
- Lua实现继承
- 【转载】【游戏开发】在Lua中实现面向对象特性——模拟类、继承、多态
- 【Rainmeter】写Lua脚本遇到的文件读写问题
- xlua备忘录
- LUA写ini配置
- lua和C#中函数string.format处理浮点数时的区别
- LUA-0 Lua的基本语法
- LUA-1 Table中的Metatables和Metamethods
- 关于lua反编译文件中文字符显示为10进制字符的处理
- lua中dofile、loadfile、require区别
- 初探angluar_01 目录结构分析及初始化项目
- 自动生成查找组件的lua代码
- [lua] 游戏客户端逻辑使用lua协程
- [lua] 你所不知道的lua nil值在可变参数函数中怎么处理!
- [lua] lua中匹配字符串小数
- lua短连接