You can use a regular expression to verify everything about a mathematical expression except the check that parentheses are balanced. That is, the regular expression will only ensure that open and close parentheses appear at the point in the expression they should appear, but not their correct relationship with other parentheses.
So you could check both that the expression matches a regex and that the parentheses are balanced. Checking for balanced parentheses is really simple if there is only one type of parenthesis:
bool check_balanced(const char* expr, char open, char close) {
int parens = 0;
for (const char* p = expr; *p; ++p) {
if (*p == open) ++parens;
else if (*p == close && parens-- == 0) return false;
}
return parens == 0;
}
To get the regular expression, note that mathematical expressions without function calls can be summarized as:
BEFORE* VALUE AFTER* (BETWEEN BEFORE* VALUE AFTER*)*
where:
BEFORE
is sub-regex which matches an open parenthesis or a prefix unary operator (if you have prefix unary operators; the question is not clear).
AFTER
is a sub-regex which matches a close parenthesis or, in the case that you have them, a postfix unary operator.
BETWEEN
is a sub-regex which matches a binary operator.
VALUE
is a sub-regex which matches a value.
For example, for ordinary four-operator arithmetic on integers you would have:
BEFORE
: [-+(]
AFTER
: [)]
BETWEEN
: [-+*/]
VALUE
: [[:digit:]]+
and putting all that together you might end up with the regex:
^[-+(]*[[:digit:]]+[)]*([-+*/][-+(]*[[:digit:]]+[)]*)*$
If you have a Posix C library, you will have the <regex.h>
header, which gives you regcomp
and regexec
. There's sample code at the bottom of the referenced page in the Posix standard, so I won't bother repeating it here. Make sure you supply REG_EXTENDED
in the last argument to regcomp
; REG_EXTENDED|REG_NOSUB
, as in the example code, is probably even better since you don't need captures and not asking for them will speed things up.