EvaluateExpression 伟大而卑微的发现

据我验证 codeblocks 的ascii码在128后就不能输出 ,又因为在此之前代码是加上了48 ,所以一旦超过80 ,就输出错误 , 输出的是 (原本的答案 - 256),比如本来应该是120, 最后输出的结果会是 120 - 256= - 136,当然如果codeblocks的版本不一样可能结果不同 , 我的版本是Release 17.12 rev 11256 (2017-12-28 10:44:41) gcc 5.1.0 Windows/unicode - 32 bit。

#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 ElemType;
typedef int Status;
typedef char OperandType;
typedef char OperatorType;
typedef struct
{
    ElemType *base;
    ElemType *top;
    int stacksize;
}SqStack;
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 Gettop(SqStack S,ElemType *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;
}
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 Pop(SqStack *S,ElemType *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)
{
    SqStack OPTR;  //运算符栈
    InitStack(&OPTR);
    Push(&OPTR,'#');

    SqStack OPND;  //运算数栈
    InitStack(&OPND);

    char ch;
    int i=0;
    ch=exp[i++];

    OperandType a,b;  //运算数类型
    OperatorType c,e;   //运算符类型

    while(ch!='#'||GetTop(OPTR)!='#') //刚开始这里符号错误处理成了&&根本进不了循环 直接返回的就是#的ascii码是35   //GetTop(OPTR)!='#'是避免第一个数输入的就是运算符
    {
        if(!In(ch))
        {
            Push(&OPND,ch);
            ch=exp[i++];
        }
        else
        {
            switch(Precede(GetTop(OPTR),ch))
            {
            case '<':
                Push(&OPTR,ch);
                ch=exp[i++];
                break;

            case '=':
                Pop(&OPTR,&e);
                ch=exp[i++];
                break;

            case '>':                      //这里没有输入字符,保留的是刚刚的字符
                Pop(&OPTR,&c);
                Pop(&OPND,&b);
                Pop(&OPND,&a);
                Push(&OPND,Operate(a,c,b));  //这个地方顺序不能反  比如5-6哈 存进去是5 6 出来应该是6 5
                break;
            }
        }
    }

    return GetTop(OPND);

}
int main()
{
    char n;
    char *exp="3*(7-2)+8#";  //因为我输入的时候输入完#号后没有结果,所以我采用的这种方法,只需要将函数中的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# 的计算结果为:23

Process returned 0 (0x0)   execution time : 0.104 s
Press any key to continue.

发布了34 篇原创文章 · 获赞 38 · 访问量 2653

猜你喜欢

转载自blog.csdn.net/qq_43779149/article/details/104190993