您的位置:首页 > 编程语言 > Lua

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
  • 收藏
  • 分享
  • 文章举报
雾里看花花里看雾 发布了18 篇原创文章 · 获赞 12 · 访问量 1630 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: