Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Разработка Windows Forms > Как прочитать функцию из textBox?


Автор: oleeg 18.7.2008, 01:17

Все привет!
Я пишу программу, строящую график функции. В целях самообучения. Как можно сделать так, чтобы читать из текстбокса информацию o функции, которую ввел пользователь? Скажем, при нажатии кнопки. Пробовал так:

Код

// наша функция
        private int Function(int x)
        {
            int y = Convert.ToInt32(textBox1.Text);
            return y;
        }


Выводит 
Код

Input string was not in a correct format
.
Почему так?
Так все нормально строиться
Код

   // наша функция
        private int Function(int x)
        {
            int y;
            return y = x;
        }


Т е как распознать функцию, грубо говоря?

Автор: SKrivosein 18.7.2008, 02:30
Не понял чо делает твой код(первый и второй) ,ну ладно, может так...
Код

 private int Function(int x)
        {
            string user_y = string.Format("{0}", textBox1.Text);
            int y = int.Patse(user_y);
            return y;
        }

Хотя этот делает тоже.
Код

 private int Function(int x)
        {
            int y = Convert.ToInt32(textBox1.Text);
            return y;
        }

Автор: nikitao 18.7.2008, 02:40
а зачем нужен x ? smile 

Автор: Partizan 18.7.2008, 07:36
вопрос просто шедевральный  smile 

Автор: oleeg 18.7.2008, 13:54
какой есть smile
смысл в том, что пользователь вводит функцию в текстбокс, а мне нужно ее прочитать.
как это можно реализовать?

Автор: Partizan 18.7.2008, 14:07
oleeg, что значит прочитать функцию?))))

я так подозреваю, что пользователь вводит например "x*2+21" а вы хотите чтобы текстбокс вам всё почситал и выдал результат - так?)))

Автор: oleeg 18.7.2008, 16:26
))
не, не так. Пользователь вводит "x*2+21", из текстбокса извлекаеться text, распознаеться, так сказать, преобразовываеться и по этому строиться график ))

Добавлено через 1 минуту и 28 секунд
я не знаю, как это лучше объяснить. типа разбор строки из текстбокса.

Автор: Partizan 18.7.2008, 16:30
oleeg, )))
1. текст из текстбокса выдрать не проблема...
2. кем распознаётся? что должно быть результатом распознавания?
3. опять же кем преобразовывается? во что преобразовывается?

вы хотите чтобы вам Convert.ToInt32("x*2+21"); выдал массив точек для построения графика?  smile 

Автор: oleeg 18.7.2008, 20:21
Цитата(Partizan @ 18.7.2008,  16:30)
вы хотите чтобы вам Convert.ToInt32("x*2+21"); выдал массив точек для построения графика?  smile

Понятно, что так не получиться ) пробовал я ))
а как еще можно распознать? есть какой-нибудь алгоритм?

Автор: Rififi 18.7.2008, 20:34
oleeg, 
если бы нужно было сделать быстро, я бы сделал так
- подключил бы к проекту Microsoft <что-то там> Script Control (выполнение скрпитов)
- полученную из TextBox строку преобразовал к виду "function f(x) { return x*2 + 21; }"
- в цикле вызвал ScriptControl для всех x из заданного диапазона
- полученные от ScriptControl значения собрал бы в массив List<int>

кривовато, зато выражение самому парсить не придётся (а оно может быть и посложнее...)

Автор: Partizan 18.7.2008, 20:50
Rififi, зато для мозга полезнее )

з.ы. oleeg, если всё-таки захочешь парсить руками, то ищи алгоритм "Обратная польская нотация".

В своё время писал разбор сложных выражений на основе ОПН...не раз пригодилось в жизни

Автор: oleeg 19.7.2008, 01:23
Rififi, Partizan
Спасибо. Думаю, буду руками парсить все-таки.

Автор: mihryak 20.7.2008, 01:19
можно сборку скомпилить, содержащую функцию

для функции одной переменной (на досуге для себя написал)
Код

    class AssemblyGenerator
    {
        public delegate float FunctionDelegate(float x);

        private const string ClassName = "Evaluator";
        private const string MethodName = "GetValue";

        private readonly string functionString;
        private MethodInfo methodInfo;

        public AssemblyGenerator(string functionString)
        {
            if (String.IsNullOrEmpty(functionString))
            {
                throw new ArgumentNullException("functionString");
            }
            this.functionString = functionString;
        }

        public FunctionDelegate Function
        {
            get
            {
                return Eval;
            }
        }

        private float Eval(float x)
        {
            return (float) EvalMethod.Invoke(null, new object[] {x});
        }


        private MethodInfo EvalMethod
        {
            get
            {
                if (methodInfo == null)
                {
                    methodInfo = BuildAssembly(functionString).GetType(ClassName).GetMethod(MethodName);
                }
                return methodInfo;
            }
        }

        private static Assembly BuildAssembly(string functionString)
        {
            CodeDomProvider provider = new CSharpCodeProvider();
            CompilerParameters compilerParameters = new CompilerParameters();
            compilerParameters.GenerateInMemory = true;

            CompilerResults compilerResults = provider.CompileAssemblyFromSource(compilerParameters, GetAssemblyCode(functionString));
            if (compilerResults.Errors.HasErrors)
            {
                StringBuilder errorStringBuilder = new StringBuilder("Unable to compile assembly.\r\n");
                foreach (CompilerError compilerError in compilerResults.Errors)
                {
                    errorStringBuilder.AppendLine(compilerError.ErrorText);
                }
                throw new ArgumentException(errorStringBuilder.ToString());
            }

            return compilerResults.CompiledAssembly;
        }

        private static string[] GetAssemblyCode(string functionString)
        {
            StringBuilder codeStringBuilder = new StringBuilder();
            codeStringBuilder.Append("using System;");
            codeStringBuilder.AppendFormat("public static class {0}", ClassName);
            codeStringBuilder.Append("{");
            codeStringBuilder.AppendFormat("public static float {0}(float x)", MethodName);
            codeStringBuilder.Append("{");
            codeStringBuilder.AppendFormat("return (float) ({0});", functionString);
            codeStringBuilder.Append("}");
            codeStringBuilder.Append("}");

            return new string[] { codeStringBuilder.ToString() };
        }
    }

использование:
Код

AssemblyGenerator.FunctionDelegate function = new AssemblyGenerator(functionTextBox.Text).Function;
float value = function(5.73);

имя переменной - x, в TextBox'е текст должен быть в правильном c# формате (для вычисления синусов, например, надо писать Math.Sin(x))

user posted image

Автор: oleeg 20.7.2008, 02:41
mihryak
Благодарю. Буду разбираться. Я все-таки решил использовать ZedGraph, а в нем введу все стандартные функции в таком виде 
a*Sin(b*x+c) + d, вручную задаються кооэфициэнты. Так, думаю, будет проще.

Автор: oleeg 20.7.2008, 20:42
mihryak Вы это приложение для себя писали, на досуге? Если не трудно, не могли бы Вы выложить исходники. Будет с чем сравнить) 
А то я че-то такого намутил в своей программе, строящей график функции, там можно аж настроить 3 цвета и угол заливки символа ( это точка на графике). smile

Автор: mihryak 20.7.2008, 22:41
oleeg, выладываю
обрати внимание - ImageProvider в шаге от hard-code, и ручной скалинг вообще не реализован (только автоматический на всю доступную высоту) - к этому моменту я уже потерял к этой поделке интерес =)
но в плане образца по компиляции сборки из исходного кода и её последующему использованию вполне сгодится  smile 

Автор: oleeg 21.7.2008, 01:30
mihryak спасибо большое, буду разбираться!

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)