Анализатор с поддержкой переменных - C#
Формулировка задачи:
Доброго времени суток!
Подскажите как в анализатор арифметических выражений можно подставить вместо буквы значение из массива.
Анализатор считает математические выражения (н-р: 10-5/2). Добавил в него возможность распознавания кроме цифр и знаков арифм. операций букв, которым присваивается тип "VARIABLE", но вот как в процессе вычисления вместо них подтянуть их значение из массива хранящего эти значения не знаю.
Это нужно для того, что бы например если на вход подаётся функция x^2+2*x+1, программа рассчитала её значения, при х равном определённым значениям, которые будут хранится в массиве.
Распознавание переменной прописано в функции get_token, её замена на конкретное значение в account7 (ref double rezult):
class Program
{
class kalculiator
{
public enum typesT {UNDEFTOK, OPERATOR, NUMBER, VARIABLE};
char[] operators_deistviy = new char[9] { '+', '-', '*', '/', '%', '^', '=', '(', ')' };
string exp_ptr; //содержет вырожение
int iter=0;
string token; //содержет текущ лексему
typesT tok_type; //содержет тип лексемы
public kalculiator ()
{
exp_ptr = "";
}
public double eval_exp (string exp)
{
double rezult=0;
exp_ptr = exp;
get_token();
if (String.IsNullOrEmpty(exp_ptr)) return 0.0;
add_sub2 (ref rezult);
if (iter != exp_ptr.Length) Console.WriteLine("Ошибка! Не достигнут конец строки.");
return rezult;
}
public void add_sub2 (ref double rezult)
{
double temp=0;
string op;
mul_div_pers3(ref rezult);
while ((op = token) == "+" || op == "-") //Исправить, после выяснения как замен указ на тек лексему
{
get_token();
mul_div_pers3(ref temp); //Исправить, после выяснения как замен указ на тек лексему
switch (op)
{
case "-":
rezult = rezult - temp;
break;
case "+":
rezult = rezult + temp;
break;
}
}
}
public void mul_div_pers3 (ref double rezult)
{
double temp=0;
string op;
stepen4 (ref rezult);
while ((op = token) == "*" || op == "/" || op == "%") //Исправить, после выяснения как замен указ на тек лексему
{
get_token();
stepen4(ref temp);
switch (op)
{
case "*":
rezult = rezult * temp;
break;
case "/":
if (temp==0.0) Console.WriteLine("Ошибка! Деление на 0.");
else rezult = rezult / temp;
break;
case "%":
rezult = (int)rezult % (int)temp;
break;
}
}
}
public void stepen4 (ref double rezult)
{
double temp=0, ex;
unarn_oper5(ref rezult);
if (token == "^") //Исправить, после выяснения как замен указ на тек лексему
{
get_token();
stepen4(ref temp);
ex = rezult;
if (temp == 0.0)
{
rezult = 1.0;
return;
}
for (int t = (int)temp - 1; t > 0; --t) rezult = rezult * (double)ex;
}
}
public void unarn_oper5 (ref double rezult)
{
string op="";
// skobky6 (ref rezult);
//op = (char)0;
if ((tok_type == typesT.OPERATOR) && token == "+" || token == "-") //Исправить, после выяснения как замен указ на тек лексему
{
op = token; //Исправить, после выяснения как замен указ на тек лексему
get_token();
}
skobky6(ref rezult);
if (op == "-") rezult = -rezult;
}
public void skobky6 (ref double rezult)
{
if ((token == "(")) //Исправить, после выяснения как замен указ на тек лексему
{
get_token();
add_sub2(ref rezult);
if (token != ")") Console.WriteLine("Ошибка! Нет закрывающейсяскобки"); //Исправить, после выяснения как замен указ на тек лексему
get_token();
}
else account7(ref rezult);
}
public void account7(ref double rezult)
{
switch (tok_type)
{
case typesT.NUMBER:
rezult = Convert.ToDouble(token); //преобразование строки в тип double
get_token();
return;
case typesT.VARIABLE:
//rezult = take_variable();
get_token();
return;
default: Console.WriteLine("Ошибка чтения числа/переменной"); return;
}
}
public bool isdelim(char c)
{
if (c=='+' || c=='-' || c=='*'|| c=='/'|| c=='^' || c=='='|| c=='('|| c==')' || c=='\r') //сравнение символа с 1-м операндом и...
return true;
return false;
}
public void get_token()
{
char [] temp=new char [10]; //??? Нужен аналог указателя!!!
token = "";
tok_type = typesT.UNDEFTOK; //обнуление типа для анализа следующей лексемы
if (iter==exp_ptr.Length) return;
if (exp_ptr.IndexOfAny(operators_deistviy, iter, 1) > -1) //
{ //ищет нужный оператор в массиве
tok_type = typesT.OPERATOR;
token=token+exp_ptr[iter]; iter++;
}
else if ((int)exp_ptr[iter]>=97 && (int)exp_ptr[iter]<=122)
{ //проверка на принадлежность к букве алфавита
while (!isdelim(exp_ptr[iter])) //проверка на разделитель
{ token = token + exp_ptr[iter]; iter++;}
tok_type= typesT.VARIABLE; }
else if ((int)exp_ptr[iter] >= 48 && (int)exp_ptr[iter] <= 57)
{ //проверяет на принадлежность к числу
while (iter < exp_ptr.Length && !isdelim(exp_ptr[iter]))
{ token = token + exp_ptr[iter];
iter++;}
tok_type = typesT.NUMBER;
}
}
};Решение задачи: «Анализатор с поддержкой переменных»
textual
Листинг программы
Parser ob = new Parser();
var array = new int[] { 1, 2, 3, 4 };
string expr = "x^2+2*x+1";
foreach (var p in array)
{
ob.eval_exp(string.Format("x={0}", p));
Console.WriteLine("{0} for {1} = {2}", expr, p, ob.eval_exp(expr));
}