计算器是经常遇到的编程作业。
一般都是实现加、减、乘、除四则运算的普通计算器。
这里介绍用几十行C#代码实现的复杂的《科学计算器》,可以计算各种函数。
不知道其他语言实现同样的功能需要编写多少行代码?20000行?
using System;
using System.Text;
using System.Drawing;
using System.Collections.Generic;
using System.Windows.Forms;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;
namespace HyperCalculator
{
public partial class Form1 : Form
{
// 预定义各 按键 的文字
string[] operationArray = new string[] {
"Abs", "Acos", "(", ",", ")", "Backspace", "C",
"Asin", "Atan", "7", "8", "9", "/", "=",
"Atan2", "Ceiling", "4", "5", "6", "*", "",
"Cos", "Cosh", "1", "2", "3", "-", "",
"E", "Exp", "0", "", ".", "+", "",
"Floor", "Log", "Log10", "Max", "Min", "PI", "Pow",
"Sign", "Sin", "Sinh", "Sqrt", "Tan", "Tanh", "",
};
List<Button> buttonList = new List<Button>();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// 动态加载液晶LED字体(请下载压缩包,内含)
System.Drawing.Text.PrivateFontCollection privateFonts = new System.Drawing.Text.PrivateFontCollection();
privateFonts.AddFontFile("LEDCalculatorBold.ttf");
System.Drawing.Font font = new Font(privateFonts.Families[0], 21);
textBox1.Font = font;
textBox1.Text = "0";
textBox1.TextAlign = HorizontalAlignment.Right;
// 打包按键集合
Control.ControlCollection sonControls = this.Controls;
foreach (Control control in sonControls)
{
if (control.GetType() == typeof(Button))
{
buttonList.Add((Button)control);
}
}
// 按位置排序,以及匹配实现预定义的文字
buttonList.Sort(delegate (Button a, Button b)
{
return Comparer<int>.Default.Compare(a.Left + a.Top * button1.Height, b.Left + b.Top * button1.Height);
});
Font nf = new Font(Font.FontFamily, 21);
for (int i = 0; i < buttonList.Count && i < operationArray.Length; i++)
{
buttonList[i].Cursor = Cursors.Hand;
buttonList[i].Text = operationArray[i];
if (buttonList[i].Text.Length == 1 && operationArray[i] != "E")
{
buttonList[i].Font = nf;
buttonList[i].BackColor = Color.FromArgb(225, 255, 200);
}
if (operationArray[i].Trim().Length > 0) buttonList[i].Click += button_Click;
}
}
private void button_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
if (btn.Text == "=")
{
// 等号就是计算啦!任何计算,都是执行一个表达式而已!
CSharpCodeProvider objCSharpCodePrivoder = new CSharpCodeProvider();
ICodeCompiler objICodeCompiler = objCSharpCodePrivoder.CreateCompiler();
CompilerParameters objCompilerParameters = new CompilerParameters();
objCompilerParameters.ReferencedAssemblies.Add("System.dll");
objCompilerParameters.GenerateExecutable = false;
objCompilerParameters.GenerateInMemory = true;
// 编译 Code() 返回的含有计算表达式的完整的 C# 程序;
CompilerResults cr = objICodeCompiler.CompileAssemblyFromSource(objCompilerParameters, Code());
if (cr.Errors.HasErrors)
{
StringBuilder sb = new StringBuilder();
foreach (CompilerError err in cr.Errors)
{
sb.AppendLine(err.ErrorText);
}
MessageBox.Show(sb.ToString(), "表达式错误");
}
else
{
// 执行 C# 程序的指定 函数,并得到返回值,就是计算结果;
Assembly objAssembly = cr.CompiledAssembly;
object objHelloWorld = objAssembly.CreateInstance("Beijing.Legalsoft.Ltd.HyperCalculator");
MethodInfo objMI = objHelloWorld.GetType().GetMethod("Run");
double resultValue = (double)objMI.Invoke(objHelloWorld, null);
textBox1.Text = resultValue + "";
}
return;
}
if (btn.Text == "C")
{
textBox1.Text = "0";
return;
}
if (btn.Text == "Backspace")
{
if (textBox1.Text.Length > 1)
{
textBox1.Text = textBox1.Text.Substring(0, textBox1.Text.Length - 1);
}
else
{
textBox1.Text = "0";
}
return;
}
if (textBox1.Text == "0") textBox1.Text = "";
if (textBox1.Text.Length + btn.Text.Length < 45)
{
textBox1.Text += btn.Text;
}
}
private string Code()
{
// 按输入的文字构造一个完整的 C# 程序;包括命名空间,类与方法(函数)
string state = textBox1.Text;
foreach (string ps in operationArray)
{
if (ps.Trim().Length > 1 || ps == "E")
{
state = state.Replace(ps, "Math." + ps);
}
}
state = state.Replace("Math.Math.", "Math.");
StringBuilder sb = new StringBuilder();
sb.AppendLine("using System;");
sb.AppendLine("namespace Beijing.Legalsoft.Ltd");
sb.AppendLine("{");
sb.AppendLine(" public class HyperCalculator");
sb.AppendLine(" {");
sb.AppendLine(" public double Run()");
sb.AppendLine(" {");
sb.AppendLine(" return (" + state + ");");
sb.AppendLine(" }");
sb.AppendLine(" }");
sb.AppendLine("}");
return sb.ToString();
}
}
}