My program should read input as an integer for the length followed by (sufficiently) parenthesized floats and simple operators and output the value of the expression. For example, if the input were 11 1 + 2 ^ 3 / 4 * 5 - 6
, the result should be equal to (1 + (((2 ^ 3) / 4) * 5)) - 6
, or 5. However, even when I input 5 1 + 2 + 3
, the output is 5 instead of 6. I think this might be because of the many vector assignments, in particular the marked line (I found this while debugging).
My code (sorry if it is not self explanatory):
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
using namespace std;
float op(char op, float x, float y)
{
switch (op)
{
case '+':
{
return x+y;
break;
}
case '-':
{
return x-y;
break;
}
case '*':
{
return x*y;
break;
}
case '/':
{
return x/y;
break;
}
case '^':
{
return pow(x,y);
break;
}
default:
{
cout << "Error: bad input ";
return 0;
}
}
}
float nopars(vector<string> stack, int stackl, vector<char> ops, int opsr)
{
int len = stackl, opsrr = opsr;
vector<string> nstack, nnstack;
vector<char> nops = ops, nnops;
nstack = stack;
while (opsrr != 0)
{
string s1 (1, nops[0]);
for (int i = 0; i < len; i++)
{
if (nstack[i] == s1)
{
for (int j = 0; j < len - 2; j++)
{
nnstack = {};
if (j == i-1)
{
nnstack.push_back(to_string(op(nops[0], stof(nstack[i-1]), stof(nstack[i+1]))));
}
else if (j < i-1)
{
nnstack.push_back(nstack[j]);
}
else if (j > i-1)
{
nnstack.push_back(nstack[j+2]);
}
}
len = len - 2;
nstack = nnstack; //I think this is wrong?
i--;
}
}
nnops = {};
for (int i = 0; i < opsr-1; i++)
{
nnops.push_back(nops[i+1]);
}
opsrr--;
nops = nnops;
}
return stof(nstack[0]);
}
float all(vector<string> stack, int stackl, vector<char> ops, int opsr)
{
int t1 = 0, t2 = 0;
int len = stackl;
int nprs;
vector<string> nstack, nnstack, nstck;
nstack = stack;
while (true)
{
nprs = 0;
for (int i = 0; i < len; i++)
{
if (nstack[i] == "(")
{
nprs = 1;
t1 = i;
}
else if (nstack[i] == ")")
{
nprs = 1;
t2 = i;
nstck = {};
for (int j = t1 + 1; j < t2; j++)
{
nstck.push_back(nstack[j]);
}
for (int j = 0; j < len - t2 + t1; j++)
{
if (j == t1)
{
nnstack.push_back(to_string(nopars(nstck, t2-t1-1, ops, opsr)));
}
else if (j < t1)
{
nnstack.push_back(nstack[j]);
}
else if (j > t1)
{
nnstack.push_back(nstack[j+t2-t1]);
}
}
len = len - t2 + t1;
break;
}
}
if (nprs == 0)
{
break;
}
nstack = nnstack;
}
return nopars(nstack, len, ops, opsr);
}
void calculate()
{
vector<string> stack;
int stackl;
string t;
cin >> stackl;
for (int i = 0; i < stackl; i++)
{
cin >> t;
stack.push_back(t);
}
cout << all(stack, stackl, {'^', '/', '*', '-', '+'}, 5);
}
int main()
{
calculate();
return 0;
}
A binary recurrent LL parser
#include <iostream>
#include <string>
#include <sstream>
#include <functional>
#include <iterator>
#include <cmath>
#include <map>
using namespace std;
using T = float;
map< int, map<std::string, std::function<T(const T&, const T&)> > > m_foo =
{ {1, { { "+", std::plus<T>() }, { "-", std::minus<T>() } } },
{2, { { "*", std::multiplies<T>() }, { "/", std::divides<T>() } } },
{3, { { "^", powf } } } };
T calc_ll(istream_iterator<string>& t, int level) {
if ( !m_foo.contains(level) ) return std::stof(*t++);
auto result = calc_ll(t, level+1);
auto l = m_foo[level];
while ( l.find(*t) != l.end() ) {
auto foo = l.find(*t)->second;
result = foo(result, calc_ll(++t, level+1) );
}
return result;
}
int main()
{
std::stringstream ss(std::string("1 + 2 ^ 3 / 4 * 5 - 6"));
auto t = istream_iterator<string>(ss);
cout << "result : " << calc_ll( t, 1 );
return 0;
}