成人午夜激情影院,小视频免费在线观看,国产精品夜夜嗨,欧美日韩精品一区二区在线播放

基于C#語言的可編程表達式計算器設計

2010-08-28 10:49:35來源:西部e網作者:

1. 說明:

   先看看我們的成果:
p_cal_main.bmp
 
   網上的表達式計算器有很多,但這次我們來點,不同的,有兩點:
   1)用戶可以編程以擴充計算器的函數
     即右下角那個“添加函數按鈕”
     比如,我們想增加一個"Factarial"階乘函數,我們可以“添加函數”
p_cal_addFun.bmp
 
然后編輯我們的函數
p_cal_edit.bmp
 
  最后“生成”即可,主窗口上會自動添加一個"Factarial"按鈕,然后就可以使用了(該函數將一直存在,除非你手動刪除它)
  其實,主窗口上的所有函數按鈕都是這樣生成的

   2)我們對表達式的計算將擺脫傳統的觀點(即傳統的對表達式進行詞法分析,語法分析等等),在編寫我們的計算器的代碼中,不會有任何的詞法分析、語法分析、后綴表達式轉換等
   等。
     啟發來自于這里:
     假設有一個函數F
     double F()
     {
         double r = 3*4.5+sin(50);
         return r;
     }

     那么,我們就可以 Console.WriteLine("{0}",F());    
     我們計算了3*4.5+sin(50),但我們有進行麻煩的詞法分析與語法分析嗎?沒有,誰幫我們做了,編譯器,ok,關鍵就在這:如果計算器用戶在計算器主窗口上輸入表達式
     3*4.5+sin(50),我們負責把它傳給F中的r,然后我們再把F的返回值輸出到用戶界面上就OK了,我們要做的就這些。
    

2 計算器上的函數
  2.1 函數按鈕對應的函數在哪里?
      在Functions.dll中,不要指望這我微軟給我們的,因為函數是用戶編寫的,我們也不知道用戶會編寫什么樣的函數,他甚至可以編寫一個播放音樂的函數(呵呵,我們的計算器
完全可以做到這點,不過似乎對于一個計算器來說這有些過分了)
  2.2 誰來負責Functions.dll的生成?
      不是.net2003,不是.net2005,是我們的計算器
      要在用戶自定義函數的時候將函數打包到Functions.dll中,就涉及到一個編譯問題,我們將負責這一工作
  2.3 誰給了我們編譯的權利?
      System.CodeDom.Compiler和Microsoft.CSharp名字空間中有我們的答案(請參見Msdn)

      我們的Functions.dll打包成功以后,我們就可以在計算表達式是調用其中的函數了


3 表達式的計算
   3.1 如何計算?
       在前面計算 3*4.5+sin(50)的例子中,已經說過,我們將利用編譯器幫我們計算,我們僅僅像Console.WriteLine("{0}",F())一樣簡單地將函數F的返回值輸出給用戶(F的返回值就是表達式的值):
     double F()
     {
         double exp = 3*4.5+sin(50);//假設3*4.5+sin(50)就是用戶輸入的表達式
         return exp;
     }
   3.2 F()從哪里來?到哪里去?
   F()肯定不是我們事先寫好的,因為其中的exp的初始表達式是用戶來寫的
   我們將這樣來解決這一問題:在用戶輸入表達式以后動態地生成函數F()的代碼 -> 將該代碼編譯 -> 調用編譯成功后的程序集中的該函數
        /// <summary>
        /// 將數學表達式轉化為C#程序
        /// </summary>
        /// <param name="express">用戶輸入的數學表達式</param>
        /// <returns>返回C#程序代碼</returns>
        public static string TranslateToCSharp(string express)
        {
            string s = "";
            if (File.Exists(Function.GetPathOfFunctionDll()))
            {
                s += "using "+Function.FunctionNameSpace + ";\n";
            }
            
            s +=
             "using System;\n" +
             "namespace ComputeUnit\n" +
             "{\n" +
                "public class Compute\n" +
                "{\n" +
                "   public static double GetResult()\n" +
                "   {\n" +
                "      return "+  TranslateToCSharpExpress(express) + ";\n"+
                "   }\n" +
                "}" +
            "}\n";

            return s;
        }
     這里的GetResult()函數也就是我們所說的函數F()
      
      3.3 誰幫我們取得計算結果?
          反射!
         
          假設用戶輸入了表達式express,我們將如同下面的代碼所敘述的那樣計算它

          string source = TranslateUnit.TranslateToCSharp(express);

            //這里加載了函數dll
            string[] dlls = new string[1];
            dlls[0] = Function.GetPathOfFunctionDll(); //這里加載了前面所說的Functions.dll
             //編譯
            CompilerResults results = CompilerUnit.Compile(source, false,true, dlls,null);

            //重要:利用反射獲取計算結果
            if (results.Errors.Count == 0)
            {
                Assembly ass = results.CompiledAssembly;

                Type tp = ass.GetType("ComputeUnit.Compute");//ass.GetType("MyNamespace.MyClass");

                // 獲取方法
                MethodInfo mi = tp.GetMethod("GetResult");//tp.GetMethod("MyMethodl");

                // 創建實例
                Object obj = System.Activator.CreateInstance(tp);

                //執行方法
                try
                {
                    object res = mi.Invoke(obj, null);
                    this.Output(res.ToString(), false, Color.Blue); //將計算結果輸出給用戶

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.ToString());
                }


以上僅僅簡要敘述了此程序的核心問題,除此之外還有許許多多的細節問題,如果需要了解更多,你可以下載此程序的源代碼http://www.cnblogs.com/Files/zhouyinhui/ProgramCalculator.rar,里面有詳細的注釋,或email:yinhui_zhou@yahoo.com.cn聯系我

關鍵詞:C#

贊助商鏈接:

主站蜘蛛池模板: 老河口市| 丹阳市| 手机| 深州市| 桂阳县| 开阳县| 吕梁市| 临夏县| 开江县| 衡阳市| 江阴市| 建水县| 贺州市| 温宿县| 高淳县| 成武县| 商洛市| 海口市| 巩义市| 五原县| 云霄县| 淅川县| 漳州市| 临桂县| 黑山县| 玛沁县| 晋城| 灵石县| 连城县| 大丰市| 天柱县| 潞城市| 黑山县| 甘洛县| 墨脱县| 长兴县| 临安市| 象山县| 临颍县| 瓮安县| 阳高县|