Parsing mathematical expression string
Tokenization is the first step towards syntactic analysis. As such, it is probably a good idea to encapsulate it into a layer of abstraction, a function that yields one token at a time. This function also discards white space and combines consecutive digits into numbers. It is hard to delegate these steps to strtok()
. Finally, the function may rewrap single characters into more structured information.
#include <ctype.h>
#include <stdio.h>
#define T_NUMBER 0
#define T_OPERATOR 1
#define T_BRACKET 2
typedef struct {
int type;
int value;
} token;
/* Reads the next token from stdin. Returns 1 on success, 0 on EOL. */
int next_token(token *t) {
char c;
/* discard spaces silently */
do {
c = getchar();
} while (c == ' ');
if (isdigit(c)) {
t->type = T_NUMBER;
t->value = 0;
do {
t->value = t->value * 10 + (c - '0');
c = getchar();
} while (isdigit(c));
ungetc(c, stdin); /* save the non-digit for next time */
} else if (c == '+' || c == '-' || c == '*' || c == '/') {
t->type = T_OPERATOR;
t->value = c;
} else if (c == '(' || c == ')') {
t->type = T_BRACKET;
t->value = c;
} else if (c == '\n') {
ungetc(c, stdin); /* make sure we always return 0 from now on */
return 0;
} else {
/* handle illegal character */
}
return 1;
}
int main() {
token t;
while (next_token(&t)) {
switch (t.type) {
case T_NUMBER: printf("number %d\n", t.value); break;
case T_OPERATOR: printf("operator %c\n", t.value); break;
case T_BRACKET: printf("bracket %c\n", t.value); break;
}
}
return 0;
}
Sample run:
(22+ 37 * ( 1534-9)) + 18
bracket (
number 22
operator +
number 37
operator *
bracket (
number 1534
operator -
number 9
bracket )
bracket )
operator +
number 18
parsing math expression in c++
Use the Shunting-yard algorithm. The wikipedia description is quite comprehensive, I hope it will suffice.
You can also try to write a formal grammar, for example a parsing-expression grammar, and use a tool to generate a parser. This site about PEGs lists 3 C/C++ libraries for PEG parsing.
C parser for mathematical expressions with one variable and save it into a function
What you want to achieve is totally feasible. You can for instance build an AST (https://en.wikipedia.org/wiki/Abstract_syntax_tree) from the expression, where some nodes of the tree represent the variables.
Then, the evaluation of the expression for some values of the variables corresponds to the evaluation of that tree.
Actually, most parsers will produce such a tree internally and you may be able to find some library producing an AST for your need or you might want to code it yourself (see also https://en.wikipedia.org/wiki/Shunting-yard_algorithm). Here is a simple example of an expression parser producing an AST (in Java though).
parsing of mathematical expressions
You need to write a lexical analyzer to tokenize the input (break it into its component parts--operators, punctuators, identifiers, etc.). Inevitably, you'll end up with some sequence of tokens.
After that, there are a number of ways to evaluate the input. One of the easiest ways to do this is to convert the expression to postfix using the shunting yard algorithm (evaluation of a postfix expression is Easy with a capital E).
How to parse mathematical expressions involving parentheses
Ages ago when working on a simple graphing app, I used this algorithm (which is reasonably easy to understand and works great for simple math expressions like these) to first turn the expression into RPN and then calculated the result. RPN was nice and fast to execute for different variable values.
Of course, language parsing is a very wide topic and there are many other ways of going about it (and pre-made tools for it too)
how to parse a matematical expression in C
There are many available projects doing it.
For example: https://github.com/codeplea/tinyexpr
Clone, test & see how it is done
Parse Math Expression
You can try using DataTable.Compute.
A related one is DataColumn.Expression.
Also check out: Doing math in vb.net like Eval in javascript
Note: I haven't used these myself.
Parsing simple mathematical expressions
To parse a number from the string as a double
, you can use strtod()
:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if (argc == 1) {
printf("\n========================================================\n");
printf("Invalid usage: <ProgramName>.exe <MathExpression:string>\n");
printf("eg: 2+3/5*9\n");
printf("========================================================\n");
return 0;
}
char *expr = argv[1];
double answer = strtod(expr, &expr);
while (*expr) {
if (*expr == ' ' || *expr == '\t')
expr++;
else if (*expr == '+')
answer += strtod(expr + 1, &expr);
else if (*expr == '-')
answer -= strtod(expr + 1, &expr);
else if (*expr == '*')
answer *= strtod(expr + 1, &expr);
else if (*expr == '/')
answer /= strtod(expr + 1, &expr);
else
break;
}
printf("answer: %.2f\n", answer);
return 0;
}
Note that invalid input may produce surprising results. Here is a simple way to detect invalid input:
#include <stdio.h>
#include <stdlib.h>
double get_number(const char *expr, char **nextp) {
double value = strtod(expr, nextp);
if (expr == *nextp) {
fprintf(stderr, "invalid input: %s\n", expr);
exit(1);
}
return value;
}
int main(int argc, char *argv[]) {
if (argc == 1) {
printf("\n========================================================\n");
printf("usage: <ProgramName>.exe <MathExpression:string>\n");
printf("eg: '2+3/5*9'\n");
printf("========================================================\n");
return 0;
}
char *expr = argv[1];
double answer = get_number(expr, &expr);
while (*expr) {
if (*expr == ' ' || *expr == '\t')
expr++;
else if (*expr == '+')
answer += get_number(expr + 1, &expr);
else if (*expr == '-')
answer -= get_number(expr + 1, &expr);
else if (*expr == '*')
answer *= get_number(expr + 1, &expr);
else if (*expr == '/')
answer /= get_number(expr + 1, &expr);
else {
printf("invalid input: %s\n", expr);
break;
}
}
printf("answer: %.2f\n", answer);
return 0;
}
Related Topics
Shgetknownfolderpath Equivalent API in Linux
Getting Mangled Name from Demangled Name
Why Doesn't Sfinae (Enable_If) Work for Member Functions of a Class Template
Unnecessary Curly Braces in C++
How to Get a "Useful" C++ Binary Search Algorithm
How to Use Sdl2 and Sdl_Image with Cmake
Access Variable Value Using String Representing Variable's Name in C++
What Is a Non-Trivial Constructor in C++
Is It Safe to Fork from Within a Thread
Create Window Without Title Bar
How True Is "Want Speed? Pass by Value"
How to Catch the Null Pointer Exception