Анализатор с поддержкой переменных - 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)); }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д