C++ 实现 算数表达式求值

好不容易抽出点时间来复习一下数据结构和算法。

看到堆栈部分。有2道题目,第一道是计算C系列括号匹配校验。第二道是计算算数表达式。

第一道题是思路是

跳过 ' ""字符串,/* // 注释以后。

如果发现{, [, ( 那么入栈,发现 },],) 以后出栈,对比是否匹配。

文件检查完以后,堆栈内为空,说明匹配成功。

(ps一句,很多代码是抄的)


第二道题思路

首先把中缀式转换为后缀式。

转换过程

1)若读入的是操作数,入到输出栈

2)读入的是闭括号,把操作栈中的运算符依次出栈,推入输出栈,一直遇到对应开括号为止,把开括号出栈

3)读入的开括号,进运算符栈

4)读入的是运算符,如果运算符栈优先级高,堆栈运算符出栈,出栈操作一直要进行到栈顶运算符优先级低为止,然后把新的运算符入栈

5)在读入操作符结束扣,把运算符栈中所有剩余运算符依次出栈,放入输出栈

6)计算输出堆表达式的


直接发代码.

先发堆栈的。

#ifndef __ListDemo__List__
#define __ListDemo__List__

#include 

template 
class ListNode
{
public:
    T            element;
    ListNode  *next;
public:
    ListNode(T te, ListNode *L):element(te), next(L){}
    ListNode(T te):element(te), next(NULL){}
};

template 
class Stack {
private:
    ListNode      *head;
public:
    const int isEmpty() const;
    
    void    push(T x);
    T       pop();
    T       top();
};


template 
const int Stack::isEmpty() const
{
    return head == NULL;
}

template 
void Stack::push(T x)
{
    if (head == NULL)
    {
        head = new ListNode(x);
    }
    else
    {
        ListNode *p = new ListNode(x, head);
        
        head = p;
    }
}

template 
T Stack::pop()
{
    if (head == NULL)
    {
//        return NULL;
    }
    ListNode *p = head->next;
    T x = head->element;
    delete head;
    head = p;
    
    return x;
}

template 
T Stack::top()
{
    if (head == NULL)
    {
        //        return NULL;
    }
    return head->element;
}

#endif /* defined(__ListDemo__List__) */

第一道题:

#ifndef ListDemo_CheckFlag_h
#define ListDemo_CheckFlag_h

#include 
#include "List.h"

struct Symbol {
    char    Token;
    int     Theline;
};

class CheckFlag
{
private:
    enum CommonentType { SlashSlash, SlashStar };   // // or /*
    istream &       InputStream;
    char            Ch;
    int             CurrentLine;
    Stack   PendingTokens;                  //没有处理的开括号
    int             Errors;
    
private:
    int NextChar();                                 //下1个字符
    void PutBackChar();                             //把当前字符放回输入流
    void SkipComment(CommonentType Start);          //跳过 // /*
    void SkipQuote(char QuoteType);                 //跳过 '' 和 ""
    char GetNextSymbol();                           //获得下1个括号
    void CheckMatch(const Symbol & OpSym, const Symbol & ClSym);        //查开闭括号是否匹配
    
public:
    CheckFlag(istream & Input) : Errors(0), CurrentLine(1), InputStream(Input){}
    ~CheckFlag() {}
    int CheckBalance();                             //检查括号是否匹配
};

int CheckFlag::NextChar()
{
    if (!InputStream.get(Ch))
    {
        return 0;
    }
    if (Ch == '\n')
    {
        CurrentLine++;
    }
    return 1;
}

void CheckFlag::PutBackChar()
{
    InputStream.putback(Ch);
    if (Ch == '\n')
    {
        CurrentLine--;
    }
}

void CheckFlag::SkipComment(CheckFlag::CommonentType Start)
{
    if (Start == SlashSlash)    //处理 //
    {
        while (NextChar() && Ch != '\n')
        {}
        return;
    }
    int State = 0;              //处理 /*
    while (NextChar())
    {
        if (State && Ch == '/')
        {
            return;
        }
        State = Ch == '*';
    }
    Errors ++;
    std::cout << "Comment not is unterminated!" << std::endl;
}

void CheckFlag::SkipQuote(char QuoteType)
{
    while (NextChar())
    {
        if (Ch == QuoteType)
        {
            return;
        }
        else if (Ch == '\n')            //搜索1行结束,没有找到引号
        {
            Errors++;
            std::cout << "Missing closed quote at line" << CurrentLine << std::endl;
        }
        else if (Ch == '\\')
        {
            NextChar();                 //跳过\转义
        }
    }
}

char CheckFlag::GetNextSymbol()
{
    while (NextChar())
    {
        if (Ch == '/')
        {
            if (NextChar())
            {
                if (Ch == '*')
                {
                    SkipComment(SlashStar);
                }
                else if (Ch == '/')
                {
                    SkipComment(SlashSlash);
                }
            }
        }
        else if (Ch == '\'' || Ch == '"')
        {
            SkipQuote(Ch);
        }
        else if (Ch == '{' || Ch == '(' || Ch == '[' ||
                 Ch == '}' || Ch == ')' || Ch == ']')
        {
            return Ch;
        }
    }
    return 0;
}

int CheckFlag::CheckBalance()
{
    char LastChar;
    Symbol LastSymbol, Match;
    Errors = 0, CurrentLine = 1;
    
    while ((LastChar = GetNextSymbol()))        //得到当前开闭括号
    {
        LastSymbol.Token = LastChar;
        LastSymbol.Theline = CurrentLine;       //当前括号所在行号
        switch (LastChar) {
            case '(':
            case '{':
            case '[':
                PendingTokens.push(LastSymbol);
                break;
            
            case ')':
            case '}':
            case ']':
                if (PendingTokens.isEmpty()) {
                    Errors++;
                    std::cout << "Extraneous" << LastChar << "at line" << CurrentLine << endl;
                }
                else
                {
                    Match = PendingTokens.pop();
                    CheckMatch(Match, LastSymbol);
                }
                break;
                
            default:
                break;
        }
    }
    
    //堆栈还有数据
    while (! PendingTokens.isEmpty()) {
        Errors++;
        Match = PendingTokens.pop();
        std::cout << "Un matched" << Match.Token << "at line" << Match.Theline << std::endl;
    }
    
    return Errors;
}

void CheckFlag::CheckMatch(const Symbol &OpSym, const Symbol &ClSym)
{
    if ((OpSym.Token == '(' && ClSym.Token == ')') ||
        (OpSym.Token == '{' && ClSym.Token == '}') ||
        (OpSym.Token == '[' && ClSym.Token == ']')
        )
    {
        std::cout
        << "Found open flag: " << OpSym.Token << " on line " << OpSym.Theline
        << " close flag: " << ClSym.Token << "on line " << ClSym.Theline 
        << std::endl;
    }
    else
    {
        std::cout << "does not match" << ClSym.Token << "at line" << OpSym.Theline << std::endl;
        Errors++;
    }
}


#endif

第二道题

#ifndef ListDemo_Evaluator_h
#define ListDemo_Evaluator_h

#include "List.h"
#include 

class EvalValue
{
public:
    int         value;
    int         opType;
public:
    EvalValue(int v, int o):value(v),opType(o){}
};

class Evaluator
{
private:
    Stack      *OpStack;               //操作符
    Stack      *PostFixStack;          //数值
    
    enum {
        UNKNOW = 100,       //  未知
        OPAREN,             //  (
        CPAREN,             //  )
        EXP,                //  ^
        MULT,               //  *
        DIV,                //  /
        PLUS,               //  +
        MINUS,              //  -
    };
    string          *sEval;
    
private:
    int GetCharOp(char Ch);
    bool IsDigit(char Ch);
    int Digit(char Ch);
    void CheckOp(int op);
    
    void openFlagEval();                        //括号处理
    void orderOpEval(int op);                   //优先级处理
    bool checkOpOrder(int TopOp, int op);       //比较优先级
    void EvalResult();                          //计算结果
    string getOpString(int op);                 //得到运算符的字符串
    int CacluateWithValue(int op, int v1, int v2);      //计算

public:
    Evaluator(const char *strEval);
    virtual ~Evaluator()    { delete sEval; delete OpStack; delete PostFixStack; }
    
public:
    void Convert();
    string Original();
    string Converted();
    int Caculator();
};

Evaluator::Evaluator(const char *strEval)
{
    sEval = new string(strEval);
    OpStack = new Stack;
    PostFixStack = new Stack;
}

void Evaluator::Convert()
{
    int value = 0;
    for (int i = 0; i < sEval->size(); i++)
    {
        char Ch = (*sEval)[i];
        if (this->IsDigit(Ch))
        {
            value = value * 10 + this->Digit(Ch);
            
        }
        else
        {
            if (value != 0)
            {
                PostFixStack->push(EvalValue(value, 0));
            }
            if (Ch == ' ')
            {
                value = 0;
                continue;
            }
            int type = this->GetCharOp(Ch);
            if ( type != UNKNOW)
            {
                this->CheckOp(type);
            }
            else
            {
                cout << "error" << endl;
                return;
            }
            value = 0;
        }
    }
    if (value != 0)
    {
        PostFixStack->push(EvalValue(value, 0));
    }
    this->EvalResult();
}

string Evaluator::Original()
{
    return *sEval;
}

string Evaluator::Converted()
{
    Stack *tmp = new Stack();
    while (! PostFixStack->isEmpty() )
    {
        tmp->push(PostFixStack->pop()) ;
    }
    while (! tmp->isEmpty() )
    {
        EvalValue eva = tmp->pop();
        if (eva.opType != 0)
        {
            cout << this->getOpString(eva.opType) << " ";
        }
        else
        {
            cout << eva.value << " ";
        }
    }
    delete tmp;
    cout << endl;
    return string("");
}

int Evaluator::Caculator()
{
    Stack *reveral = new Stack();
    while (! PostFixStack->isEmpty() )
    {
        reveral->push(PostFixStack->pop()) ;
    }
    Stack *tmp = new Stack();
    
    while (! reveral->isEmpty() )
    {
        EvalValue eva = reveral->pop();
        if (eva.opType != 0)
        {
//            cout << this->getOpString(eva.opType) << " ";
            int value1 = tmp->pop().value;
            int value2 = tmp->pop().value;
            int Vtmp = this->CacluateWithValue(eva.opType, value1, value2);
            tmp->push(EvalValue(Vtmp, 0));
        }
        else
        {
//            cout << eva.value << " ";
            tmp->push(eva);
        }
    }
    EvalValue eva = tmp->pop();
    delete tmp;
    delete reveral;
    
    return eva.value;
}


int Evaluator::GetCharOp(char Ch)
{
    switch (Ch) {
        case '(':   return OPAREN;
        case ')':   return CPAREN;
        case '^':   return EXP;
        case '*':   return MULT;
        case '/':   return DIV;
        case '+':   return PLUS;
        case '-':   return MINUS;
        default:    return UNKNOW;
    }
}

bool Evaluator::IsDigit(char Ch)
{
    if (Ch >= '0' && Ch <= '9')
    {
        return true;
    }
    return false;
}

int Evaluator::Digit(char Ch)
{
    return Ch - '0';
}

void Evaluator::CheckOp(int op)
{
    switch (op) {
        case OPAREN:
            OpStack->push(EvalValue(0, op));
            break;
        case CPAREN:
            //出栈计算
            this->openFlagEval();
            break;
        case EXP:
        case MULT:
        case DIV:
        case PLUS:
        case MINUS:
            //优先级
            this->orderOpEval(op);
            break;
            
        default:
            break;
    }
}

void Evaluator::openFlagEval()
{
    EvalValue ev = OpStack->pop();
    while (ev.opType != OPAREN)
    {
        PostFixStack->push(ev);
        ev = OpStack->pop();
    }
}

void Evaluator::orderOpEval(int op)
{
    if (!OpStack->isEmpty())
    {
        EvalValue ev = OpStack->top();
        //栈顶优先级高
        while (this->checkOpOrder(ev.opType, op))
        {
            PostFixStack->push(OpStack->pop());
        }
        
    }
    OpStack->push(EvalValue(0, op));
}

bool Evaluator::checkOpOrder(int TopOp, int op)
{
    if (TopOp < op)
    {
        if (TopOp == EXP ||                     // ^悠闲级高
            (TopOp == MULT && op < DIV))        // * / 大于 + - 优先级
        {
            return true;
        }
    }
    return false;
}

void Evaluator::EvalResult()
{
    while (!OpStack->isEmpty())
    {
        PostFixStack->push(OpStack->pop());
    }
}

string Evaluator::getOpString(int op)
{
    switch (op) {
        case OPAREN:    return "(";
        case CPAREN:    return ")";
        case EXP:       return "^";
        case MULT:      return "*";
        case DIV:       return "/";
        case PLUS:      return "+";
        case MINUS:     return "-";
        default:
            break;
    }
    return "[error]";
}

#include 

int Evaluator::CacluateWithValue(int op, int v1, int v2)
{
    switch (op) {
        case EXP:   return pow(v2, v1);
        case MULT:  return v2 * v1;
        case DIV:   return v2 / v1;
        case PLUS:  return v2 + v1;
        case MINUS: return v2 - v1;
            
        default:
            break;
    }
    return 0;
}

#endif



你可能感兴趣的:(数据结构和算法,c/c++)