编程论坛's Archiver

firel 发表于 2008-4-16 20:23

谁能做表达式求值啊 求助!!!!!!!!!!!!!!

做了一个但怎么也出不来!!!!!!!!1

zjl138 发表于 2008-4-16 21:55

帮你看了一下,光眼看,看不出什么,我一直用C++来写这些,我用VS2008编译器,打不开你那个malloc文件.
你若想要一个C++写的,我可以写一个发上来。

zjl138 发表于 2008-4-16 22:04

或者你可以BAIDU一下的,应该很多这方面的。

firel 发表于 2008-4-16 22:13

谢了兄弟

我一直都是用c没用过c++不过想试试看给我发一个把我看看谢了

zjl138 发表于 2008-4-18 11:31

昨天写好了,调试到今天,晕。。。。。。。。。
我写得是后缀计算表达式,因为现在编译程序一般都是用后缀表达式求解表达式的值。
我用VS2008编译器,经测试通过。如果有什么问题,望告诉一声,谢谢。
我用多文件形势写出来,包含:
栈类"Stack.h","Stack.cpp"
表达式类:"Calculator.h","Calculator.cpp"
还有一个"main.cpp"
大部分程序都有注释,如有不懂,再交流。。

zjl138 发表于 2008-4-18 11:32

//Stack.h

#ifndef STACK_H
#define STACK_H
typedef double DataType;
#include<iostream>
#include<cstdlib>
using namespace std;
const int MaxStackSize=50;
class Stack
{
private:
        DataType stacklist[MaxStackSize];
        int top;
public:
        Stack();
        void Push(const DataType& item);                //压入操作
        DataType Pop();                                 //弹出一个元素
        void ClearStack();                              //清空栈
        DataType Peek()const;                           //访问栈顶元素
        int StackEmpty()const;                          //查看是否为空栈
        int StackFull()const;                           //查看是否已满
};
#endif

zjl138 发表于 2008-4-18 11:32

//Stack.cpp

#include "Stack.h"
Stack::Stack():top(-1){}
void Stack::Push(const DataType& item)
{
        //若栈已满,则终止程序
        if(top==MaxStackSize-1)
        {
                cerr<<"Stack overflow!"<<endl;
                exit(1);
        }
                //将top加一并将ITEM拷贝到STACKLIST中
        top++;
        stacklist[top]=item;
}
DataType Stack::Pop()
{
        DataType temp;
        if(top==-1)                         //栈为空,退出
        {
                cerr<<"Attemp to pop an empty stack!"<<endl;
                exit(1);
        }
        temp=stacklist[top];                  //将栈顶元素赋给temp;
        //top减一并返回temp
        top--;
        return temp;
}
DataType Stack::Peek()const               //返回栈顶元素的值
{
        //若栈为空,退出
        if(top==-1)
        {
                cerr<<"Attemp to peek t an empty stack!"<<endl;
                exit(1);
        }
        return stacklist[top];
}
int Stack::StackEmpty()const              //检测栈是否为空
{
        return top==-1;                       //返回top==-1的逻辑值
}
int Stack::StackFull()const              //检测栈是否为满
{
        //检测top的位置
        return top==MaxStackSize-1;
}
void Stack::ClearStack()                   //从栈中清除所有元素
{
        top=-1;
}

zjl138 发表于 2008-4-18 11:33

//Calculator.h

#ifndef CALCULATOR_H
#define CALCULATOR_H
enum Boolean{False,True};

#include "Stack.h"
#include <cmath>
class Calculator
{
private:
        Stack s;                                      //存放操作数
        void Enter(double num);
        Boolean GetTwoOperands(double& opnd1,double &opnd2);
        void Compute(char op);
public:
       
        void Run();                                //计算表达式
        void Clear();                              //清空计算器
};
#endif

zjl138 发表于 2008-4-18 11:34

//Calculator.cpp


#include "Calculator.h"

void Calculator::Enter(double num)             //住栈中存放数据值
{
        s.Push(num);
}
//从栈中取得操作数并赋值给形参,若操作数不够,则打印出错信息,并返回False
Boolean Calculator::GetTwoOperands(double& opnd1,double& opnd2)
{
        if(s.StackEmpty())                         //检查操作数是否存在
        {
                cerr<<"Missing operand!"<<endl;
                return False;
        }
        opnd1=s.Pop();                               //取右操作数
        if(s.StackEmpty())
        {
                cerr<<"Missing operand!"<<endl;
                return False;
        }
        opnd2=s.Pop();                               //取左操作数
        return True;
}
void Calculator::Compute(char op)
{
        Boolean result;
        double operand1,operand2;
        //取两个操作数,并判断是否成功取到
        result=GetTwoOperands(operand1,operand2);
        if(result==True)
                switch(op)
        {
                case '+':
                        s.Push(operand2+operand1);
                        break;
                case '-':
                        s.Push(operand2-operand1);
                        break;
                case '*':
                        s.Push(operand2*operand1);
                        break;
                case '/':
                        if(operand1==0.0)
                        {
                                cerr<<"Divide by 0!"<<endl;
                                s.ClearStack();
                        }
                        else
                                s.Push(operand2/operand1);
                        break;
                case '^':
                        s.Push(pow(operand2,operand1));
                        break;
        }
        else
                s.ClearStack();                       //出错!清空计算器
}
void Calculator::Run()
{
        char c;
        double newoperand;
        while(cin>>c&&c!='=')                           //读入字符,直到遇“=”时退出
        {
                switch(c)
                {
                case '+':
                case '-':
                case '*':
                case '/':
                case '^':
                        Compute(c);                        //读到运算符,求值
                        break;
                default:
                        //非运算符,则必为操作数,将数字送回
                        cin.putback(c);
                        //读入操作符并将其存入栈中
                        cin>>newoperand;
                        Enter(newoperand);
                        break;
                }
        }
        //答案已在栈顶,用peek输出之
        if(!s.StackEmpty())
                cout<<s.Peek()<<endl;
}
//清空操作数栈
void Calculator::Clear()
{
        s.ClearStack();
}

zjl138 发表于 2008-4-18 11:34

//main.cpp

#include "Calculator.h"
int main()
{
    Calculator Calc;
        Calc.Run();
        system("pause");
        return 0;
}

sunkaidong 发表于 2008-4-18 12:13

前几天写的支持括号,但是只支持正整数

#include<stdio.h>
#include<stdlib.h>
#include <ctype.h>
#define Stack_Size 50
typedef struct
{
    char elem[Stack_Size];
    int top;
}OpStack;
typedef struct
{
    int elem[Stack_Size];
    int top;
}NumStack;

void Push(OpStack *s,char x);
void Pop(OpStack *s,char *x);
void Push(NumStack *s,int x);
void Pop(NumStack *s,int *x);
int Execute(int a,char c,int b);
int ExpEvaluation(NumStack *OVS,OpStack *OPTR);
void GetNumber(char p);
int Cint(char mychar);
int num=0;
void main()
{   
    int result;
    OpStack OPTR;
    NumStack OVS;
    OVS.top=-1;OPTR.top=-1;
    result=ExpEvaluation(&OVS,&OPTR);
    printf("The result is %d\n",result);
}

void Push(OpStack *s,char x)
{
    s->top++;
    s->elem[s->top]=x;
}
void Pop(OpStack *s,char *x)
{
    *x=s->elem[s->top];
    s->top--;
}
void Push(NumStack *s,int x)
{
    s->top++;
    s->elem[s->top]=x;
}
void Pop(NumStack *s,int *x)
{
    *x=s->elem[s->top];
    s->top--;
}
int Execute(int a,char c,int b)
{
   
     switch(c)
     {
     case '+':return a+b;break;
     case '-':return a-b;break;
     case '*':;return a*b;break;
     case '/':return a/b;break;
     }
     
}

void GetNumber(char p)
{
    num=num*10+Cint(p);
}
int Cint(char mychar)
{
    return (mychar-48);
}
//栈运算符与读入运算符优先级的比较
char Compare(char x,char y)
{
  char priority='<';  
  switch(x)
  {
   case '+':
   case '-':if(y=='#'||y=='+'||y=='-'||y==')')priority='>';break;
   case '*':
   case '/': priority='>';if(y=='(' )priority='<';break;
   case '(':if(y==')')priority='=';break;
   case '#':if(y=='#') priority='=';break;
   default:priority='E';
  }
  return priority;
}
int ExpEvaluation(NumStack *OVS,OpStack *OPTR)
{
     int v,flag=0,f1=1,f2=1;
    char ch,ch1,c;
    int a,b,flag1=1;
    Push(OPTR,'#');
    printf("\n\nputin a string(stop with #):");
    while(ch!='#'||OPTR->elem[OPTR->top]!='#')
    {   if(f1&&f2)
         ch=getchar();
        if(isdigit(ch))
        {
            GetNumber(ch);
            
        }
        else
        {   
            
            if((ch>='0'&&ch<='9'||ch1>='0'&&ch1<='9')&&!flag)
            {   
                Push(OVS,num);            
                num=0;
            }
            switch(Compare(OPTR->elem[OPTR->top],ch))
            {
                                
            case '<':               
                Push(OPTR,ch);
                flag=0;
                break;
            case '>':
                Pop(OPTR,&c);
                Pop(OVS,&b);
                Pop(OVS,&a);
                v=Execute(a,c,b);
               
                if(OPTR->elem[OPTR->top]=='-')
                {
                      v=-1*v;
                      OPTR->elem[OPTR->top]='+';
                }
                    Push(OVS,v);
                if(ch!='#'&&ch!=')')   
                {   
                    
                        Push(OPTR,ch);
                        flag=0;
                }
                else
                {
                    f1=0;
                    flag=1;
                    
                }
               
                //printf("%d %c %d  %d\n",a,c,b,v);
                break;
            case '=':
                Pop(OPTR,&c);
                if(c=='('&&ch==')')
                {   
                    
                        f1=1;
                        flag=1;
                    
                }
                break;
            default:printf("Wrong Express!");exit(0);
               
            }
        }
         ch1=ch;
         
    }
   
    return(v);
}

zjl138 发表于 2008-4-18 12:23

呵呵,楼上厉害,我用的是数组,我的整形,浮点都行,还能算平方。我的篇幅太长了,自已看了都头疼,呵呵。。。

sunkaidong 发表于 2008-4-18 12:32

我的没办法.因为只能一个一个字符读取..然后还要分析..当然改一下也可以..呵呵.反正是玩玩..等到有时间的时候给它改版..呵呵

firel 发表于 2008-4-18 12:33

强啊  哈哈谢谢啊

firel 发表于 2008-4-18 17:37

这是怎么了

为什么在我的机子上不能通过我用的是vc++6.0我没学过c++
不要见笑啊

zjl138 发表于 2008-4-18 18:05

[quote][bo]以下是引用 [un]firel[/un] 在 2008-4-18 17:37 的发言:[/bo]

为什么在我的机子上不能通过我用的是vc++6.0我没学过c++
不要见笑啊 [/quote]
是我的吗,我的在VS2008通过,并测试正确,你用VC6,可以先建一个空的WIN32 console application,然后再一个一个地把文件加进去,注意哪些是头文件,哪些是源文件。
你没学过C++吗?那sunkaidong大哥写得应该看得懂吧,就用他的了。

sunkaidong 发表于 2008-4-18 18:22

用楼上的兄弟的..他的很规范..说实在的..我的程序理解有点难...

zjl138 发表于 2008-4-18 18:40

呵呵,楼上谦虚!
另外,我帮楼主你再看了一下源程序,由于你没写注释,我看得比较累,就没认真看,但发现了几个重要错误,就是你使用的变量i,m都没有初始化,还有就是这个警告:warning C4715: 'precede' : not all control paths return a value
其实该算是个错误了:就是你自定义函数里出了错。你希望函数返回某个值,但是可能在函数里加了if等条件判断,使得一部分情况下有返回值,而另一种情况没返回值。我也帮你改了一下。现在能运行了,但发现你没写最后结果的输出函数,这个就你自已加了。呵呵。。。

zjl138 发表于 2008-4-18 18:41

//下面是我帮你改的:
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define num 20
typedef struct stackf
{
        int *top;
        int *base;
}stack1;
typedef struct stackl
{
        char *top;
        char *base;
}stack2;
char precede(char x,char y)
{
        switch(x)
        {
        case '+':
                if(y=='+'||y=='-'||y==')'||y=='#')
                                return '>';
                else
                return '<';
        case '-':
                if(y=='+'||y=='-'||y==')'||y=='#')
                                return '>';
                else
                return '<';
        case '*':
                if(y=='(')
                        return '<';
                else
                        return '>';
        case '/':
                if(y=='(')
                        return '<';
                else
                        return '>';
        case '(':
                if(y==')')
                        return '=';
                else
                        if(y=='#')
                        break;
                else
                        return '<';
        case ')':
                if(y=='(')
                break;
                else
                        return '>';
        case '#':
                if(y=='#')
                        return '=';
                else
                        if(y==')')
                break;
                        else
                                return '<';
        }
        return 1;
}
void init_stack1(stack1 *st)
{
        st->base=(int *)malloc(num*sizeof(int));
        st->top=st->base;
}
void init_stack2(stack2 *st)
{
        st->base=(char *)malloc(num*sizeof(char));
        st->top=st->base;
}
int empty_stack1(stack1 *st)
{
        if(st->base==st->top)
                return 1;
        return 0;
}
int empty_stack2(stack2 *st)
{
        if(st->base==st->top)
                return 1;
        return 0;
}
int full_stack1(stack1 *st)
{
        if(st->top-st->base>=num)
                return 1;
        return 0;
}
int full_stack2(stack2 *st)
{
        if(st->top-st->base>=num)
                return 1;
        return 0;
}
void push1(stack1 *st,int x)
{
                if(full_stack1(st))
                        printf("error");
                else
                        *st->top++=x;
}
void push2(stack2 *st,int x)
{
                if(full_stack2(st))
                        printf("error");
                else
                        *st->top++=x;
}
int pop1(stack1 *st)
{       
        int shuzi;
        shuzi=--*st->top;
        return shuzi;
}
char pop2(stack2 *st)
{       
        char zimu;
        zimu=--*st->top;
        return zimu;
}
char get_top2(stack2 *st)
{

                return *(st->top-1);
}
int operter(int num1,char oper,int num2)
{
        switch(oper)
        {
        case '+':
                return num1+num2;
                break;
        case '-':
                return num1-num2;
                break;
        case '*':
                return num1*num2;
                break;
        case '/':
                return num1/num2;
        }
        return 1;
}
void open()
{
        printf("****************************************\n");
        printf("***作者----------------冯亮*************\n");
        printf("***计算机0602--------------*************\n");
        printf("****************************************\n");
        printf("****请输入您想的操作********************\n");
        printf("0-----------------退出\n");
        printf("1-----------------输入表达式\n");
        printf("2-----------------使用说明\n");
}
void readme()
{
        printf("****************************************\n");
        printf("输入数据!!\n");
        printf("例如 ----1+2*3-4#以#号结束\n");
        printf("谢谢使用^_^!\n");
        printf("****************************************\n");
}
void main()
{       
        int i,x,num1,num2,m=0,e;
        char oper;
        stack1 s;
        stack2 r;
        char a[20];
        init_stack1(&s);
        init_stack2(&r);
        push2(&r,'#');
        while(1)
        {
                open();
                scanf("%d",&i);
                switch(i)
                {
                case 0:
                        break;
                case 1:
                        printf("请输入表达式!!!!!!!!\n");
                        scanf("%s",a);
                        while(a[m]!='#')
                                {       
                                        x=a[m];
                                        if(x>=60&&x<=69)
                                        {
                                                if(a[m-1]>=60&&a[m-1]<=69&&m>0)
                                                {
                                                        e=pop1(&s);
                                                        e=e*10+(int)(x-'0');
                                                }
                                                else
                                                e=(int)(x-'0');
                                                push1(&s,e);
                                                m++;
                                        }
                                        else
                                        {
                                                switch(precede(get_top2(&r),x))
                                                {
                                                case '<':
                                                push2(&r,x);
                                                break;
                                                case '>':
                                                        num1=pop1(&s);
                                                        num2=pop1(&s);
                                                        oper=pop2(&r);
                                                        push1(&s,operter(num1,oper,num2));
                                                        break;
                                                case '=':
                                                        pop2(&r);
                                                        break;
                                                }
                                                m++;
                                        }
                                }
                                break;
                case 2:
                        readme();
                        break;
                default :
                        printf("error");
                        break;
                }
                               
        }
}

sunkaidong 发表于 2008-4-18 19:04

那个结果问题是我故意的..毕竟我的运算函数只有四个操作符号.....结果有输出啊....没有结果不好判断对错了...呵呵...

[[it] 本帖最后由 sunkaidong 于 2008-4-18 19:06 编辑 [/it]]

页: [1] 2

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.