What sorts of algorithms would be used to do this (as in, this is a string, and I want to find the answer):
((5 + (3 + (7 * 2))) - (8 * 9)) / 72
I would use the tools that are available nearly everywhere.
I like lex/yacc because I know them but there are equivalents everywhere. So before you write complex code see if there are tools that can help you to make it simple (problems like this have been solved before so don;t re-invent the wheel).
So, using lex(flex)/yacc(bison) I would do:
%option noyywrap
Number [0-9]+
WhiteSpace [ \t\v\r]+
NewLine \n
%{
#include
%}
%%
\( return '(';
\) return ')';
\+ return '+';
\- return '-';
\* return '*';
\/ return '/';
{Number} return 'N';
{NewLine} return '\n';
{WhiteSpace} /* Ignore */
. fprintf(stdout,"Error\n");exit(1);
%%
%{
#include
typedef double (*Operator)(double,double);
double mulOp(double l,double r) {return l*r;}
double divOp(double l,double r) {return l/r;}
double addOp(double l,double r) {return l+r;}
double subOp(double l,double r) {return l-r;}
extern char* yytext;
extern void yyerror(char const * msg);
%}
%union
{
Operator op;
double value;
}
%type MultOp AddOp
%type Expression MultExpr AddExpr BraceExpr
%%
Value: Expression '\n' { fprintf(stdout, "Result: %le\n", $1);return 0; }
Expression: AddExpr { $$ = $1;}
AddExpr: MultExpr { $$ = $1;}
| AddExpr AddOp MultExpr { $$ = ($2)($1, $3);}
MultExpr: BraceExpr { $$ = $1;}
| MultExpr MultOp BraceExpr { $$ = ($2)($1, $3);}
BraceExpr: '(' Expression ')' { $$ = $2;}
| 'N' { sscanf(yytext,"%le", &$$);}
MultOp: '*' { $$ = &mulOp;}
| '/' { $$ = &divOp;}
AddOp: '+' { $$ = &addOp;}
| '-' { $$ = &subOp;}
%%
void yyerror(char const * msg)
{
fprintf(stdout,"Error: %s", msg);
}
int main()
{
yyparse();
}
> flex e.l
> bison e.y
> gcc *.c
> ./a.out
((5 + (3 + (7 * 2))) - (8 * 9)) / 72
Result: -6.944444e-01
>
The above also handles normal operator precedence rules:
Not because of anything I did,but somebody smart worked this out ages ago and now you can get the grammar rules for expression parsing easily (Just google C Grammer and rip the bit you need out).
> ./a.out
2 + 3 * 4
Result: 1.400000e+01