C#制作简单的计算器(运算级+括号+超长算式处理)

5 篇文章 1 订阅
4 篇文章 2 订阅

计算器做其实很简单,这里的核心算法只需要做到以下几步:(界面等请看后面

1.分割得到的数组(字符串,用Tochararray)再拼接

2.检查(可以自己添加)

3.计算

其中核心的计算方式如下↓↓↓↓↓↓

举个例子,2*3+45,分割后就是'2','*','3','+','4','5'

然后一个for循环将"+","-","*","/"后面的数字(从上一个符号开始)一起拼接起来,最后得到的是2,*,3,+,45.

在检查一下有没有*/,并返回true和false(有,无)

这里结果肯定是true

在进入计算阶段,因为是true,所以遍历到第一个,直到第一个乘号或除号处,把列表的前一个位和后一个位相乘(如果是除法就相除),得到了6,将开始的那个数(2)变成6,再减去列表后面两个值,得到列表为6+45,最后进行加减法(如果是false,上面的乘除法就不用计算了),众所周知,一般来说一个算式它第二个总是“+”,“-”,“×”,“÷”,所以在加减计算中只要将下标为0和下标为2的数按照下标为1的符号计算即可,这里就6(下标为0),+(下标为1),45(下表为2),因为下标1的是+,所以6+45=51,得到的最后的结果就是51

如果说有括号的话,从括号(“(”)处+1的位置添加到一个新列表然后到“)”将里面的项添加到新列表里面就OK了,然后调用一下上面的算法,算出括号里的值,接着把值添加进去同时把列表后面的项删掉,重复此操作直到没有括号,最终再调用一下计算模块即可。

废话不多说直接上代码

        public static double main(string get)
        {
            List<string> li = new List<string>();
            List<int> wh = new List<int>();
            bool hav;
            double final;
            li = Sp(get);
            wh = backet(li);
            hav = have(li);
            if (wh.Count > 1)
            {
                final = ba(wh, li, hav);
            }
            else
            {
                final = calulater(li, hav);
            }
            return final;
        }

        public static List<string> Sp(string input)
        {
            char[] spilt = input.ToCharArray();
            string num = "";
            int where = 0;
            bool whbr = false;
            List<string> get = new List<string>();
            for (int c = 0; c < spilt.Length; c++)
            {
                if (spilt[c] == ')')
                {
                    for (int i = where; i < c; i++)
                    {
                        num = num + spilt[i];
                    }
                    get.Add(num);
                    get.Add(")");
                    where = c + 1;
                    num = "";
                    whbr = true;
                }
                else if (whbr)
                {
                    get.Add(Convert.ToString(spilt[c]));
                    where = c + 1;
                    num = "";
                    whbr = false;
                }
                else if (spilt[c] == '+' || spilt[c] == '-' || spilt[c] == '*' || spilt[c] == '/')
                {
                    for (int i = where; i < c; i++)
                    {
                        num = num + spilt[i];
                    }
                    get.Add(num);
                    switch (spilt[c])
                    {
                        case '+': get.Add("+"); break;
                        case '-': get.Add("-"); break;
                        case '*': get.Add("*"); break;
                        case '/': get.Add("/"); break;
                    }
                    where = c + 1;
                    num = "";
                }
                if (spilt[c] == '(')
                {
                    switch (spilt[c])
                    {
                        case '(': get.Add("("); break;
                    }
                    where = c + 1;
                }

            }
            num = string.Empty;
            if(spilt[spilt.Length-1] != ')')
            {
                for (int i = where; i < spilt.Length; i++)
                {
                    num = num + spilt[i];

                }
                get.Add(num);
            }
            return get;
        }

        public static List<int> backet(List<string> get)
        {
            int num = 0;//括号(组)的个数
            List<int> where = new List<int>();
            for (int i = 0; i < get.Count; i++)
            {
                if (get[i] == "(")
                {
                    num = num + 1;
                    where.Add(i);
                }
                if (get[i] == ")")
                {
                    where.Add(i);
                }
            }
            return where;
        }

        public static bool have(List<string> get)
        {
            bool h = false;
            for (int i = 0; i < get.Count; i++)
            {
                if (get[i] == "*" || get[i] == "/")
                {
                    h = true;
                    return h;
                }
            }
            return h;
        }

        public static double calulater(List<string> get, bool hav)
        {
            int i = 0;
            double c = 0;//计算结果
            bool h;
            if (hav)
            {
                while (true)
                {
                    i++;
                    if (get[i] == "*")
                    {
                        c = int.Parse(get[i - 1]) * int.Parse(get[i + 1]);
                        get[i - 1] = Convert.ToString(c);
                        get.RemoveAt(i);
                        get.RemoveAt(i);
                        i = 0;
                    }
                    else if (get[i] == "/")
                    {
                        if (int.Parse(get[i - 1]) % int.Parse(get[i + 1]) == 0)
                        {
                            c = int.Parse(get[i - 1]) / int.Parse(get[i + 1]);
                            get[i - 1] = Convert.ToString(c);
                            get.RemoveAt(i);
                            get.RemoveAt(i);
                            i = 0;
                        }
                        else
                        {
                            c = double.Parse(get[i - 1]) / double.Parse(get[i + 1]);
                            get[i - 1] = Convert.ToString(c);
                            get.RemoveAt(i);
                            get.RemoveAt(i);
                            i = 0;
                        }
                    }
                    h = have(get);
                    if (!h)
                    {
                        break;
                    }
                    c = 0;
                }
                c = 0;
            }
            if (get.Count != 1)
            {
                while (true)
                {
                    if (get[1] == "+")
                    {
                        c = int.Parse(get[0]) + int.Parse(get[2]);
                        get[0] = Convert.ToString(c);
                        get.RemoveAt(1);
                        get.RemoveAt(1);
                    }
                    else if (get[1] == "-")
                    {
                        c = int.Parse(get[0]) - int.Parse(get[2]);
                        get[0] = Convert.ToString(c);
                        get.RemoveAt(1);
                        get.RemoveAt(1);
                    }
                    c = 0;
                    if (get.Count == 1)
                    {
                        break;
                    }
                }
            }
            return int.Parse(get[0]);
        }

        public static double ba(List<int> b, List<string> get, bool hav)
        {
            List<string> li = new List<string>();
            double re = 0;
            int cut = 0;
            int ci = b.Count / 2;
            List<int> whereba = new List<int>();
            whereba = b;
            for (int i = 0; i < ci; i++)
            {
                for (int j = whereba[0] + 1; j < whereba[1]; j++)
                {
                    li.Add(get[j]);
                    cut = cut + 1;
                }
                cut = cut + 2;
                bool ha = have(li);
                re = calulater(li, ha);
                get[whereba[0]] = Convert.ToString(re);
                for (int k = 0; k < cut - 1; k++)
                {
                    get.RemoveAt(whereba[0] + 1);
                }
                li.Clear();
                whereba = backet(get);
                cut = 0;
            }
            re = calulater(get, hav);
            return re;

        }

注意,在这里面()必须是英文的括号,中文的括号不行!!!

这就是核心算法,当然,还要记得加上一下几段话在调用包下面

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

这些主要调用里面的List

其次就是构造界面:(c#2019,winform窗体应用)

刚开始要添加各个数字按钮,乘除号,=,清除,返回和一个textbox(建议将multiline设置为true会比较好看)

 我是这么排版的,仿照的是windows自带的计算器

接着只要在每一个button(vs双击可以进入button事件)事件里添加如下

        private void button7_Click(object sender, EventArgs e)
        {
            textBox1.Text = textBox1.Text + "1";
        }

同时如果=号控件按下时则调用上面的main方法,将参数设置为textbox1.Text,找一个值储存返回值并在textbox1上面显示,如下↓↓↓↓↓↓

        private void button15_Click(object sender, EventArgs e)
        {
            double re;
            re = main(textBox1.Text);
            textBox1.Text = Convert.ToString(re);
        }

这样就可以了

至于删除清空的内容直接可以用string.Empty或者Remove等方法对字符串进行操作

这个算法整体比较复杂但还是OK的,由于复杂性还可能会出现一些问题,至于算式是否规范可以在button后面写相关的代码,这里给出一些相关的检验方式:

1.看看每一个+-*/前后的数字是否可以被int.Parse转换成数字(这里要用到try……catch),如果是括号则跳过

2.看看除号后下一项是否为0,这个可以在控件中防止如当除号按下时则不能按0(除非已经按了其他数字)

至于更多规定大家可以自己补充说明。

当然,在最后我也把c#计算器最新源码(命令行,非界面)2023.7.4的公布一下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace calulater
{
    internal class Program
    {
        static void Main(string[] vs)
        {
            //数据创建@用户输入
            int have = 0;  //优先级,1代表有*/,0代表无*/
            string input = Console.ReadLine();
            List<string> get = new List<string>();
            int re = 0;       //计算最后的值
            bool ch = false;  //检查是否通过
            int count = 0;    //是否有括号以及括号个数


            char[] spilt = input.ToCharArray();
            string num = "";
            int where = 0;
            bool whbr = false;

            for (int c = 0; c < spilt.Length; c++)
            {
                if (spilt[c] == ')')
                {
                    for (int i = where; i < c; i++)
                    {
                        num = num + spilt[i];
                    }
                    get.Add(num);
                    get.Add(")");
                    where = c + 1;
                    num = "";
                    whbr = true;
                }
                 else if (whbr)
                {
                    get.Add(Convert.ToString(spilt[c]));
                    where = c + 1;
                    num = "";
                    whbr = false;
                 }
                else if (spilt[c] == '+' || spilt[c] == '-' || spilt[c] == '*' || spilt[c] == '/')
                {
                    for (int i = where; i < c; i++)
                    {
                        num = num + spilt[i];
                    }
                    get.Add(num);
                    switch (spilt[c])
                    {
                        case '+': get.Add("+"); break;
                        case '-': get.Add("-"); break;
                        case '*': get.Add("*"); break;
                        case '/': get.Add("/"); break;
                    }
                    where = c + 1;
                    num = "";
                }
                if (spilt[c] == '(')
                {
                    switch (spilt[c])
                    {
                        case '(': get.Add("("); break;
                    }
                    where = c + 1;
                }
            }
            num = "";
            if (spilt[spilt.Length - 1] == ')')
            {
                for (int k = where; k < spilt.Length-1; k++)
                {
                    num = num + spilt[k];
                }
                get.Add(num.ToString());
                get.Add(")");
            }
            else
            {
                for (int k = where; k < spilt.Length; k++)
                {
                    num = num + spilt[k];
                }
                get.Add(num.ToString());
            }




            //检验是否正确
            ch = Check(get);
            have = priority(get);
            if (ch)
            {
                //计算
                count = Brackets(get);
                if (count == 0)
                {
                    re = calulater(get, have);
                }
                else
                {
                    re = calbr(get, have,count);
                }
                Console.WriteLine(re);
            }
        }


        static bool Check(List<string> arr)
        {
            /*
             * 输入值中不可有除加减乘除以及其他数字之外的内容
             * 开头和结尾只能是数字
             * 符号不可并存
             * 除数不能为0
             */
            int get = 0;
            int pass = 0;
            List<string> check = new List<string>(arr);
            for (int i = 0; i < check.Count; i++)
            {
                /*
                if(check[0] != "(" || check[check.Count-1] != ")")
                {
                    if (i == 0 || i == check.Count - 1)
                    {
                        try
                        {
                            get = int.Parse(check[i]);
                        }
                        catch (Exception ax)
                        {
                            Console.WriteLine("接收到异常,发现您的开头或结尾并非数字,请规范您的算式书写:" + ax.Message);
                            return false;
                        }
                    }
                }
                */
                /*
                if (check[i] == "+" || check[i] == "-" || check[i] == "*" || check[i] == "/" )
                {
                    try
                    {
                        get = int.Parse(check[i+1]);
                        get = int.Parse(check[i-1]);
                    }
                    catch (Exception ex)
                    {
                        if(check[i] != "("||check[i] !=")" || check[i+1] != "(" || check[i+1] != ")" || check[i-1] != "(" || check[i-1] != ")")
                        {
                            Console.WriteLine("接收到异常,发现您的输入之中有其他字符,请规范您的算式书写:" + ex.Message);
                            return false;
                        }
                    }
                }
                */
                if ((check[i] == "+" || check[i] == "-" || check[i] == "*" || check[i] == "/") && (check[i + 1] == "+" || check[i + 1] == "-" || check[i + 1] == "*" || check[i + 1] == "/"))
                { 
                    Console.WriteLine("接收到异常,发现您的输入之中加减乘除重叠,请规范您的算式书写");
                    return false;
                }
                if (check[i] == "/")
                {
                    get = int.Parse(check[i + 1]);
                    if (get == 0)
                    {
                        Console.WriteLine("接收到异常,发现您的输入之中除数为0,请规范您的算式书写");
                        return false;
                    }
                }
            }
            return true;
        }





        static int priority(List<string> err)                     //err为列表
        {
            List<string> prior = new List<string>(err);
            for (int i = 0;i < prior.Count; i++)
            {
                if (prior[i] == "*" || prior[i] == "/")
                {
                    return 1;
                }
            }
            return 0;
        }

        static int Brackets(List<string> brr)
        {
            int count = 0;
            List<string> backet = new List<string>(brr);
            for (int i = 0; i < backet.Count; i++)
            {
                if(backet[i] == "(")
                {
                    count = count+1;
                }
            }
            return count;
        }

        static int[,] wherebracket(List<string> crr , int num) // num为括号(组)的个数
        {
            int[,] vs = new int[num, 2];
            int count = 0;
            for (int k = 0; k < crr.Count; k++)
            {
                if (crr[k] == "(")
                {
                    vs[count, 0] = k+1;
                }
                else if (crr[k] == ")")
                {
                    vs[count, 1] = k;
                }
                if(count < num-1)
                {
                    count++;
                }

            }
            return vs;
        }




        static int calulater(List<string> get , int have)
        {
            int answer = 0;
            int m = 0; // m只用于维持列表循环
            int ca = 0; //ca 辅助计算
            int a = 0; // a只用于列表循环
            int b = 0; // b只用于判断列表结束
            int c = 0; // c只用于列表循环
            List<string> cal = new List<string>(get);
            while (m == 0)
            {
                if (have == 1)
                {
                    while (a == 0)
                    {
                        for (int i = 0; i < cal.Count; i++)
                        {
                            if (cal[i] == "*")
                            {
                                ca = int.Parse(cal[i - 1]) * int.Parse(cal[i + 1]);
                                cal[i - 1] = Convert.ToString(ca);
                                cal.RemoveAt(i);
                                cal.RemoveAt(i);
                            }
                            else if (cal[i] == "/")
                            {
                                ca = int.Parse(cal[i - 1]) / int.Parse(cal[i + 1]);
                                cal[i - 1] = Convert.ToString(ca);
                                cal.RemoveAt(i);
                                cal.RemoveAt(i);
                            }
                        }
                        b = priority(cal);
                        if (b == 0)
                        {
                            ca = 0;
                            break;
                        }
                    }
                }
                if (cal.Count > 2)
                {
                    while (c == 0)
                    {
                        if (cal[1] == "+")
                        {
                            ca = int.Parse(cal[0]) + int.Parse(cal[2]);
                            cal[0] = Convert.ToString(ca);
                            cal.RemoveAt(1);
                            cal.RemoveAt(1);
                        }
                        else if (cal[1] == "-")
                        {
                            ca = int.Parse(cal[0]) - int.Parse(cal[2]);
                            cal[0] = Convert.ToString(ca);
                            cal.RemoveAt(1);
                            cal.RemoveAt(1);
                        }
                        if (cal.Count == 1)
                        {
                            break;
                        }
                    }
                }
                break;
            }
            return int.Parse(cal[0]);
        }
        



        static int calbr(List<string> get ,int have, int brackets)
        {
            int[,] calul = new int[brackets, 2];
            calul = wherebracket(get, brackets);
            List<string> brlist = new List<string>();
            int count = 0; //循环的次数
            int cl = 0;
            for (int i = 0; i < brackets; i++)
            {
                for (int j = calul[count, 0]; j < calul[count, 1];j++)
                {
                    brlist.Add(get[j]);
                }
                cl = calulater(brlist, have);
                get[calul[count, 0]] = Convert.ToString(cl);
                get.RemoveRange(calul[count, 0] + 1, calul[count, 1] - calul[count, 0]);
                get.RemoveAt(calul[count, 0]-1);
                cl = 0;
                brlist.Clear();
                count++;
            }
            cl = calulater(get, have);
            return cl;
        }
    }
}

这就是计算器的全部内容了,不过比较简单粗暴,适合编程新手使用和理解,如果有更好的方法的话可以在评论区中点评,谢谢!

  • 24
    点赞
  • 116
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现功能:模拟微软计算器界面,实现四则混合运算1.键盘输入(KeyUp事件)2.无焦点(按钮失去焦点)3.实现优先运算。比如直接输入1-2*3=-5,而不是微软计算器的-34.使用操作工厂,使用接口5.实现菜单里的复制粘贴功能6.可视化文本框7.实现中间操作结果显示8.正则表达式验证输入是否为数字9.小数点个数校验10.使用发消息_Flag实现操作符状态的判定及转换部分注释预览:失去焦点: private void text_display_GotFocus(object sender, EventArgs e) { /* * 文本框的“获取焦点”事件发生时执行的方法。每次获得焦点时,就会执行此方法,使之马上失去焦点。 * * 当某控件的Enable属性变为False的时候,它的焦点将转移到TabIndex属性值比它大1的控件上。 * 这时,如果有多个控件的TabIndex属性值同时比它大1,鼠标点击按钮或敲击键盘时候会发出“咚”的一声。 * 故在本程序中,将label_m控件的TabIndex设为1,其它的全部设为0,因此所有的控件在不可用时焦点都会转移到label_m上, * 因为label_m没有Click和KeyUp事件,所以不会出错。 * 这样就实现了全局无焦点的功能。 * */ text_display.Enabled = false; //先使文本框不可用,这时焦点转移到TabIndex比文本框大的下一个控件上 text_display.Enabled = true; //再使文本框可用,这时焦点不会返回。 }KeyUp事件: else if (e.KeyCode == Keys.NumPad1 || e.KeyCode == Keys.D1) { /* 当窗体的某个控件触发了其本身的KeyUp事件之后, * 将会调用keyUp()方法,并判断是哪个按键 * 如果是大键盘或者是小键盘的1时,便调用num_Click()方法。 * 参数是no_1和e。 * 在这里的no_1指的是按钮no_1,e是KeyUp事件 * no_1是按钮,参数格式正确;而e是KeyUp事件,也是事件的一种。KeyEventHandler当然也是EventHandler的一部分。 * 所以调用了之num_Click()后一切按照no_1按钮事件的操作执行 * 所以no_1按钮的这一句 * this.no_1.KeyUp += new System.Windows.Forms.KeyEventHandler(this.num_Click); * 可以不写 */ num_Click(no_1, e); }小数点点击的校验: private void dot_Click(object sender, EventArgs e) { if (!dotFlag) //没点击的情况下 { if (operFlag) //如果点击了运算符,就将文本换为"0.",并将小数点设为已点击 { text_display.Text = "0."; dotFlag = true; } else if (text_display.Text.Equals("0.")) //如果没有点击运算符,切当前文本是"0.",便保持现状但将小数点设为已点击 { dotFlag = true; } else if (text_display.Text.Equals("0") || text_display.Text.Equals("")) { text_display.Text = "0."; dotFlag = true; } else //其他情况直接添加并将小数点设为已点击 { text_display.Text = text_display.Text + "."; dotFlag = true; } } else //如果已点击则什么也不做 { } enterFlag = false; label_m.Focus(); //键盘按键之后焦点由下面的各个_GotFocus()方法控制;鼠标点击之后的焦点有这条语句控制,同样使焦点转移到label_m上。 }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值