/// <summary> /// 运算因子(数字、常数及运算符)列表合法性检查,并规范化 /// </summary> private void ToNormalList() { CalOpeList opeList = new CalOpeList(); #region 第一次处理 //第一次处理,如sin2pi,转换成sin(2pi) for (int i = 0; i < valList.Count; i++) { //如果是数字 if (valList[i].type == ValType.Number) { //如果前面是左括号 if (i - 1 >= 0 && valList[i - 1].OpeType == OpeType.leftParenthesis) { continue; } //如果前面是一个参数的函数 if (i - 1 >= 0 && valList[i - 1].OpeType == OpeType.right && valList[i - 1].ParameterNumber == 1) { //如果下一个是常数 if (i + 1 < valList.Count && valList[i + 1].OpeType == OpeType.noParameter) { Insert(opeList.GetOpe(")"), i + 2); Insert(opeList.GetOpe("("), i); i++; } } } } #endregion #region 第二次处理 //第二次处理,如sin30度,转换为sin(30度) for (int i = 0; i < valList.Count - 1; i++) { //如果是参数在右边的单目运算符 if (valList[i].OpeType == OpeType.right && valList[i].ParameterNumber == 1) { //如果下一个是运算符且是左括号 if (valList[i + 1].OpeType == OpeType.leftParenthesis) { continue; } //如果下一个是常数或数字 if (valList[i + 1].OpeType == OpeType.noParameter || valList[i + 1].type == ValType.Number) { //如果下下个运算符是参数在左边的运算符 if (i + 2 < valList.Count && valList[i + 2].OpeType == OpeType.left) { Insert(opeList.GetOpe(")"), i + 3); Insert(opeList.GetOpe("("), i + 1); i++; } else { Insert(opeList.GetOpe(")"), i + 2); Insert(opeList.GetOpe("("), i + 1); i++; } } } } #endregion #region 第三次处理 //第三次处理,如3+-3转换为3+(-3) for (int i = 1; i < valList.Count - 1; i++) { //如果是'+'或'-'运算符 if (valList[i].OpeType == OpeType.PlusOrMinus) { //如果前一个是运算符且类型如下 if (valList[i - 1].OpeType == OpeType.PlusOrMinus || valList[i - 1].OpeType == OpeType.bothSides || valList[i - 1].OpeType == OpeType.right) { //如果下一个是数字或常数 if (valList[i + 1].type == ValType.Number || valList[i + 1].OpeType == OpeType.noParameter) { Insert(opeList.GetOpe(")"), i + 2); Insert(opeList.GetOpe("("), i); i++; } } } } #endregion #region 第四次处理 //第四次处理,判断表达式是否合法,并在合适的地方插入乘号 for (int i = 0; i < valList.Count - 1; i++) { #region 当前运算因子是数字 if (valList[i].type == ValType.Number)//数字 { if (valList[i + 1].type == ValType.Operator)//右边是运算符 { switch (valList[i + 1].OpeType) { case OpeType.bothSides://正确 break; case OpeType.left://正确 break; case OpeType.leftParenthesis: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.noParameter: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.PlusOrMinus://正确 break; case OpeType.right: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.rightParenthesis://正确 break; case OpeType.Separator://正确 break; } } else//右边是数字 { Insert(opeList.GetOpe("*"), i + 1); } } #endregion #region 当前运算因子是运算符 if (valList[i].type == ValType.Operator)//运算符 { #region 当前运算符右边是运算符 if (valList[i + 1].type == ValType.Operator)//右边是运算符 { switch (valList[i].OpeType)//左运算符 { #region case OpeType.bothSides://左运算符参数信息 case OpeType.bothSides://左运算符参数信息 switch (valList[i + 1].OpeType)//右运算符 { case OpeType.bothSides: MakeException(i); break; case OpeType.left: MakeException(i); break; case OpeType.leftParenthesis://正确 break; case OpeType.noParameter://正确 break; case OpeType.PlusOrMinus: MakeException(i); break; case OpeType.right://正确 break; case OpeType.rightParenthesis: MakeException(i); break; case OpeType.Separator: MakeException(i); break; } break; #endregion #region case OpeType.left://左运算符参数信息 case OpeType.left://左运算符参数信息 switch (valList[i + 1].OpeType)//右运算符 { case OpeType.bothSides://正确 break; case OpeType.left://正确 break; case OpeType.leftParenthesis: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.noParameter: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.PlusOrMinus://正确 break; case OpeType.right: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.rightParenthesis://正确 break; case OpeType.Separator: //正确 break; } break; #endregion #region case OpeType.leftParenthesis://左运算符参数信息 case OpeType.leftParenthesis://左运算符参数信息 switch (valList[i + 1].OpeType)//右运算符 { case OpeType.bothSides: int pos = i + 1 >= 0 ? i + 1 : i; MakeException(pos); break; case OpeType.left: pos = i + 1 >= 0 ? i + 1 : i; MakeException(pos); break; case OpeType.leftParenthesis://正确 break; case OpeType.noParameter://正确 break; case OpeType.PlusOrMinus://正确 break; case OpeType.right://正确 break; case OpeType.rightParenthesis: pos = i - 1 >= 0 ? i - 1 : i; MakeException(pos); break; case OpeType.Separator: pos = i - 1 >= 0 ? i - 1 : i; MakeException(pos); break; } break; #endregion #region case OpeType.noParameter://左运算符参数信息 case OpeType.noParameter://左运算符参数信息 switch (valList[i + 1].OpeType)//右运算符 { case OpeType.bothSides://正确 break; case OpeType.left://正确 break; case OpeType.leftParenthesis: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.noParameter: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.PlusOrMinus://正确 break; case OpeType.right: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.rightParenthesis://正确 break; case OpeType.Separator: //正确 break; } break; #endregion #region case OpeType.PlusOrMinus://左运算符参数信息 case OpeType.PlusOrMinus://左运算符参数信息 switch (valList[i + 1].OpeType)//右运算符 { case OpeType.bothSides: MakeException(i); break; case OpeType.left: MakeException(i); break; case OpeType.leftParenthesis://正确 break; case OpeType.noParameter://正确 break; case OpeType.PlusOrMinus: MakeException(i); break; case OpeType.right://正确 break; case OpeType.rightParenthesis: MakeException(i); break; case OpeType.Separator: MakeException(i); break; } break; #endregion #region case OpeType.right://左运算符参数信息 case OpeType.right://左运算符参数信息 switch (valList[i + 1].OpeType)//右运算符 { case OpeType.bothSides: MakeException(i); break; case OpeType.left: MakeException(i); break; case OpeType.leftParenthesis://正确 break; case OpeType.noParameter: MakeException(i); break; case OpeType.PlusOrMinus: MakeException(i); break; case OpeType.right: MakeException(i); break; case OpeType.rightParenthesis: MakeException(i); break; case OpeType.Separator: MakeException(i); break; } break; #endregion #region case OpeType.rightParenthesis://左运算符参数信息 case OpeType.rightParenthesis://左运算符参数信息 switch (valList[i + 1].OpeType)//右运算符 { case OpeType.bothSides://正确 break; case OpeType.left://正确 break; case OpeType.leftParenthesis: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.noParameter: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.PlusOrMinus://正确 break; case OpeType.right: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.rightParenthesis://正确 break; case OpeType.Separator://正确 break; } break; #endregion #region case OpeType.Separator://左运算符参数信息 case OpeType.Separator://左运算符参数信息 switch (valList[i + 1].OpeType)//右运算符 { case OpeType.bothSides: MakeException(i + 1); break; case OpeType.left: MakeException(i + 1); break; case OpeType.leftParenthesis://正确 break; case OpeType.noParameter://正确 break; case OpeType.PlusOrMinus://正确 break; case OpeType.right://正确 break; case OpeType.rightParenthesis: MakeException(i); break; case OpeType.Separator: MakeException(i); break; } break; #endregion } } #endregion #region 当前运算符右边是数字 else if (valList[i + 1].type == ValType.Number)//运算符右边是数字 { switch (valList[i].OpeType) { case OpeType.bothSides://正确 break; case OpeType.left: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.leftParenthesis://正确 break; case OpeType.noParameter: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.PlusOrMinus://正确 break; case OpeType.right: MakeException(i); break; case OpeType.rightParenthesis: Insert(opeList.GetOpe("*"), i + 1); break; case OpeType.Separator: //正确 break; } } #endregion } #endregion } #endregion #region 第五次处理 //检查表达式的开头和结尾(第四次处理检查不到的地方)、数字两边括号 //*9不合法 //8-不合法 //nCr(9,8,7)不合法 //(9)%处理成9% for (int i = 0; i < valList.Count; i++)//逐个扫描 { #region 如果是运算符 if (valList[i].type == ValType.Operator)//如果是运算符 { switch (valList[i].OpeType) { case OpeType.bothSides: if (!(i - 1 >= 0 && i + 1 < valList.Count)) { MakeException(i); } break; case OpeType.left: if (!(i - 1 >= 0)) { MakeException(i); } break; case OpeType.leftParenthesis: if (!(i + 1 < valList.Count)) { MakeException(i); } break; case OpeType.noParameter: break; case OpeType.PlusOrMinus: if (!(i + 1 < valList.Count)) { MakeException(i); } break; case OpeType.right: if (!(i + 1 < valList.Count)) { MakeException(i); } break; case OpeType.rightParenthesis: if (!(i - 1 >= 0)) { MakeException(i); } break; case OpeType.Separator: if (!(i - 1 >= 0 && i + 1 < valList.Count)) { MakeException(i); } break; } } #endregion #region 如果是数字 if (valList[i].type == ValType.Number)//如果是数字 { if (i - 1 >= 0 && i + 1 < valList.Count) { //两边同时为括号 if (valList[i - 1].OpeType == OpeType.leftParenthesis && valList[i + 1].OpeType == OpeType.rightParenthesis) { //如sin(9-7),average(9-7) if (!(i - 2 >= 0 && valList[i - 2].OpeType == OpeType.right)) { ReplaceVal(valList[i].num, 3, i - 1); } } } } #endregion } #endregion }
/// <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; }
/// <summary> /// 输入运算符 /// </summary> /// <param name="sender"></param> private void InputOpe(object sender) { string[] tagList = ((Control)sender).Tag.ToString().Split('|'); //输入运算符 if (tagList[0] != "") { string str = tagList[0]; //对于函数,输入左括号 CalOpeList opeList = new CalOpeList(); if (opeList.GetOpe(((Control)sender).Tag.ToString()) != null && opeList.GetOpe(((Control)sender).Tag.ToString()).opeType == OpeType.right) { str += "("; } //输入运算符 Input(str); } }
/// <summary> /// 是否负号 /// </summary> /// <param name="strExp">已输入的表达式</param> /// <param name="tag">当前符号</param> public static bool isSubtractive(string strExp, string tag, int selectionStart) { bool result = false;//默认不是负号 if (tag == "-") { strExp = strExp.Substring(0, selectionStart).Replace(" ", ""); if (strExp.Length == 1)//只有一个符号 { result = true; } else { //科学计数法的情况 if (strExp[strExp.Length - 2] == 'E') { result = true; } //前面是'='号的情况 if (strExp[strExp.Length - 2] == '=') { result = true; } CalOpeList opeList = new CalOpeList(); CalOpe ope = null; //检测tag前面有没有运算符 for (int i = 0; i < strExp.Length; i++) { //从长字符串到短字符串检测 string subStr = strExp.Substring(i, strExp.Length - i - 1); ope = opeList.GetOpe(subStr);//查找运算符 if (ope != null)//找到运算符 { break; } } if (ope != null)//找到运算符 { //检测运算符种类 if (ope.opeType == OpeType.bothSides || ope.opeType == OpeType.leftParenthesis || ope.opeType == OpeType.PlusOrMinus || ope.opeType == OpeType.right || ope.opeType == OpeType.Separator) { result = true; ; } } } } return result; }