Jump to content
  • Advertisement
Sign in to follow this  
ajm113

How Would You Write A Dynamic Text Input Calculator?

This topic is 2301 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello all, I was wondering how any of you would write a dynamic text input calculator. I.E Lets say you have a single line text input field where the user can type their formula. How would you go about figuring out how to do the correct math calculations from the variables collected in a string?

Lets say the current input field value is "2 + 2"

structure mathStep Vector
enum m_type;
var value;

cLine = removeSpacesInText

For Each Character in cLine Loop

if cLine Character Does Not Equal to any operator.

Add Character to tempString

Else

Convert tempString into correct variable type determining if the string has a period in it.
Then add the variable to the mathStep Vector
After adding it to the to do list then add the operator to the back of the list. Simply by changing the m_type to PLUS and add it to the vector.

End If

End For Loop

If float/double/int use the correct variable type for the result value variable.


For Each Element in mathStep
Add/Subtract/etc to result value
End If

Return Result

I had something like that in mind, I didn't write it in C++ yet, but I've been pondering if there are better ways and variable types to use then adding a bunch of variables in a struct if it's a float or int, a plus, minus, etc in the text we are figuring out what it result is.

Share this post


Link to post
Share on other sites
Advertisement
One solution would be to first tokenize the input line using regular expressions. This would convert the input string "2 + 2" to a token list like { Value(2), Operator(+), Value(2) }. Next, perform a syntactic analysis which identifies and organizes (typically in some tree structure) the elements that need to be evaluated. Continuing with our "2 + 2" example this would create a tree from the token list with 3 nodes constituting a single addition expression: { Addition(Value(2),Value(2)) }. Lastly, evaluate the tree (or more specifically each node in the tree), which in our example would yield something like Value(4).

Share this post


Link to post
Share on other sites
If you can get your hands one Bjarne's "The C++ Programming Language" book, he explains how to create a calculator. The source code can also be found at his site.

Share this post


Link to post
Share on other sites

One solution would be to first tokenize the input line using regular expressions. This would convert the input string "2 + 2" to a token list like { Value(2), Operator(+), Value(2) }. Next, perform a syntactic analysis which identifies and organizes (typically in some tree structure) the elements that need to be evaluated. Continuing with our "2 + 2" example this would create a tree from the token list with 3 nodes constituting a single addition expression: { Addition(Value(2),Value(2)) }. Lastly, evaluate the tree (or more specifically each node in the tree), which in our example would yield something like Value(4).

The tree structure you would want happens to have a name as well

Share this post


Link to post
Share on other sites
A couple of alternatives that haven't been mentioned:

  • There is a well-known algorithm that converts infix notation (what you have) to reverse polish notation. Once you have the expression in RPN, computing the result is trivially achieved using a stack.
  • You can also write your own recursive descent parser for the types of expressions that you expect. I think this is a good exercise to go through at some point.

Share this post


Link to post
Share on other sites
I would second alvaro and suggest rolling a recursive descent parser - there are lots of examples and explanations around, and it is indeed a good fundamental excercise.

Share this post


Link to post
Share on other sites
Here's a recursive descent parser I just hacked together. The hardest part is reporting meaningful errors, which I haven't been careful about:
#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstdlib>

void skip_white_space(char const *&s) {
while (isspace(*s))
++s;
}

double compute_expression(char const *&s);

double compute_non_signed_factor(char const *&s) {
double result;

if (isdigit(*s)) {
int n_characters_read;
std::sscanf(s, "%lg%n", &result, &n_characters_read);
s += n_characters_read;
skip_white_space(s);
}
else if (*s == '(') {
++s;
skip_white_space(s);
result = compute_expression(s);
if (*s != ')') {
std::cerr << "`)' expected\n";
std::exit(1);
}
++s;
skip_white_space(s);
}
else {
std::cerr << "Number or `(' expected\n";
std::exit(1);
}

return result;
}

double compute_factor(char const *&s) {
bool positive = true;

if (*s == '+')
positive = true, ++s, skip_white_space(s);
else if (*s == '-')
positive = false, ++s, skip_white_space(s);

return positive ? compute_non_signed_factor(s) : -compute_non_signed_factor(s);
}

double compute_term(char const *&s) {
double result = 1.0;
bool dividing = false;

while (1) {
result *= dividing ? 1.0 / compute_factor(s) : compute_factor(s);
if (*s == '*')
dividing = false, ++s, skip_white_space(s);
else if (*s == '/')
dividing = true, ++s, skip_white_space(s);
else break;
}

return result;
}

double compute_expression(char const *&s) {
double result = 0.0;
bool subtracting = false;

while (1) {
result += subtracting ? -compute_term(s) : compute_term(s);
if (*s == '+')
subtracting = false, ++s, skip_white_space(s);
else if (*s == '-')
subtracting = true, ++s, skip_white_space(s);
else break;
}

return result;
}

double compute(char const *s) {
skip_white_space(s);
double result = compute_expression(s);
if (*s != '\0') {
std::cerr << "End of line expected\n";
std::exit(1);
}
return result;
}

int main() {
std::cout << compute("2+2") << '\n';
}



EDIT: My code had some issues with unary + and - operators, but I fixed them.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!