在C ++中解决算术表达式的另一种方法? [英] Another way of solving arithmetic expressions in C++?

查看:47
本文介绍了在C ++中解决算术表达式的另一种方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

免责声明:如果这是太长时间阅读,那么有一个TL; DR在底部。



Hello和wassup对任何人都在读这个。最近我接受了一次面试,他们让我做了一个带回家的编码工作,这是为了编写一个程序,用面向对象的方式解决使用C ++的算术表达式,不使用分流码算法。所以我能够编写程序,当我弄清楚时,我被抽了出来,我的程序解决了诸如(-100.5 + 2 + 1 +(250/40 + 4)+100)-10 = 2.75之类的问题。不幸的是他们不喜欢它,并决定追求其他候选人,起初我就像F ******* K,但后来我就像是好的一切。但是,我真的很想知道他们在寻找什么。我可以采取什么其他方法? 这是显示我做了什么的片段:



括号:

DISCLAIMER: IF THIS IS TOO LONG TO READ THEN THERE'S A TL;DR AT THE BOTTOM.

Hello and wassup to whoever's reading this. Recently I had a job interview where they made me do a take home coding assignment, which was to write a program that solves arithmetic expressions using C++ in an object-oriented fashion that doesn't use the shunting yard algorithm. So I was able to write the program and I was pumped when I figured it out, my program solved problems such as (-100.5+2+1+(250/40+4)+100)-10 = 2.75. Unfortunately they didn't like it and decided to pursue other candidates, which at first I was like "F*******K" but then I was like whatever it's all good. However, I am really curious to see what they were looking for. What other approach could I have taken? Here's the snippet that shows what I did:

For Parentheses:

// Private helper method for computing values in parantheses.
void parenthesesHelper(int index) {
   double value = 0;
   for(size_t i = index; i < formula.size() - index; i++) {
      string singleVal = formula[i];
      if (singleVal[0] == '(') {
         int count = 0;
         int j = i + 1;
         string parFinder = formula[j];
         string problem = "";
         // Recursively computes multiple parentheses
         while (parFinder[0] != ')') {
            if(parFinder[0] == '(') {
               parenthesesHelper(j);
            }
            problem = problem + formula[j];
            count++;
            j++;
            parFinder = formula[j];
         }
         if (count > 3) {
            Calculator calc;
            calc.enterExpression(problem);
            calc.parentheses();
            calc.exponent();
            calc.multiplyOrDiv();
            calc.additionOrSub();
            formula.erase(formula.begin() + i);
            for(size_t k = 0; k < (size_t)count; k++) {
               formula.erase(formula.begin() + i);
            }
            formula.erase(formula.begin() + i);
            string valString = numToString(calc.getTotal());
            formula.insert(formula.begin() + i, valString);
         } else {
            string op = formula[i + 2];
            string left = formula[i + 1];
            string right = formula[i + 3];
            double operandL = stringToNum(left);
            double operandR = stringToNum(right);
            if (op[0] ==  '^') {
               value = 1;
               for (int j = 0; j < operandR; j++) {;
                  value *= operandL;
               }
            } else if (op[0] == '*') {
               value = operandL * operandR;
            } else if (op[0] == '/') {
               value = operandL / operandR;
            } else if (op[0] == '+') {
               value = operandL + operandR;
            } else if (op[0] == '-' && op.length() == 1) {
               value = operandL - operandR;
            }
            string valString = numToString(value);
            formula.erase(formula.begin() + i);
            formula.erase(formula.begin() + i);
            formula.erase(formula.begin() + i);
            formula.erase(formula.begin() + i);
            formula.erase(formula.begin() + i);
            formula.insert(formula.begin() + i, valString);
         }
      }
   }
}





对于其他运营商:



For other operators:

void solve(int exponent, int multOrDiv, int addOrSub) {
   double value = 0;
   for(size_t i = 0; i < formula.size(); i++) {
      string s = formula[i];
      // Ensures no other operator except the current one is being evaluated.
      if ((operators.count(s[0]) && (s[0] == '^') && exponent) ||
      (operators.count(s[0]) && (s[0] == '*' || s[0] == '/') && multOrDiv) ||
      (operators.count(s[0]) && (s[0] == '+' || (s[0] == '-' && s.length() == 1)) && addOrSub)) {
         string left = formula[i - 1];
         string right = formula[i + 1];
         double operandL = stringToNum(left);
         double operandR = stringToNum(right);
         if (exponent) {
            if (s[0] == '^') {
               value = 1;
               for (int j = 0; j < operandR; j++) {
                  value *= operandL;
               }
            }
         } else if (multOrDiv) {
            if (s[0] == '*') {
               value = operandL * operandR;
            } else if (s[0] == '/') {
               value = operandL / operandR;
            }
         } else if (addOrSub) {
            if (s[0] == '+') {
               value = operandL + operandR;
            } else if (s[0] == '-' && s.length() == 1) {
               value = operandL - operandR;
            }
         }
         string valString = numToString(value);
         formula.erase(formula.begin() + i - 1);
         formula.erase(formula.begin() + i - 1);
         formula.erase(formula.begin() + i - 1);
         formula.insert(formula.begin() + i - 1, valString);
         i = 0;
      }
   }
}





这两种方法扫描表达式从左到右并根据当前优先考虑的内容来解决表达式。 什么是更好的方法?



这是完整的程序





These two methods sweep through the expression from left to right and solves the expression depending on what is being prioritized at the moment. What would be the better approach?

Here is the full program

/*
 * Calculator
 *
 * This program calculates arithmetic expressions
 * and strictly follows the PEMDAS order of operations.
 * (Note: Assumes the user will input valid expressions)
 *
 */

#include <string>
#include <cstdlib>
#include <vector>
#include <set>
#include <sstream>
#include <iostream>
using namespace std;

class Calculator {

   public:
      // Initializes the Calculator class.
      Calculator() {
		 total = 0.0; 
         operators.insert('(');
         operators.insert(')');
         operators.insert('^');
         operators.insert('*');
         operators.insert('/');
         operators.insert('+');
         operators.insert('-');
      }

      // Passes in a string that represents the arithmetic
      // expression to be solved. The expression can contain
      // spaces, and assumes that the arithmetic expression is valid.
      void enterExpression(string problem) {
         // Gets rid of spaces within the expression.
         for(size_t i = 0; i < problem.length(); i++) {
            char space = problem[i];
			if (space != ' ') {	
               string s(1, problem[i]);
               expression += s;
            }
         }

         // Strings together values larger than 9 (more than one digit)
         for(size_t i = 0; i < expression.size(); i++) {
            string bigDigit = "";
            if ((expression[i] <= '9' && expression[i] >= '0') ||
               expression[i] == '.' || (expression[i] == '-' && i == 0) ) { 
               while((expression[i] <= '9' && expression[i] >= '0') ||
               expression[i] == '.' || (expression[i] == '-' && i == 0) ) {
                  string temp(1, expression[i]);
                  bigDigit = bigDigit + temp;
                  i++;
               }
               formula.push_back(bigDigit);
            } 
            string temp(1, expression[i]);
            formula.push_back(temp);
         }
      }

      // Solves expressions that contain parantheses.
      void parentheses() {
         if (formula.size() > 2) {
            parenthesesHelper(0);
            if(numCheck()) {
               total = stringToNum(formula[0]);
            }
         }
      }

      // Solves expressions that contain exponents.
      void exponent() {
         if (formula.size() > 2) {
            solve(1, 0, 0);
            if (numCheck()) {
               total = stringToNum(formula[0]);
            }
         }
      }

      // Solves expressions that contain either multiplication or division (or both).
      void multiplyOrDiv() {
         if (formula.size() > 2) {
            solve(0, 1, 0);
            if(numCheck()) {
               total = stringToNum(formula[0]);
            }
         }
      }

      // Solves expressions that contain either addition or subtraction (or both).
      void additionOrSub() {
         if (formula.size() > 2) {
            solve(0, 0, 1);
            double val = stringToNum(formula[0]);
            if(numCheck() || (formula.size() <= 2 && val < 0)) {
               total = stringToNum(formula[0]);
            }
         }
      }

      // Displays the content of the current expression being solved.
      void display() {
         for(size_t i = 0; i < formula.size(); i++) {
            string s = formula[i];
            cout << "" << s;
         }
         cout << endl;
      }

      // Passes in a string and returns the decimal representation of it.
      double stringToNum(string s) {
         double val = 0.0;
         stringstream(s) >> val;
         return val;
      }

      // Passes in a number and returns the string representation of it.
      string numToString(double val) {
         ostringstream strs;
         strs <<





TL; DR :我只想知道他们如何在面向对象的时尚中解决C ++中的算术表达式而不使用SHUNTING YARD算法,并且对C ++代码也提出了提示,这样我就能获得更好的效果。



我尝试了什么:



我绝对知道我没有编写好的代码,所以我可以看出为什么他们做出了他们做出的决定。我本可以清理代码,删除一些冗余(比如以某种方式结合使用solve方法和括号方法),并编写一个方法来检查表达式是否有效但我是在时间限制,他们告诉我对他们来说唯一重要的是这种方法(他们不喜欢哈哈)。 同样,更好的方法是什么?此外,我欢迎所有对我的编码的批评,因为我知道我可以编写一些s ***代码,我正在尝试清理它。



TL;DR: I JUST WANT to KNOW HOW ELSE to SOLVE ARITHMETIC EXPRESSIONS in C++ in an OBJECT-ORIENTED FASHION WITHOUT USING the SHUNTING YARD ALGORITHM and WOULD ALSO LIKE TIPS on C++ CODE SO I CAN GET BETTER.

What I have tried:

I definitely know that I didn't write good code so I can see why they made the decision that they made. I could have cleaned up the code, removed some redundancy (such as somehow combining the solve method and the parentheses method), and write a method that checks to see if the expression is valid but I was on a time constraint and they told me that the only thing that mattered to them was the approach (which they didn't like haha). Again, what would be the better approach? Also, I welcome all criticisms on my coding as well because I know I can write some s*** code and I am trying to clean it up.

推荐答案

实现的主要缺陷可能是它不是面向对象的。操作员扫描 对象。



所以一个左括号应该创建一个子计算,这个结果是父计算的输入。



示例=(2 + 3)* 4



应在内部扫描到:

计算((计算(2,加,3) ,Multiply,4); // Add und Multiply应该是工厂函数或构造函数检测到的枚举。(我不喜欢复杂的ctors因为错误处理问题)



PS:编码员得到这份工作的决定主要是取决于工资或一些为个人感受提供空间的软技能。
The main flaw of your implementation may be that it isnt very object oriented. And the operator scan should in the object.

So an opening parenthesis should create a subcalculation and this results is input for the parent calculation.

Example = ( 2 + 3 ) * 4

should be internally scanned to:
Calculation( (Calculation(2, Add,3), Multiply, 4 );// Add und Multiply should be enums which the "factory function" or constructor detects. (I dont like sophisticated ctors because error handling problems)

PS: decision which coder gets the job is mostly depending on the salary or some "soft skills" which provides room for the personal feelings.


这篇关于在C ++中解决算术表达式的另一种方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆