I'm writing a function parser, which (hopefully) will be able to handle much more complex problems than basic operations. I've just completed the handling of the addition, subtraction, and brackets, but am at a loss of how to implement proper order of operations for multiplication and division. In order to make them work correctly, they must first be put in brackets. ie 2 + 4 * 3 outputs 18 instead of 14, but 2 + (4 * 3) outputs 14.
I've thought of just adding brackets to the function to force order of operations, but that seems more like a band-aid than an actual fix. Heres the code:
Header:
#pragma once
#pragma warning(disable: 4018)
#include <iostream>
#include <string.h>
using namespace std;
class CFunction
{
protected:
string _sFunc;
int _iCursor;
int GetNextValue(int &);
char GetNextOp(int &);
string ToCloseBracket(int &);
public:
bool SetFunc(string);
int Solve(char = 0);
//inline ctor
CFunction(string s): _iCursor(0)
{
int iO(0),iC(0);
for (int i(0); i < strlen(s.c_str()); ++i)
{
if (s[i] == '(')
iO++;
else if (s[i] == ')')
iC++;
}
if (iO != iC)
throw exception ("Bracket Error");
_sFunc = s;
}
~CFunction(void);
};
class cpp file:
#include "Function.h"
CFunction::~CFunction(void)
{
}
int CFunction::GetNextValue(int & i)
{
string sBuffer;
char szFormula[255];
strcpy_s(szFormula, 255, _sFunc.c_str());
bool numStream(false);
for (i = i; i < strlen(szFormula); ++i)
{
if (isdigit(szFormula[i]))
{
//add the digit to the buffer
numStream = true;
sBuffer += szFormula[i];
}
if (numStream && (!isdigit(szFormula[i]) || i == strlen(szFormula) - 1))
{
return atoi(sBuffer.c_str()); //return the buffer, converted to int
}
if (szFormula[i] == '(')
{//solve what's inside brackets first!
string tmp(ToCloseBracket(i));
return CFunction(tmp).Solve();
}
}
//error flag
return -1;
}
string CFunction::ToCloseBracket(int & iIndex)
{
string sBuffer = "";
int iCount(0), iCount2(0);
int iOIndex(iIndex), iCIndex(iIndex + 1);
for (iCIndex; iCIndex < strlen(_sFunc.c_str()); ++iCIndex)
{
if (_sFunc[iCIndex] == '(')
iCount++;
if (_sFunc[iCIndex] == ')' && iCount == 0)
break;
if (_sFunc[iCIndex] == ')')
iCount--;
}
for (iIndex++; iIndex < iCIndex; iIndex++)
sBuffer += _sFunc[iIndex];
return sBuffer;
}
int CFunction::Solve(char var)
{
if (strlen(_sFunc.c_str()) < 1)
throw exception ("Invalid Function");
int i(0),
iTmpVal(0),
iReturn(0);
char op(0);
iReturn = GetNextValue(i);
while (i < strlen(_sFunc.c_str()) - 1)
{
op = GetNextOp(i);
iTmpVal = GetNextValue(i);
switch (op)
{
case '+': iReturn += iTmpVal; break;
case '-': iReturn -= iTmpVal; break;
case '*': iReturn *= iTmpVal; break;
case '/': if (iTmpVal != 0) iReturn /= iTmpVal; else throw exception("Division By Zero"); break;
default: break;
}
}
return iReturn;
}
char CFunction::GetNextOp(int & i)
{
for (i; i < strlen(_sFunc.c_str()); ++i)
if (_sFunc[i] == '+' || _sFunc[i] == '-' || _sFunc[i] == '*' || _sFunc[i] == '/')
return _sFunc[i];
//error flag
return -1;
}
Sample implementation in main()
#include <string>
#include <iostream>
using namespace std;
#include "Function.h"
int main()
{
char szBuffer[255];
string sBuffer = "";
for (int i(0); i < 5; ++i)
{
cin.ignore(cin.rdbuf()->in_avail());
cout << "Enter formula: ";
cin.getline(szBuffer, 254);
sBuffer = szBuffer;
CFunction myFunc(sBuffer);
int ii(0);
try
{
if ((ii = myFunc.Solve()) == -1)
throw exception("Unknown Error");
cout << sBuffer << " = " << ii;
}
catch (exception exc)
{
cout << "Error Encountered while solving for " << sBuffer;
cout << "\nType: " << exc.what();
}
cin.get();
}
return 0;
}
Any pointers in the right direction would be greatly appreciated!