前言
今天整理我所有写过的文件,发现了一个我C#写过的最长的程序——算式计算器,支持“+”、“-”、“*”、“/”、“%”、“^”和括号整体字符串的计算【当然这个程序在python中可以用两种内置函数print(exal(“算式”))和exec(“print(‘算式’)”)计算打印出来,我不知道C#中有没有这个函数,如果有,那就是我孤陋寡闻了,毕竟不是主学语言…】这个程序的核心步骤就是分解算式字符串,按照运算优先级规则从内到外逐层合并计算,用着最笨的方法完成最简单的计算;另外我在后来新加入了解一元二次方程的功能,算是让它稍微复杂了那么一点点。如果你们有谁喜欢,可以给我点个赞收藏一下,内部有大量注释,可以供给学编程基础的小伙伴当作思路参考。
代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Project5
{
class Program
{
static void Main(string[] args)
{
int kz = 0;//左括号计数变量
int ky = 0;//右括号计数变量
int tjn = 0;//单算式数字计数
int tjs = 0;//单算式符号计数
bool nr = false;//检测除括号和算式符号外是否含有非数字的内部布尔值
bool nrs = false;//检测除括号和算式符号外是否含有非数字的外部布尔值
bool stu = true;//检测是否出现异常输入的算式&是否应该输出结果的布尔值
double num = 0;//尝试转化为double类型语句的(非)变量&指示除数是否为0变量
double temp = 0;//临时变量&单算式结果变量
string str = "";//总算式变量
string strsss = "";//算式临时变量
string strssss = "";//总算式变量副本
while (true)
{
#region 检测输入正确性
kz = 0;
ky = 0;
tjn = 0;
tjs = 0;
nr = false;
nrs = false;
stu = true;
temp = 0;
Console.WriteLine("\n请输入算式,支持的运算符为“+”、“-”、“*”、“/”、“%”、“^”和括号(输入quit退出help查看帮助):");
str = Console.ReadLine().Replace(" ", "").Replace("(", "(").Replace(")", ")");//置换空格和括号中英文
strsss = str;
strssss = str;
if (strsss.ToLower() == "quit")//退出操作
{
break;
}
else if (strsss == "")//未输入操作
{
Console.WriteLine("\n请输入算式或quit或help!");
stu = false;
}
else if (strsss.ToLower() == "help")//帮助操作
{
Console.WriteLine("\n帮助说明:*为乘法,/为除法,%为被除数被除后取的余数,+为加法,-为减法,^为乘方,开方则将指数输为0.5(输入分式请加括号),括号无需指定中英文输入。(新功能:解方程!输入jfc即可进入解一元二次方程功能!)");
stu = false;
}
else if (strsss.ToLower() == "copy" || strsss.ToLower() == "copyright" || strsss.ToLower() == "@")//版权说明操作
{
Console.WriteLine("\n版权 @ 2019-05-31 由 高俊佶 做完 算式计算器。");
Console.WriteLine("高俊佶版权所有 自动化处理算式的计算器。");
Console.WriteLine("完善BUG情况:基本完善,其余基本可忽略。");
stu = false;
}
else if (strsss.ToLower() == "jfc")
{
#region 解方程
double a = 0;
double b = 0;
double c = 0;
string astr = "";
string bstr = "";
string cstr = "";
Console.WriteLine("\n求解方程ax*x+bx+c=0");
Console.WriteLine("请输入a,b,c");
Console.Write("a=");
a = int.Parse(Console.ReadLine());
if (a == 0)
{
Console.WriteLine("该方程不是一元二次方程!");
}
else
{
Console.Write("b=");
b = int.Parse(Console.ReadLine());
Console.Write("c=");
c = int.Parse(Console.ReadLine());
if (a == 1)
{
astr = "x*x";
}
else if (a == -1)
{
astr = "-x*x";
}
else
{
astr = a.ToString() + "x*x";
}
if (b > 0)
{
if (b == 1)
{
bstr = "+x";
}
else
{
bstr = "+" + b.ToString() + "x";
}
}
else if (b == 0)
{
bstr = "";
}
else
{
if (b == -1)
{
bstr = "-x";
}
else
{
bstr = b.ToString() + "x";
}
}
if (c > 0)
{
cstr = "+" + c.ToString();
}
else if (c == 0)
{
cstr = "";
}
else
{
cstr = c.ToString();
}
Console.WriteLine("原方程为:" + astr + bstr + cstr + "=0");
double delt = b * b - 4 * a * c;
if (delt < 0)
{
Console.WriteLine("本方程无实根");
}
else
{
double x1 = ((-1) * b - Math.Sqrt(delt)) / (2 * a);
double x2 = ((-1) * b + Math.Sqrt(delt)) / (2 * a);
Console.WriteLine("方程两实根为:x1={0},x2={1}。", x1, x2);
}
}
#endregion
stu = false;
}
else if (double.TryParse(strsss, out num) == true)//纯数字检查
{
nrs = true;
stu = false;
}
else
{
strsss = strsss.Replace("*-", "*").Replace("/-", "/").Replace("%-", "%").Replace("+-", "+").Replace("--", "-").Replace("^-", "^");//去除算式一般负号
if (strsss[0] == '-' || strsss[0] == '+')
{
strsss = strsss.Substring(1, strsss.Length - 1);//去除算式特殊开头负号和加号
}
strsss = strsss.Replace("(", " ( ").Replace(")", " ) ").Trim();//准备分离括号
var maths = strsss.Split(' ');//用于检测的算式数组
var list = new List<string>(maths);//用于检测的算式列表
foreach (string strs in list)//遍历分辨算式和括号
{
if (strs.IndexOf("(") != -1)//左括号计数
{
if (kz >= ky)
{
kz++;
}
else
{
kz = ky + 1;
break;
}
}
else if (strs.IndexOf(")") != -1)//右括号计数
{
if (kz > ky)
{
ky++;
}
else
{
kz = ky + 1;
break;
}
}
else if (strs == "")//过滤可能存在的空白片段
{
continue;
}
else if (double.TryParse(strs, out num))//对仅存在数字的片段输出算式输入错误
{
nrs = false;
}
else
{
strsss = strs;
if (strs[0] == '-' || strs[0] == '+')
{
strsss = strs.Substring(1, strs.Length - 1);//去除算式特殊开头负号和加号
}
strsss = strsss.Replace(" ", "");//过滤可能存在的空白
string[] nums = strsss.Split('+', '-', '*', '/', '%', '^');//用于检测的单算式数字数组
var lists = new List<string>(nums);//用于检测的单算式数字列表
for (int c = 0; c < nums.Length; c++)
{
lists.Remove("");//去除空白列表项
}
nr = false;
foreach (string t in lists)//遍历每个列表项
{
if (double.TryParse(t, out num) == false)
{
nr = true;
break;
}
}
tjn = tjn + lists.Count();//总数字字符统计,正常的算式总运算符数目应该比总字符减去数字总字符少一
tjs = tjs + nums.Length - 1;//总运算符字符统计,正常的算式总运算符数目应该比总字符减去数字总字符少一
if (nr == true)//间接退出循环
{
nrs = true;
break;
}
}
}
if (tjs != tjn - 1)//判断算式正误
{
nrs = true;
}
}
if (kz != ky)//判断括号情况
{
stu = false;
Console.WriteLine("\n括号输入错误!");
}
else if (nrs == true)//判断算式情况
{
stu = false;
Console.WriteLine("\n算式输入错误!");
}
#endregion
else if (str != "")//算式不为空进入正式计算
{
#region 自动计算算式
int nob = 0;//当前单算式计算时的位置
bool flag = true;//单算式计算总控布尔值
while (flag)
{
if (str.IndexOf("-") != -1)
{
str = str.Replace("*-", "*_").Replace("/-", "/_").Replace("%-", "%_").Replace("+-", "+_").Replace("--", "+").Replace("^-", "^_");//标记算式一般负号
if (str[0] == '+')
{
str = str.Substring(1, str.Length - 1);//除去开头加号
}
if (str.IndexOf("-") == 0)
{
str = "_1*" + str.Substring(1, str.Length - 1);//标记算式开头特殊负号
}
}
if (str.IndexOf("+") == 0)
{
str = str.Substring(1, str.Length - 1);//去除开头多余的加号
}
int index = 0;//当前单算式
str = str.Replace(" ", "").Replace("(", " ( ").Replace(")", " ) ").Trim();//置换空格和括号中英文
string[] strss = str.Split(' ');//算式总&基于括号分离算式的数组
var list = new List<string>(strss);//算式总&基于括号分离算式的列表
for (int i = 1; i < list.Count(); i++)
{
list.Remove("");//去除空白列表项
}
#region 单算式计算
foreach (string t in list)
{
string math = t;//单算式字符串变量
if (math.IndexOf("-") != -1)
{
math = math.Replace("*-", "*_").Replace("/-", "/_").Replace("%-", "%_").Replace("+-", "+_").Replace("--", "+").Replace("^-", "^_");//标记算式一般负号
if (math[0] == '+')
{
math = math.Substring(1, math.Length - 1);//除去开头加号
}
if (math.IndexOf("-") == 0)
{
math = "_1*" + math.Substring(1, math.Length - 1);//标记算式开头特殊负号
}
}
if (math.IndexOf("+") == 0)
{
math = math.Substring(1, math.Length - 1);//去除开头多余的加号
}
if (math.IndexOf("(") == -1 && math.IndexOf(")") == -1)//非括号列表项
{
nob = list.IndexOf(t);
math = math.Replace(" ", "");
math = math.Replace("*", " * ").Replace("/", " / ").Replace("%", " % ").Replace("+", " + ").Replace("-", " - ").Replace("^", " ^ ").Trim();
string[] all = math.Split(' ');//单算式总&基于*/+-分离算式的数组
//string[] nums = math.Split(new string[] { '^', '*', '/', '%', '+', '-' }, StringSplitOptions.RemoveEmptyEntries);
var symbols = new List<string>();//单算式符号&基于*/+-分离算式的列表
var nums = new List<double>();//单算式数字&基于*/+-分离算式的列表
for (int i = 0; i < all.Length; i++)//遍历所有元素
{
if (double.TryParse(all[i], out num) == true || all[i].IndexOf("_") != -1)//找出(有负号标记)的元素
{
all[i] = all[i].Replace("_", "-");//替换负号标记
try
{
nums.Add(Convert.ToDouble(all[i]));//尝试放进数字列表中
}
catch
{
continue;//或用throw;
}
}
else//添加标记符号
{
symbols.Add(all[i]);
}
}
if (nums.Count() == symbols.Count() + 1)//正常的单算式判断
{
while (1 <= symbols.Count())//开始循环计算
{
int condition = 0;//运算符指示变量
if (symbols.IndexOf("^") != -1)
{
condition = 6;
}
else
{
#region 乘除取余处理
if (symbols.IndexOf("*") != -1 && symbols.IndexOf("/") != -1 && symbols.IndexOf("%") != -1)
{
if ((symbols.IndexOf("*") < symbols.IndexOf("/")) && (symbols.IndexOf("*") < symbols.IndexOf("%")))
{
condition = 1;
}
else if ((symbols.IndexOf("/") < symbols.IndexOf("*")) && (symbols.IndexOf("/") < symbols.IndexOf("%")))
{
condition = 2;
}
else
{
condition = 3;
}
}
else if (symbols.IndexOf("*") != -1 && symbols.IndexOf("/") != -1)
{
if ((symbols.IndexOf("*") < symbols.IndexOf("/")))
{
condition = 1;
}
else
{
condition = 2;
}
}
else if (symbols.IndexOf("*") != -1 && symbols.IndexOf("%") != -1)
{
if ((symbols.IndexOf("*") < symbols.IndexOf("%")))
{
condition = 1;
}
else
{
condition = 3;
}
}
else if (symbols.IndexOf("/") != -1 && symbols.IndexOf("%") != -1)
{
if ((symbols.IndexOf("/") < symbols.IndexOf("%")))
{
condition = 2;
}
else
{
condition = 3;
}
}
else
{
if (symbols.IndexOf("*") != -1)
{
condition = 1;
}
else if (symbols.IndexOf("/") != -1)
{
condition = 2;
}
else if (symbols.IndexOf("%") != -1)
{
condition = 3;
}
else
{
#region 加减处理
if (symbols.IndexOf("+") != -1 && symbols.IndexOf("-") != -1)
{
if (symbols.IndexOf("+") < symbols.IndexOf("-"))
{
condition = 4;
}
else
{
condition = 5;
}
}
else
{
if (symbols.IndexOf("+") != -1)
{
condition = 4;
}
else if (symbols.IndexOf("-") != -1)
{
condition = 5;
}
}
#endregion
}
}
#endregion
}
#region 执行处理
num = 0;
switch (condition)// 1为* | 2为/ | 3为% | 4为+ | 5为- | 6为^
{
case 1:
index = symbols.IndexOf("*");
temp = nums[index] * nums[index + 1];
symbols.Remove("*");
break;
case 2:
index = symbols.IndexOf("/");
if (nums[index + 1] == 0)
{
num = 1;
break;
}
temp = (double)nums[index] / nums[index + 1];
symbols.Remove("/");
break;
case 3:
index = symbols.IndexOf("%");
if (nums[index + 1] == 0)
{
num = 1;
break;
}
temp = nums[index] % nums[index + 1];
symbols.Remove("%");
break;
case 4:
index = symbols.IndexOf("+");
temp = nums[index] + nums[index + 1];
symbols.Remove("+");
break;
case 5:
index = symbols.IndexOf("-");
temp = nums[index] - nums[index + 1];
symbols.Remove("-");
break;
case 6:
index = symbols.IndexOf("^");
temp = Math.Pow(nums[index], nums[index + 1]);
symbols.Remove("^");
break;
}
#endregion
if (num == 1)
{
Console.WriteLine("\n除数不能为0!");
flag = false;
stu = false;
break;
}
nums[index + 1] = temp;
nums.Remove(nums[index]);
}
break;//结束当前foreach遍历
}
}
}
#endregion
#region 算式重合成
if (list.IndexOf("(") == -1 && list.IndexOf(")") == -1)//替换不带括号总算式中的单算式
{
list[nob] = Convert.ToString(temp);
}
else//替换带括号总算式中的单算式
{
try
{
list[nob - 1] = Convert.ToString(temp);
list.Remove(list[nob]);
list.Remove(list[nob]);
}
catch
{
continue;//或用throw;
}
}
str = "";
foreach (string n in list)
{
str = str + n;//总算式合成
}
str = str.Replace(" ", "").Replace("(", " ( ").Replace(")", " ) ").Trim();//准备分离括号
if (str.IndexOf("(") == 0 && str.LastIndexOf(")") == str.Length - 1)
{
str = str.Substring(1, str.Length - 2).Replace(" ", "");//除去无用的最外层括号和空格
}
if (double.TryParse(str, out num) == true)
{
flag = false;//当str只剩数字时,退出循环,输出结果
}
#endregion
}
#endregion
}
#region 输出计算结果
while (stu)
{
Console.WriteLine("\n算式 " + strssss + " 计算的结果为:" + str);
break;
}
#endregion
}
}
}
}
结尾
本来看到里面有我名字想去除的,但万一有哪个小姐姐看到了想认识我呢~【/手动调皮/】