/// <summary> /// 获取变量值或用户自定义函数的计算结果 /// </summary> /// <param name="tag">变量标识符</param> private static CalNum GetVariableOrCustomFunResultValue(string tag, List<CalNum> numList) { CalNum result = null; if (numList.Count == 0)//变量 { string[] variables = Properties.Settings.Default.strVariables.Split('|'); //扫描变量键值列表 for (int i = 0; i < variables.Length; i++) { //找到变量 if (variables[i] == tag) { double d; if (double.TryParse(variables[i + 1], out d)) { result = new CalNum(d); } else { result = new CalNum(variables[i + 1]); } } } } else//用户自定义函数 { try { StringCollection funList = Properties.Settings.Default.funList; if (funList != null) { //逐个扫描存在的函数,查找函数 for (int i = 0; i < funList.Count; i++) { if (funList[i].Split('|')[0] == tag)//找到函数 { //参数个数不正确 if (numList.Count != funList[i].Split('|')[3].Split(',').Length) { throw new Exception("|参数个数不正确"); } string[] funParts = funList[i].Split('|');//分隔 StringBuilder funExpr = new StringBuilder(funParts[2]);//取出表达式 //替换表达式中的变量 for (int k = 0; k < numList.Count; k++) { bool bl; //替换,用参数的stringValue替换且两边加上括号 funExpr.Replace(Common.DeleteAnnotate(funParts[3].Split(',')[k], out bl), "(" + numList[k].stringValue + ")"); } //分段函数 if (funExpr.ToString().IndexOf("subfuns") != -1) { return subfuns(funExpr, numList);//不再进行后面的计算,返回 } //计算 bool bl1; string str = Common.DeleteAnnotate(funExpr.ToString(), out bl1);//删除注释 CalValList valList = new CalValList(str); CalResult calResult = valList.Calculate(); if (calResult.numList.Count == 1)//一个计算结果 { result = calResult.numList[0]; } else//多个计算结果 { result = new CalNum(calResult.GeneralResultToShow.Trim()); } } } } } catch (Exception ex) { throw new Exception(ex.Message + "|(函数'" + tag + "'的表达式是'" + Common.GetFunExpr(tag) + "')"); } } return result; }
/// <summary> /// 分段函数 /// </summary> private static CalNum subfuns(StringBuilder funExpr, List<CalNum> numList) { CalNum result = null; if (funExpr.ToString().IndexOf("subfuns(") == -1) { MakeException("分段函数语法不正确"); } if (funExpr[funExpr.Length - 1] != ')') { MakeException("分段函数语法不正确"); } funExpr.Replace("subfuns(", ""); funExpr.Remove(funExpr.Length - 1, 1); CalNum num = numList[0];//仅支持对第一个参数分段 bool isBeyond = true;//是否越界 string[] funs = funExpr.ToString().Split(','); if (funs.Length % 3 != 0) { MakeException("subfuns的参数个数不正确,必须三个为一组"); } for (int i = 0; i < funs.Length; i += 3)//每三个一组:左边界、右边界、对应表达式 { double leftBoundary = double.MinValue;//左边界 double rightBoundary = double.MaxValue;//右边界 bool leftHollow = false;//左边界是否空心,默认是实心 bool rightHollow = false;//右边界是否空心,默认是实心 bool isIn = false;//参数是否在该范围内,默认false if (funs[i].IndexOf(">") != -1)//左边界空心 { leftHollow = true; leftBoundary = double.Parse(funs[i].Substring(1)); } else { leftBoundary = double.Parse(funs[i]); } if (funs[i + 1].IndexOf("<") != -1)//右边界空心 { rightHollow = true; rightBoundary = double.Parse(funs[i + 1].Substring(1)); } else { rightBoundary = double.Parse(funs[i + 1]); } #region 判断参数是否在当前范围内 if (leftHollow == true)//左边界空心 { if (rightHollow == true)//右边界空心 { if (num.DoubleValue > leftBoundary && num.DoubleValue < rightBoundary) { isIn = true; } } else//右边界实心 { if (num.DoubleValue > leftBoundary && num.DoubleValue <= rightBoundary) { isIn = true; } } } else//左边界实心 { if (rightHollow == true)//右边界空心 { if (num.DoubleValue >= leftBoundary && num.DoubleValue < rightBoundary) { isIn = true; } } else//右边界实心 { if (num.DoubleValue >= leftBoundary && num.DoubleValue <= rightBoundary) { isIn = true; } } } #endregion if (isIn)//如果参数在当前范围内 { isBeyond = false;//没有越界 //计算 bool bl1; string str = Common.DeleteAnnotate(funs[i + 2], out bl1);//删除注释 CalValList valList = new CalValList(str); CalResult calResult = valList.Calculate(); if (calResult.numList.Count == 1)//一个计算结果 { result = calResult.numList[0]; } else//多个计算结果 { result = new CalNum(calResult.GeneralResultToShow.Trim()); } //跳出循环 break; } } if (isBeyond) { MakeException("输入的参数超出定义的范围"); } return result; }
/// <summary> /// 抛出异常 /// </summary> /// <param name="pos">异常在运算因子列表中的位置</param> private void MakeException(int pos, Exception ex) { List<CalVal> tempValList = new CalValList(nomalStringExpression).valList; throw (new Exception(ex.Message + "|:" + tempValList[pos].ope.tag + "|:" + BackToStrExp(pos, tempValList).Length.ToString())); }
/// <summary> /// 存储变量 /// </summary> private void memoryVars() { string[] variables = Properties.Settings.Default.strVariables.Split('|'); //进入该函数说明'='存在,下面两条语句不会出错 string leftValue = txtExp.Text.Split('=')[0]; string rightValue = txtExp.Text.Split('=')[1]; //等号右边计算结果 string rightResult = ""; //支持存储15个变量 int maxVarLength = 30; #region 赋值语句不合法的情况 //确保只有一个'=' if (txtExp.Text.Split('=').Length > 2) { txtResult.Text = "变量赋值语句不合法"; return; } //左右值存在 if (txtExp.Text.Split('=')[0].Trim() == "" || txtExp.Text.Split('=')[1].Trim() == "") { txtResult.Text = "变量赋值语句不合法"; return; } //变量名称不合法的情况 //变量名称中不能存在单引号 if (leftValue.IndexOf("'") != -1) { txtResult.Text = "变量赋值语句不合法"; return; } double d; //变量名称不能全为数字 if (double.TryParse(leftValue, out d) || double.TryParse(leftValue.Substring(0, 1), out d)) { txtResult.Text = "变量名称不合法"; return; } //单引号必须成对出现,且最多只能有一对 if (rightValue.Split('\'').Length != 1 && rightValue.Split('\'').Length != 3) { txtResult.Text = "变量赋值语句不合法"; return; } #endregion //计算等号右边 if (rightValue[0] == '\'' && rightValue[rightValue.Length - 1] == '\'') { rightResult = rightValue.Replace("'", ""); } else { CalValList valList = new CalValList(rightValue); rightResult = valList.Calculate().GeneralResultToShow.Replace(" ", ""); txtExp.Text = leftValue + "=" + valList.nomalStringExpression; } if (variables.Length == 1)//特殊情况 { Properties.Settings.Default.strVariables = leftValue + "|" + rightResult; Properties.Settings.Default.Save(); txtResult.Text = "变量'" + leftValue + "'已赋值为'" + rightResult + "'"; } else { #region 查找是否存在同名变量或同名运算符或常数 bool homonymyOpe = false; bool varExists = false; int existsVarPos = -1;//同名变量位置 //是否存在同名变量 for (int i = 0; i < variables.Length; i += 2) { //找到同名变量 if (variables[i] == leftValue) { existsVarPos = i; varExists = true; break; } } //是否存在同名运算符 CalOpeList opeList = new CalOpeList(); for (int i = 0; i < opeList.count; i++) { //找到同名运算符 if (opeList.opeList[i].tag == leftValue) { homonymyOpe = true; break; } } #endregion #region 存在同名变量,替换变量 if (varExists) { if (MessageBox.Show("变量'" + leftValue + "'已存在,且它的值为'" + variables[existsVarPos + 1] + "',是否替换?", "提示", MessageBoxButtons.OKCancel) == DialogResult.OK) { variables[existsVarPos + 1] = rightResult; string s = variables[0]; for (int i = 1; i < variables.Length; i++) { s += "|" + variables[i]; } Properties.Settings.Default.strVariables = s; Properties.Settings.Default.Save(); txtResult.Text = "变量'" + leftValue + "'的值已替换为'" + rightResult + "'"; } } #endregion #region 存在同名常数或运算符 else if (homonymyOpe) { txtResult.Text = "存储变量失败!存在同名常数或运算符"; } #endregion #region 不存在同名变量、常数或运算符,插入变量 else { //列表variables的开始读取位置 int startPos = -1; //是否超出支持的最大变量个数 if (variables.Length < maxVarLength) { startPos = 0; } else { startPos = 2; if (MessageBox.Show("存储的变量已达到最大个数\n\n若要添加新的变量,则需要删除旧变量'" + variables[0] + "'(它的值为" + variables[1] + ")\n\n是否删除?", "提示", MessageBoxButtons.OKCancel) == DialogResult.Cancel) { txtResult.Text = "变量未存储!"; return; } } string s = variables[startPos]; for (int i = startPos + 1; i < variables.Length; i++) { s += "|" + variables[i]; } Properties.Settings.Default.strVariables = s + "|" + leftValue + "|" + rightResult; Properties.Settings.Default.Save(); txtResult.Text = "变量'" + leftValue + "'已赋值为'" + rightResult + "'"; } #endregion } //更新变量菜单 this.变量ToolStripMenuItem.DropDownItems.Clear(); InsertVarsItem(); //更新算式输入框右键菜单 UpdateMenuRichTextBox(); //更新文本框 txtExp.Text = txtExp.Text; }
/// <summary> /// 计算表达式 /// </summary> private CalResult Calculate() { CalValList valList = null; //记录表达式 memoryExp = txtExp.Text; //删除注释 txtExp.Text = Common.DeleteAnnotate(txtExp.Text, out hasAnnotate); //生成运算因子列表 valList = new CalValList(txtExp.Text); //重新显示表达式 if (hasAnnotate)//有注释 { txtExp.Text = memoryExp; } else//没有注释 { txtExp.Text = valList.nomalStringExpression; } CalResult result = null; if (this.单步计算ToolStripMenuItem.Checked)//单步计算 { completeSteps++; for (int i = 0; i < completeSteps; i++) { //优先级列表为空的情况 if (valList.levelList.Count == 0) { result = valList.CalculateOneStep(); } if (valList.levelList.Count > 0)//如果优先级尚未处理完毕 { result = valList.CalculateOneStep(); } } } else//一次性计算最终结果 { result = valList.Calculate();//计算 } return result; }
/// <summary> /// 存储函数 /// </summary> /// <param name="expr">存储还是替换</param> /// <returns>是否存储成功</returns> private bool StoreFun(string expr) { try { //记录表达式 string tempExpr = funExpr.Text; bool hasAnnotate;//表达式是否有注释 //删除注释 tempExpr = Common.DeleteAnnotate(funExpr.Text, out hasAnnotate); //生成运算因子列表,此过程可以检查表达式是否合法 //若不合法会抛出异常 CalValList valList = new CalValList(tempExpr); //存储函数 string strFun = txtFunName.Text.Trim() + "|" + txtDesc.Text.Trim() + "|" + funExpr.Text.Trim() + "|" + txtFunVars.Text.Trim() + "|" + (cmbFunSort.Text.Trim() == "" ? "其它" : cmbFunSort.Text.Trim()); if (Properties.Settings.Default.funList == null)//判断是否为null { Properties.Settings.Default.funList = new StringCollection(); } Properties.Settings.Default.funList.Add(strFun); Properties.Settings.Default.Save(); if (expr == "重命名") { MessageBox.Show("函数'" + listBox_FunList.SelectedItem.ToString().Split('(')[0] + "'已重命名为'" + txtFunName.Text + "'", "提示"); return true; } MessageBox.Show("函数'" + txtFunName.Text.Trim() + ":" + funExpr.Text.Trim() + "'\n\n" + expr + "成功!", "提示"); return true; } catch { MessageBox.Show("存储失败", "提示"); return false; } }
/// <summary> /// 参数变量列表是否合法 /// </summary> private bool isVarsLegit(out string desc) { desc = "合法"; txtFunVars.Text = txtFunVars.Text.Replace(" ", ""); string[] str = txtFunVars.Text.Trim().Split(','); for (int i = 0; i < str.Length; i++) { //参数变量列表不合法 if (str[i] == "") { desc = "参数变量列表不合法"; return false; } //参数变量不能以数字开头 int n; if (int.TryParse(str[i][0].ToString(), out n)) { desc = "参数变量不能以数字开头"; return false; } //参数变量不能是已存在的函数或常量 CalOpeList opeList = new CalOpeList(); CalOpe ope = opeList.GetOpe(str[i]); if (ope != null) { desc = "参数变量不能是已存在的函数、变量或常量"; return false; } #region 参数变量个数是否与函数表达式中参数变量个数匹配 //记录表达式 string tempExpr = funExpr.Text; bool hasAnnotate;//表达式是否有注释 //删除注释 tempExpr = Common.DeleteAnnotate(funExpr.Text, out hasAnnotate); //生成运算因子列表,此过程可以检查表达式是否合法 //若不合法会抛出异常 CalValList valList = new CalValList(tempExpr); if (!hasAnnotate)//没有注释 { funExpr.Text = valList.nomalStringExpression; } List<string> strVarList = new List<string>();//记录表达式中的参数 //扫描运算因子列表 for (int k = 0; k < valList.valList.Count; k++) { //如果当前运算因子的类型是值类型 if (valList.valList[k].type == ValType.Number) { double d; //如果值类型无法转换为数字 if (!double.TryParse(valList.valList[k].num.stringValue, out d)) { //且没有大于或小于号,为了支持分段函数 if (valList.valList[k].num.stringValue.IndexOf("<") == -1 && valList.valList[k].num.stringValue.IndexOf(">") == -1) { strVarList.Add(valList.valList[k].num.stringValue); } } } } //删除重复 for (int m = 0; m < strVarList.Count; m++) { //逐个扫描当前参数变量后面的参数变量 for (int k = m + 1; k < strVarList.Count; k++) { if (strVarList[k] == strVarList[m])//存在相同的 { strVarList.RemoveAt(k--);//删除相同的变量,注意调整k的值 } } } //如果参数变量个数与函数表达式中参数变量个数不相等 if (strVarList.Count != txtFunVars.Text.Trim().Split(',').Length) { desc = "存储失败!\n\n参数变量过多或过少"; return false; } //检测变量是否对应 //扫描从表达式中取出的每一个函数变量 string[] strParameterList = txtFunVars.Text.Trim().Split(','); for (i = 0; i < strVarList.Count; i++) { bool exists = false; for (int m = 0; m < strParameterList.Length; m++) { if (strVarList[i] == Common.DeleteAnnotate(strParameterList[i], out hasAnnotate)) { exists = true; break; } } if (!exists) { desc = "存储失败!\n\n表达式中的变量与参数列表中的变量不对应"; return false; } } #endregion } return true; }