11
回答
写了几天的方程式解析,实在是写不出来..有没大神帮忙写一个..
华为云实践训练营,热门技术免费实践!>>>   

做一个基于CVI的方程式解析产生波形,写了几天,对堆栈实在是不熟悉,然后用if一直写..写出几百行,就是没结果..只能求助大神了..

得到了一个字符串"sin((1*2*3*a)/4)*tan(5*(6+7)*a+0.1)",像计算器一样能解析并算出最终结果,a是个一个变量,用以循环得到一个连续的波形.

我的想法是用if,得到sin以及括号,然后在if得到运算符,然后一直循环下去,但是工程实在是太大,一个错误导致最后结果完全错..

用java或者C++都比用C容易很多啊..用C实在是没办法了,只能求助大神了..

<无标签>
举报
LMMaptx
发帖于4年前 11回/599阅
共有11个答案 最后回答: 4年前

两种方式:

1 如楼上所说,自己写解析器,当然不是手写,有工具可以根据语法自动生成。该方法难度较高。

2 走捷径,在c中嵌一个动态语言环境,直接运行脚本。比如嵌入一个lua运行环境,直接运行脚本即可。

1. 需要会表达是求值,例如使用逆波兰式,不会的话去看看,挺简单的。

2. 把表达式中的变量替换成它的值。

3. 函数sin((1*2*3*a)/4):先求出函数中的表达式的值,再求出函数值,用这个值替换掉原来表达式中函数的部分,最终得到一个表达式。为了得到函数部分的字符串可以使用堆栈。

4. 求3得到的表达式的值,就是整个表达式的结果。

引用来自“jorneyr”的评论

1. 需要会表达是求值,例如使用逆波兰式,不会的话去看看,挺简单的。

2. 把表达式中的变量替换成它的值。

3. 函数sin((1*2*3*a)/4):先求出函数中的表达式的值,再求出函数值,用这个值替换掉原来表达式中函数的部分,最终得到一个表达式。为了得到函数部分的字符串可以使用堆栈。

4. 求3得到的表达式的值,就是整个表达式的结果。

谢谢.现在是做出了不带函数的表达式解析,然后替换这里就是出问题..主要是替换数值太多..上万个值一一替换就容易出错..

借用了.net的Math库,利用动态生成代码写的,稍微不足的地方是需要对变量a进行定义。解析也可以,怎么赋初始值也是问题,不明白你的具体要求,所以就没写。


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.IO;
using System.Text.RegularExpressions;

namespace ConsoleApplication2
{
    class Program
    {
        public static string CreateMathCode(string dynamicCode,string returnVariable,params string[] variables)
        {

            MemberInfo[] methods=  typeof(Math).GetMethods(BindingFlags.Static | BindingFlags.Public);
            foreach (MethodInfo m in methods)
            {
                string REGEX_VALIDATION = string.Format(@"(?<{0}>{0}\()",m.Name);
                if (Regex.IsMatch(dynamicCode, REGEX_VALIDATION, RegexOptions.IgnoreCase | RegexOptions.Multiline))
                {
                    dynamicCode = Regex.Replace(
                           dynamicCode,
                           REGEX_VALIDATION,
                           then =>
                           {
                               return string.Format("Math.{0}(", m.Name);
                           }, RegexOptions.IgnoreCase | RegexOptions.Multiline);
                }
            }
            Console.WriteLine(dynamicCode);

            StringBuilder sb = new StringBuilder();

            sb.AppendLine("using System;");
            sb.AppendLine("namespace DynaCore");
            sb.AppendLine("{");
            sb.AppendLine("   public class DynaCore");
            sb.AppendLine("   {");
            sb.AppendLine("       static public double Main()");
            sb.AppendLine("       {");
            if (!string.IsNullOrEmpty(returnVariable))
            {
                sb.AppendLine(string.Format(" double {0}=0;", returnVariable));
            }
            if (variables != null && variables.Length > 0)
            {
                foreach (string var in variables)
                {
                    sb.AppendLine(var);
                }
            }
            sb.AppendLine(string.Format(" {0}={1};",returnVariable,dynamicCode));
            sb.AppendLine(string.Format(" Console.WriteLine({0});", returnVariable));
            sb.AppendLine(string.Format(" return {0};", returnVariable));
            sb.AppendLine("       }");
            sb.AppendLine("   }");
            sb.AppendLine("}");
            return sb.ToString();
        }

        static void Main(string[] args)
        {
            string dynamicString = "sin((1*2*3*a)/4)*tan(5*(6+7)*a+0.1)";
            //a的初始值设为5;
            string code = CreateMathCode(dynamicString, "returnValue", "double a=5;");
            CompileAndRun(code);        
            Console.ReadKey();
        }

        static void CompileAndRun(params string[] code)
        {
            CompilerParameters CompilerParams = new CompilerParameters();
            string outputDirectory = Directory.GetCurrentDirectory();

            CompilerParams.GenerateInMemory = true;
            CompilerParams.TreatWarningsAsErrors = false;
            CompilerParams.GenerateExecutable = false;
            CompilerParams.CompilerOptions = "/optimize";

            string[] references = { "System.dll" };
            CompilerParams.ReferencedAssemblies.AddRange(references);

            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerResults compile = provider.CompileAssemblyFromSource(CompilerParams, code);

            if (compile.Errors.HasErrors)
            {
                string text = "Compile error: ";
                foreach (CompilerError ce in compile.Errors)
                {
                    text += "rn" + ce.ToString();
                }
                throw new Exception(text);
            }

            //ExpoloreAssembly(compile.CompiledAssembly);

            Module module = compile.CompiledAssembly.GetModules()[0];
            Type mt = null;
            MethodInfo methInfo = null;

            if (module != null)
            {
                mt = module.GetType("DynaCore.DynaCore");
            }

            if (mt != null)
            {
                methInfo = mt.GetMethod("Main");
            }

            if (methInfo != null)
            {
                Console.WriteLine(methInfo.Invoke(null, null));
            }
        }

        static void ExpoloreAssembly(Assembly assembly)
        {
            Console.WriteLine("Modules in the assembly:");
            foreach (Module m in assembly.GetModules())
            {
                Console.WriteLine("{0}", m);

                foreach (Type t in m.GetTypes())
                {
                    Console.WriteLine("t{0}", t.Name);

                    foreach (MethodInfo mi in t.GetMethods())
                    {
                        Console.WriteLine("tt{0}", mi.Name);
                    }
                }
            }
        }
    }
}




--- 共有 1 条评论 ---
LMMaptx十分感谢.但我这CVI软件只能用C写. 4年前 回复
顶部