簡體   English   中英

計算器 c++ 已解決

[英]Calculator c++ Solved

我的任務是創建一個后綴計算器,但問題是我無法將 Token 與任何東西進行比較。 我知道評估后修復的偽代碼是這個,我試圖基於它來做我的程序:

從制作文件:

測試: build/infix_calculator build/postfix_calculator build/tokenize

./build/tokenize "2 3 4 + *"

./build/postfix_calculator "2 3 4 + *"

./build/tokenize "2 * (3 + 4)"

./build/infix_calculator "2 * (3 + 4)"


for ( each character ch in the string) 
{ 
if (ch is an operand) 
Push the value of the operand ch onto the stack
else // ch is an operator named op
 { 
// Evaluate and push the result 
 operand2 = top of stack
Pop the stack
 operand1 = top of stack
Pop the stack
 result = operand1 op operand2 
Push result onto the stack
 } 
} 

任何反饋表示贊賞

以下是在線 gdb 的鏈接,可以親自查看:

https://onlinegdb.com/BkIkaPzBO

錯誤:src/PostfixCalculator.cpp:15:19:錯誤:'operator>=' 不匹配(操作數類型為 '__gnu_cxx::__alloc_traitsstd::allocator<Token >::value_type {aka Token}' 和 'char') if (tokens[i] >= '0' && tokens[i] <= '9' ){

src/PostfixCalculator.cpp:15:39: error: no match for 'operator<=' (operand types are '__gnu_cxx::__alloc_traitsstd::allocator<Token >::value_type {aka Token}' and 'char') if (令牌[i] >= '0' && 令牌[i] <= '9' ){

src/PostfixCalculator.cpp:16:24: error: no match for 'operator-' (操作數類型是 '__gnu_cxx::__alloc_traitsstd::allocator<Token >::value_type {aka Token}' 和 'char') s.push (令牌[i] - '0');



/**
 * @file PostfixCalculator.cpp
 */
 #include "PostfixCalculator.h"
 #include<stack>
 #include<iostream>
 #include<stack>
 #include<string>


double PostfixCalculator::eval(std::vector<Token> tokens) {
  std::stack<double>s;

  for (unsigned int i = 0; i < tokens.size(); i++){
    if (tokens[i] >= '0' && tokens[i] <= '9' ){
      s.push(tokens[i] - '0');
    }
  }

  return 0;
}

/**
 * @file PostfixCalculator.h
 */
#ifndef POSTFIX_CALCULATOR_H
#define POSTFIX_CALCULATOR_H

#include<vector>

#include "EvalInterface.h"

class PostfixCalculator : public EvalInterface<double>
{
public:
    double eval(std::vector<Token> expr);
};

#endif


/**
 * @file Token.h
 */
#ifndef TOKEN_H
#define TOKEN_H
#include <iostream>

/**
 * Tag represents a categories of token types
 */
enum Tag { OPERATOR, OPERAND, LPAREN, RPAREN };

/**
 * @brief Operator represents types of binary operations
 */
enum Operator { ADD, SUBTRACT, MULTIPLY, DIVIDE };

/**
 * @brief A data structure to represent a token parsed from a string.
 */
struct Token {
    /** a numeric value -- only valid if the tag is OPERAND */
    double d;
    /** an operator type -- only valid if the tag is OPERATOR */
    Operator o;
    /** the category of the token */
    Tag tag;
};

/**
 * @brief convert an Operator to a std::string
 * @param o the operator
 * @return a string representation of the operator
 */
std::string opToString(Operator o);

/**
 * @brief An overloaded stream insertion operator for the Token type.
 * @param os the output stream object
 * @param t the Token to be inserted into the stream
 * @return the same ostream that was passed in
 */
std::ostream& operator<<(std::ostream& os, const Token& t);

/**
 * @brief parse a string representing a simple arithmetic expression
 * into sequence of tokens.
 * @param s the string to parse
 * @return the result of parsing the string into tokens
 */
std::vector<Token> tokenize(std::string s);

#endif




/**
 * @file Token.cpp
 */
#include <sstream>
#include <string>
#include <vector>
#include <stdexcept>
#include "Token.h"

std::string opToString(Operator o) {
    std::string result;
    switch(o) {
        case ADD:
            result = "ADD";
            break;
        case SUBTRACT:
            result = "SUBTRACT";
            break;
        case MULTIPLY:
            result = "MULTIPLY";
            break;
        case DIVIDE:
            result = "DIVIDE";
            break;
    }
    return result;
}

std::ostream& operator<<(std::ostream& os, const Token& t) {
    std::string type;
    switch (t.tag) {
        case OPERATOR:
            os << "OPERATOR: " << opToString(t.o) << std::endl;
            break;
        case OPERAND:
            os << "OPERAND: " << t.d << std::endl;
            break;
        case LPAREN:
            os << "LPAREN" << std::endl;
            break;
        case RPAREN:
            os << "RPAREN" << std::endl;
            break;
        default:
            throw std::logic_error("Invalid token");
            break;
    }
    return os;
}

std::vector<Token> tokenize(std::string s) {
    std::stringstream ss(s);
    std::vector<Token> result; 

    while (ss) {
        Token t;
        if (ss.peek() == ' ') {
            ss.get();
            continue;
        }
        if (isalnum(ss.peek())) {
            ss >> t.d;
            t.tag = OPERAND;
        }
        else {
            char op;
            ss >> op;
            t.d = 0;
            if (op == '(') {
                t.tag = LPAREN;
            }
            else if (op == ')') {
                t.tag = RPAREN;
            }
            else if (op == '*') {
                t.o = MULTIPLY;
                t.tag = OPERATOR;
            }
            else if (op == '/') {
                t.o = DIVIDE;
                t.tag = OPERATOR;
            }
            else if (op == '+') {
                t.o = ADD;
                t.tag = OPERATOR;
            }
            else if (op == '-') {
                t.o = SUBTRACT;
                t.tag = OPERATOR;
            }
            else {
                throw std::logic_error("Invalid token");
            }
        }
        result.push_back(t);
    }
    result.pop_back();
    return result;
}


該錯誤清楚地說明了問題:

PostfixCalculator.cpp: In member function ‘virtual double PostfixCalculator::eval(std::vector<Token>)’: PostfixCalculator.cpp:15:19: error: no match for ‘operator>=’ (operand types are ‘__gnu_cxx::__alloc_traits >::value_type {aka Token}’ and ‘char’)
     if (tokens[i] >= '0' && tokens[i] <= '9' ){
                     PostfixCalculator.cpp:15:39: error: no match for ‘operator<=’ (operand types are ‘__gnu_cxx::__alloc_traits
>::value_type {aka Token}’ and ‘char’)
     if (tokens[i] >= '0' && tokens[i] <= '9' ){
                                         PostfixCalculator.cpp:16:24: error: no match for ‘operator-’ (operand types are ‘__gnu_cxx::__alloc_traits >::value_type {aka Token}’ and ‘char’)
       s.push(tokens[i] - '0');

Token是用戶定義的數據類型,當A的類型為TokenB的類型為char時,編譯器需要知道如何處理表達式A >= B 您可以在 Token class 上定義運算符<==以實現以下目的:

bool Token::operator==(char c) const {
    return (char)d == c;
}

bool Token::operator< (char c) const {
    return (char)d < c;
}

但是,我會要求您通過在doublechar之間進行比較來仔細思考您的實際意思,因為這就是您的代碼似乎正在做的事情

tokens[i] >= '0'

我認為您可能需要重新考慮您的Token class。 從您共享的代碼來看,它似乎是一個字符的包裝器,並附有一些元數據以表示它的屬性。 在您的代碼中,僅僅是使用

if (isalnum(ss.peek())) {
    ss >> t.d;
    t.tag = OPERAND;
}

t.d = 0;

Tokendouble似乎並沒有被用盡其容量和以更高的精度存儲浮點數的實際用途。 所有存儲的都是純數字。

#include <iostream>
#include <cctype>
#include <algorithm>
#include <string>
#include <cstdint>
#include <vector>

struct Token {
    enum class Tag : uint8_t { OPERATOR, OPERAND, LPAREN, RPAREN };
    static constexpr char OPERANDS[] = {'/', '*', '+', '-'};
    explicit Token(char);
    /** a numeric value -- only valid if the tag is OPERAND */
    char unit;
    /** the category of the token */
    Tag tag;
    char operator()() const;
};

Token::Token(char c): unit(c){
    if(std::isdigit(unit)){ //Numbers are for sure operands
        tag = Tag::OPERAND;
    } else if(unit == '('){
        tag = Tag::LPAREN;
    } else if(unit == ')') {
        tag = Tag::RPAREN;
    } else if(std::any_of(std::begin(OPERANDS), std::end(OPERANDS),
        [&](char c){return c == unit;})) {
        tag = Tag::OPERATOR;
        //Then classify what's the operator if required.
    }
}

char Token::operator()() const {
    return unit;
}

int main()
{
    std::vector<Token> tokenVector;
    std::string inp = "935*+";
    for(char c: inp){
        //Weed out whatever Token doesn't support
        if(c != ' ') {
            tokenVector.emplace_back(c);
        }
    }
    for(const auto& token: tokenVector){
        std::cout<<token()<<' ';
    }
    std::cout<<'\n';
}

Output (使用C++17 ):

9 3 5 * + 

這只是一個基於實現與 char 奇偶校驗的問題的簡單示例。

您不應該將該標記轉換為字符。 處理字符是分詞器的工作,它已經完成了它的工作。 停止考慮字符,開始考慮 OPERAND、OPERATOR、LPAREN 和 RPAREN,它們是令牌的種類。

你顯然需要一些類似的東西

for (auto tkn : tokens) {        // was for (unsigned int i = 0; i < tokens.size(); i++){
  if (tkn.Tag == Tag::OPERAND) { //        if (tokens[i] >= '0' && tokens[i] <= '9' ){
    s.push(tkn.d);               //            s.push(tokens[i] - '0');
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM