1,105,633 Community Members

DEV-C++ equation solver

Question Answered as of 2 Years Ago by raptr_dflo, pseudorandom21, sergent and 3 others
Member Avatar
thecoolman5
Posting Whiz in Training
245 posts since Dec 2010
Reputation Points: 8 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

oh, forgive me but i found the problem. i replaced operators on line 74 with operators2 and it works fine now.

Member Avatar
raptr_dflo
Practically a Master Poster
604 posts since Aug 2010
Reputation Points: 48 [?]
Q&As Helped to Solve: 83 [?]
Skill Endorsements: 1 [?]
 
0
 

Hey thecoolman5, don't worry if my code-block doesn't make sense yet, just go back and look at it once in a while. It's a good beginning to your question about "what if the user doesn't type in spaces?" but isn't necessary at this point. And what you'd do with it, as far as solving the equation, is similar to what you're already doing. With the added benefit that you've already determined whether each item is a number, a variable, or an operator, so you can detect whether the user typed in something that doesn't make sense.

Let me know if you get stuck on something else.

Member Avatar
thecoolman5
Posting Whiz in Training
245 posts since Dec 2010
Reputation Points: 8 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

Ok. I just need to know how to operators, operators2, and operators3 to detect '^'. also I need it to be able to detect any other variable than just x.

If(n1 == string)
{
      // the rest of the code
Member Avatar
raptr_dflo
Practically a Master Poster
604 posts since Aug 2010
Reputation Points: 48 [?]
Q&As Helped to Solve: 83 [?]
Skill Endorsements: 1 [?]
 
0
 

Detecting '^' is no different from checking for any other operator. The problem you're more likely to be running into now is implicit operator precedence. In the simplest case, if the user types in "3 + 5 * 2 = x", you need to make sure that you're doing the "5 * 2" part before the "3 +" part. Same for '^', that will have to come before "*/" or "+-".

As far as detecting more variables than "just x" ... if you want the user to be able to use "y" instead, then it might be as simple as "if it's not a number or an operator, then replace it with x" and continue as you do now. If you want to remember that it used to be y, save it in a separate variable, and replace it when you print out the result:

string actual_var = "";
    if ((strtream(n2) >> n2_val).fail()) {
        actual_var = n2;
        n2 = "x";
    }

    // do rest of equation solving here

    if (actual_var != "") {
        cout << actual_var << " = " << answer;
    }
    else {
        cout << "answer = " << answer;
    }

If instead you want the user to be able to input something like "y = 3 * x + 5", that's a whole other level of code management, and you're not approaching the problem in a sufficiently scalable manner -- what are you going to do when you're ready to read something like "z = x ^ 2 + y ^ 2 - 2 * x * y"? If you keep going the way you have been, you'll have hundreds, or possibly thousands of lines of almost-unmaintainable code. You really need to start appreciating a topic called "data structures" and also working with your equations at a more abstract level.

Member Avatar
thecoolman5
Posting Whiz in Training
245 posts since Dec 2010
Reputation Points: 8 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

Yeah. I know what you mean. I just know too little of the c++ language. Plus, I taught it to myself. Back on the 1st page, you said "recursive descent parser". Do you happen to have a recursive descent parser code? Or do you think you could post a data structure code snippet that I might understand? Thanks.

Member Avatar
raptr_dflo
Practically a Master Poster
604 posts since Aug 2010
Reputation Points: 48 [?]
Q&As Helped to Solve: 83 [?]
Skill Endorsements: 1 [?]
 
0
 

No, I don't have anything already written, I'm pretty sure I made that point as well. :) As far as data structures, I'd recommend grabbing a book. I bet there's a decent "Data Structures in C++" book on the shelves of your local book store, or they'd be able to point you to another store to try.

Rather than trying to come up with code that you can understand, which solves your problem, I'd prefer that you actually take a bit of a break (if you need) and learn more about programming in general ... then when you go back to reading specifically about "recursive descent parsers", it'll make more sense to you, and you'll have a much better idea how to approach the problem code-wise.

Not that it helps much now, but you can think of your equations in a hierarchical sense:
+ an equation is made up of expressions on either side of an '=' sign (*)
+ an expression is a sequence: operand, operator, operand, ..., operand.
+++ an exception to the above is the unary "negation" operator which doesn't need a preceding operand.
+ operators include +, -, *, /, ^ (others too, i bet)
+ operands can be numeric constants, variables, or other expressions (**)

(*) in fact, you can think of the entire equation as a single expression, where the "=" (along with "<", ">", etc.) is a "relational operator" -- one that returns true or false instead of a numeric answer

(**) especially useful for incorporating "()" ... "(" denotes the start of a sub-expression, which can be treated exactly like any other expression. also now that an expression can contain sub-expressions, which can in turn contain sub-sub-expressions, you can see where the "recursive" part comes in. The "descent" part comes from working your way through a branching "tree" structure of operands and operators, accumulating partial results in the correct order -- in computer science, trees are represented with the "root" at the top, and the branches growing downward, probably just because its easier to deal with on paper that way. A data structure for a point in the tree might look something like:

struct rdp_node {
    bool is_operator;  // tells whether the "op" or "value" is relevant
    Operator op;
    Value val;
    struct rdp_node *left_operand;
    struct rdp_node *right_operand;
};

typedef struct rdp_node RDPNode;  // Now you can say something like RDPNode *ptr = new RDPNode();

I'm not defining the Operator or Value class/structure yet, the point here is simply that you can have a data structure that can "point to" other objects of the same type, in this case left and right sub-expressions, which might be other "operator nodes", or might be "value nodes".

I'm also not writing full-up tree code for you. Functions you would need, in order to make the data structure useful, include "add a node into the tree", "compute the value of this node, taking into account its sub-nodes", "print the expression represented by this tree", "get rid of this tree (and all the nodes in it)", and so on. Of particular interest is "build up a tree from the input expression/equation" which requires no small amount of thought. Try it out on paper -- how would you represent "3 + 2 * 5" using the RDPNode structure above? (Hint: try drawing one node as a box with four rows, the bottom row divided into two columns, one will start an arrow pointing down and to the left, the other will start an arrow pointing down and to the right, each to another box). What goes at the root/top of the tree? What are the "leaf nodes" (those that don't point to any sub-expressions)?)

Member Avatar
thecoolman5
Posting Whiz in Training
245 posts since Dec 2010
Reputation Points: 8 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

So about the book. I have c++ for dummies and when I came up with the idea to make a variable equation solver, I looked around my house for about an hour and I still can't find it.

Member Avatar
raptr_dflo
Practically a Master Poster
604 posts since Aug 2010
Reputation Points: 48 [?]
Q&As Helped to Solve: 83 [?]
Skill Endorsements: 1 [?]
 
0
 

various input on books here: http://stackoverflow.com/questions/366317/good-data-structures-text-book. I can vouch for Aho, Hopcroft, Ullman -- but like other commenters, it was my college text over 20 years ago. And definitely -not- C++-specific. The good news is, data structures are virtually identical in every programming language, so the primary purpose is to understand the structures, how and when to use them, and what's involved in a complete and correct implementation, regardless of the programming language of choice. Also from the top of this C++ forum: http://www.daniweb.com/software-development/cpp/threads/70096

Member Avatar
thecoolman5
Posting Whiz in Training
245 posts since Dec 2010
Reputation Points: 8 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

Hey, Im wondering if you know how to detect a char in a string.

Member Avatar
sfuo
Master Poster
713 posts since Jul 2009
Reputation Points: 109 [?]
Q&As Helped to Solve: 111 [?]
Skill Endorsements: 0 [?]
 
0
 

You should really start a new thread for new questions since this is a really old thread.

To find a char in a string you can use the find() member of the string class and get the index of it.

example:

#include <iostream>
#include <string>
using namespace std;

int main()
{
	string eqn = "x + 2 + 2 = 3";
	int pos = -1;
	char toFind = '+';
	do //this loop will find all occurrences of the char to you want to find
	{
		pos = eqn.find(toFind, pos+1);
		if( pos != -1 ) //if the char was found
			cout << toFind << " was found at " << pos << endl;
	}while( pos != -1 ); //end loop if char wasn't found

	return 0;
}
Member Avatar
thecoolman5
Posting Whiz in Training
245 posts since Dec 2010
Reputation Points: 8 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

Ok, thanks dude.

Member Avatar
thecoolman5
Posting Whiz in Training
245 posts since Dec 2010
Reputation Points: 8 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

i am also wondering how to retrieve all the numbers in an equation.

cin >> equation //equation is 1-3/7*3
cout << numbers << endl; //output is 1,3,7, and 3
Member Avatar
sfuo
Master Poster
713 posts since Jul 2009
Reputation Points: 109 [?]
Q&As Helped to Solve: 111 [?]
Skill Endorsements: 0 [?]
 
0
 

Here is something I threw together pretty quick.

This breaks down the input into separate strings of numbers and operators.

You can use atoi() (string to int) to convert the number of string type to an integer.

This is pretty basic so you will want to add to it if you want variables and other things.

#include <iostream>
#include <string>
#include <vector>
using namespace std;

int main()
{
	vector<string> eqnParts;
	string eqn, part = "";
	cout << "Please input your equation: ";
	getline(cin, eqn);

	for( unsigned int i = 0; i < eqn.length(); i++ )
	{
		if( eqn[i] == '+' || eqn[i] == '-' || eqn[i] == '*' || eqn[i] == '/' )
		{
			eqnParts.push_back(part);
			part = eqn[i];
			eqnParts.push_back(part);
			part = "";
		}
		else
		{
			part += eqn[i];
			if( i == eqn.length()-1 )
				eqnParts.push_back(part);
		}
	}

	for( unsigned int i = 0; i < eqnParts.size(); i++ )
		cout << eqnParts[i] << endl;

	return 0;
}
Member Avatar
thecoolman5
Posting Whiz in Training
245 posts since Dec 2010
Reputation Points: 8 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

here, take a look at my new thread. its related to this one. http://www.daniweb.com/software-development/cpp/threads/370974

Member Avatar
thecoolman5
Posting Whiz in Training
245 posts since Dec 2010
Reputation Points: 8 [?]
Q&As Helped to Solve: 1 [?]
Skill Endorsements: 0 [?]
 
0
 

ok guys. I finally finished a full working calculator that can handle parantehsis, order of operations, and unlimited operators.

#include<iostream>
#include<string>
#include<sstream>
#include<windows.h>
#include<conio.h>
#include<ctime>
using namespace std;
int main ()
{
    cout << "No variables." << endl;
    cout << "Type in cls to clear the screen, and type exit to exit." << endl;
    SetConsoleTitle("Calculator");
    for(;;)
    {
    re:
    string equation = "";
    string equation2 = "";
    string equation3 = "";
    string equation4 = "";
    string equation5 = "";
    int non_digit5 = 0;
    int non_digit2 = -1;
    int non_digit6 = 0;
    int c = 0;
    int i = 0;
    float n1 = 0;
    string operators = "";
    float n2 = 0;
    cin >> equation;
    DWORD ticks = GetTickCount();
    if(equation == "exit")
    {
                return 0;
    }
    
    if(equation == "cls")
    {
                system("cls");
                goto re;
    }
    while(true)
    {
               c = equation.find('(', c);
               if(c == -1)
               {
                    break;
               }
    //PARENTHESIS SOLVING CODE
    do
    {
                  non_digit2 = equation.find('(', non_digit2+1);
                  if(non_digit2 == -1)
                  {
                        break;
                  }
                  non_digit5 = non_digit2;
    }while(non_digit2 != -1);
    non_digit5 = non_digit5 + 1;
    int non_digit3 = 0;
    //DOUBLE PARANTHESIS EQUATIONS
    equation4 = equation.substr(non_digit5, 999999999);
    int l = equation.length();
    int l1 = equation4.length();
    non_digit3 = equation4.find(")", non_digit3+1);
    l1 = l1 - non_digit3;
    l = l - l1;
    non_digit3 = l;
    equation3 = equation.substr(non_digit3+1, 999999999);
    equation2 = equation.substr(non_digit5, non_digit3);
    do
    {
                  non_digit2 = equation2.find(')', non_digit2+1);
                  if(non_digit2 == -1)
                  {
                        break;
                  }
                  non_digit6 = non_digit2;
    }while(non_digit2 != -1);
    equation2 = equation2.substr(0, non_digit6);
    equation = equation.substr(0, non_digit5-1);
    n1 = 0;
    operators = "";
    n2 = 0;
    int non_digit = equation2.find_first_not_of("12345677890.");
    string part = equation2.substr(0, non_digit);
    stringstream(part) >> n1;
    operators = equation2[non_digit];
    equation2 = equation2.substr(non_digit + 1);
    while(true)
    {
             n2 = 0;
             non_digit = equation2.find_first_not_of("1234567890.");
             part = equation2.substr (0, non_digit);
             stringstream(part) >> n2;
             if(int(non_digit) == 0)
             {
                               string part = equation2.substr (0, non_digit+3);
                               stringstream(part) >> n2;
                               equation2 = equation2.substr(non_digit + 1);
             }
        if(operators == "+")
        {
                     n1 = n1 + n2;   
        }      
        
        if(operators == "-")
        {
                     n1 = n1 - n2;
        }
        
        if(operators == "*")
        {
                     n1 = n1 * n2; 
        }
        
        if(operators == "/")
        {
                     n1 = n1 / n2;
        }
        
        if(non_digit == -1)
        {
                           break;
        }
        non_digit = equation2.find_first_not_of("0123456789.");
        operators = equation2[non_digit];
        equation2 = equation2.substr(non_digit + 1);
    }
        stringstream out;
        out << n1;
        equation = equation + out.str();
        equation = equation + equation3;
    }
    //ORDER OF OPERATIONS
    while(true)
    {
               c = equation.find_first_not_of("1234567890.-+");
               if(c == -1)
               {
                    break;
               } 
    equation2 = "";
    equation3 = "";
    equation4 = "";
    operators = "";
    float n1 = 0;
    float n2 = 0;
    float n3 = 0;
    int non_digit = equation.find_first_not_of("1234567890.-+");
    operators = equation[non_digit];
    equation2 = equation.substr(non_digit+1, 999999999);
    stringstream(equation2) >> n1;
    equation3 = equation.substr(0,non_digit);
    reverse(equation3.begin(), equation3.end());
    //BEGIN FIXING REVERSED EQUATION
    non_digit = equation3.find_first_not_of("1234567890.");
    if(non_digit == -1)
    {
                 reverse(equation3.begin(), equation3.end());
                 stringstream(equation3) >> n2;
    }
    else
    {
                 equation5 = equation3.substr(0, non_digit);
                 reverse(equation5.begin(), equation5.end());
                 stringstream(equation5) >> n2;
    }
    
    stringstream out;
    out << n2;
    equation4 = equation4 + out.str();
    equation4 = equation4 + operators;
    stringstream out1;
    out1 << n1;
    equation4 = equation4 + out1.str();
    //END OF FIND OPERATOR
    int l = equation4.length();
    non_digit = equation.find(equation4);
    equation2 = equation.substr(0, non_digit);
    equation4 = equation.substr(non_digit+l, 999999999);
    if(operators == "/")
    {
                 n3 = n2 / n1;
    }
    if(operators == "*")
    {
                 n3 = n2 * n1;
    }
    stringstream out2;
    out2 << n3;
    equation2 = equation2 + out2.str();
    equation2 = equation2 + equation4;
    equation = equation2;
    }
    //START FIXED EQUATION SOLVING
    n1 = 0;
    operators = "";
    n2 = 0;
    size_t non_digit = equation.find_first_not_of("12345677890.");
    string part = equation.substr (0, non_digit);
    stringstream(part) >> n1;
    operators = equation[non_digit];
    equation = equation.substr(non_digit + 1);
    while (true)
    {
             n2 = 0;
             size_t non_digit = equation.find_first_not_of("1234567890.");
             string part = equation.substr (0, non_digit);
             stringstream(part) >> n2;
             if(int(non_digit) == 0)
             {
                               string part = equation.substr (0, non_digit+3);
                               stringstream(part) >> n2;
                               equation = equation.substr(non_digit + 1);
             }
        if(operators == "+")
        {
                     n1 = n1 + n2;   
        }      
        
        if(operators == "-")
        {
                     n1 = n1 - n2;
        }
        
        if(operators == "*")
        {
                     n1 = n1 * n2; 
        }
        
        if(operators == "/")
        {
                     n1 = n1 / n2;
        }
        
        if (int(non_digit) == -1)
        {
                           break;
        }
        
        non_digit = equation.find_first_not_of("0123456789.");
        operators = equation[non_digit];
        equation = equation.substr(non_digit + 1);
    }
    cout << "Speed of calculation: " << GetTickCount() - ticks << " milliseconds." << endl;
    cout << "Result : " << n1 << endl;
    system("pause");
    goto re;
    }
}

Please dont edit the code in any way. This calculator is very special to me. its the first advanced program that i have coded. Thanks for all your help.

Member Avatar
eddiecrosby
Newbie Poster
5 posts since Jan 2012
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

Let me just warn you that I am a beginner in early C + +. So I searched recursive descent parser and I know idea how to put this into code.

You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
View similar articles that have also been tagged: