C#利用栈实现加减乘除运算

C#利用栈实现加减乘除运算攻略

背景

在程序设计中,实现加减乘除运算是非常基础和常见的需求。而在计算表达式时,我们可以利用栈的特性来进行运算,这样可以避免使用递归等复杂的算法。本篇文章将介绍如何使用C#语言利用栈实现加减乘除运算。

方案

1.利用栈实现加减运算

我们可以使用两个栈numStackopStack,分别存放数字和操作符。具体的方法如下:

1.1. 遍历待计算的字符串,依次处理每一个字符。
1.2. 如果遇到数字,将其入数字栈numStack
1.3. 如果遇到操作符,分两种情况处理:
1.3.1. 如果操作符栈opStack为空,则将操作符直接入栈。
1.3.2. 如果操作符不为空,比较当前操作符和操作符栈顶的优先级。如果当前操作符优先级不高于栈顶操作符,则从数字栈numStack中取出两个数进行运算,并将结果入栈numStack,重复此过程直到当前操作符优先级高于栈顶操作符或操作符栈为空,最后将当前操作符入栈opStack
1.4.字符遍历结束后,如果操作符栈不为空,则依次取出操作符和数字进行运算。

下面是使用上述算法计算表达式(4+2)*5-3的演示(代码中用#表示空栈):

numStack:   # 4  6  6  6  5  2  30  30  27
opStack:    # +  #  *  -  *  +   #   #   #

具体实现可以参考以下代码示例:

public static double Eval(string expr)
{
    var numStack = new Stack<double>();
    var opStack = new Stack<char>();
    for (int i = 0; i < expr.Length; i++)
    {
        if (char.IsDigit(expr[i]))
        {
            // 提取数字
            int j = i + 1;
            while (j < expr.Length && (char.IsDigit(expr[j]) || expr[j] == '.')) j++;
            numStack.Push(double.Parse(expr.Substring(i, j - i)));
            i = j - 1;
        }
        else
        {
            // 提取操作符
            char op = expr[i];
            while (opStack.Count > 0 && Priority(op) <= Priority(opStack.Peek()))
                numStack.Push(Compute(opStack.Pop(), numStack.Pop(), numStack.Pop()));
            opStack.Push(op);
        }
    }
    while (opStack.Count > 0)
        numStack.Push(Compute(opStack.Pop(), numStack.Pop(), numStack.Pop()));
    return numStack.Pop();
}

private static double Compute(char op, double a, double b)
{
    switch (op)
    {
        case '+': return b + a;
        case '-': return b - a;
        case '*': return b * a;
        case '/': return b / a;
        default: throw new ArgumentException($"Invalid operator \"{op}\".");
    }
}

private static int Priority(char op)
{
    switch (op)
    {
        case '+':
        case '-': return 1;
        case '*':
        case '/': return 2;
        default: throw new ArgumentException($"Invalid operator \"{op}\".");
    }
}

1.2. 利用栈实现加减乘除运算

在进行加减运算时,我们已经使用了栈来处理。接下来我们将介绍如何利用栈实现乘除运算的处理。具体的方法如下:

1.2.1. 遍历待计算的字符串,依次处理每一个字符。
1.2.2. 如果遇到数字,将其入数字栈numStack
1.2.3. 如果遇到乘或除操作符,取出数字栈numStack的栈顶元素a,并再次取出数字栈numStack的栈顶元素b,计算ba的乘(或除)积,并将结果压入数字栈numStack
1.2.4. 如果遇到加或减操作符,则先将其入操作符栈opStack

下面是使用上述算法计算表达式(4+2)*5/3的演示(代码中用#表示空栈):

numStack:   # 4  6 30  10  3.33333333333333
opStack:    # +  #  *   /   #

具体实现可以参考以下代码示例:

public static double Eval(string expr)
{
    var numStack = new Stack<double>();
    var opStack = new Stack<char>();
    for (int i = 0; i < expr.Length; i++)
    {
        if (char.IsDigit(expr[i]))
        {
            // 提取数字
            int j = i + 1;
            while (j < expr.Length && (char.IsDigit(expr[j]) || expr[j] == '.')) j++;
            numStack.Push(double.Parse(expr.Substring(i, j - i)));
            i = j - 1;
        }
        else if (expr[i] == '*' || expr[i] == '/')
        {
            // 计算乘(或除)积
            double a = numStack.Pop();
            double b = numStack.Pop();
            numStack.Push(Compute(expr[i], a, b));
        }
        else if (expr[i] == '+' || expr[i] == '-')
        {
            // 入操作符栈
            opStack.Push(expr[i]);
        }
    }
    while (opStack.Count > 0)
    {
        char op = opStack.Pop();
        double a = numStack.Pop();
        double b = numStack.Pop();
        numStack.Push(Compute(op, a, b));
    }
    return numStack.Pop();
}

private static double Compute(char op, double a, double b)
{
    switch (op)
    {
        case '+': return b + a;
        case '-': return b - a;
        case '*': return b * a;
        case '/': return b / a;
        default: throw new ArgumentException($"Invalid operator \"{op}\".");
    }
}

结论

利用栈实现加减乘除运算,不仅比递归等算法容易理解,而且还可以避免出现栈溢出等问题,因此在程序设计中非常实用。本篇文章给出了两种实现方法,读者可以根据实际需求选择适合的方法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#利用栈实现加减乘除运算 - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • Unity中协程IEnumerator的使用方法介绍详解

    针对“Unity中协程IEnumerator的使用方法介绍详解”这个话题,以下是详细的攻略: 什么是协程? 协程是一个非常重要的Unity中的功能,它可以让你在程序执行期间暂停执行当前方法,进行一段时间的等待,然后再继续执行这个方法。通过协程,你可以创建更加动态、流畅的游戏体验。 协程的使用方法 在Unity中,协程的使用方法非常简单,我们只需要使用IEnu…

    C# 2023年6月3日
    00
  • C#泛型接口的协变和逆变

    C#泛型接口的协变和逆变是指能够使泛型对象之间存在子类关系的一种特性,使接口的使用更加灵活方便。在使用泛型接口时,可以使用协变和逆变的特性来增强程序的稳健性和可扩展性。 什么是协变和逆变 在 C# 中,协变和逆变是指参数类型的转换。在泛型接口中,接口定义了必须实现的方法,而协变和逆变则影响了实现这些方法的类的类型关系。 协变:从派生类向基础类转换。也就是说,…

    C# 2023年5月15日
    00
  • ASP.NET(C#) String, StringBuilder 与 StringWriter性能比较

    ASP.NET是一种广泛使用的Web应用程序框架,C#是一种强类型面向对象的编程语言。在开发ASP.NET应用程序时,我们常常需要使用字符串操作,其中包括String、StringBuilder和StringWriter这三种不同的类型。这三种类型有着不同的性能特点,需要根据具体的情况来选择使用。 1. String String是C#中常用的字符串类型,它…

    C# 2023年6月3日
    00
  • 使用数字签名实现数据库记录防篡改(Java实现)

    使用数字签名实现数据库记录防篡改是一种常见的数据安全保护方法。以下是使用Java实现数字签名的完整攻略。 环境准备 在使用Java实现数字签名前,需要确保以下环境已经准备好: JDK已经安装并配置好了环境变量。 项目中已经添加了需要引入的包的依赖。 实现数字签名 以下是使用Java实现数字签名的步骤: 步骤1:生成密钥对 使用Java的KeyPairGene…

    C# 2023年5月15日
    00
  • C# lambda表达式原理定义及实例详解

    C# lambda表达式原理定义及实例详解 1. 什么是lambda表达式 Lambda表达式是一种能够把代码作为一个参数传递的匿名函数。它是从LISP借鉴过来的一个概念,相当于是在代码里面定义一个函数,然后直接把这个函数作为一个参数传递给另一个函数,简化了代码的书写。在C#中,Lambda表达式是Func<>或Action<> 或 …

    C# 2023年6月7日
    00
  • c# 单例模式的实现

    当在 C# 中开发应用程序时,善于使用设计模式是非常重要的。单例模式是一种常用的模式,它用于确保一个类只有一个实例,并提供全局访问点。 以下是实现单例模式的典型步骤: 步骤一:声明一个私有的构造函数 单例模式的首要目标是保证一个类只创建一个对象,并允许客户端代码访问实例。为了控制类的实例化,需要阻止类外部的代码调用构造函数。可以通过将构造函数的访问权限设置为…

    C# 2023年5月31日
    00
  • C#访问C++动态分配的数组指针(实例讲解)

    初步分析这个问题,我们可以将其分为以下几个部分来进行回答: 什么是C++动态分配的数组指针? 为什么需要使用C#来访问C++动态分配的数组指针? 怎么使用C#来访问C++动态分配的数组指针? 示例说明。 下面逐一进行回答。 1. 什么是C++动态分配的数组指针? C++中的数组指针,是指指向数组的指针。动态分配的数组指针是指,程序在运行时根据需要动态分配内存…

    C# 2023年6月7日
    00
  • 盘点C# 9.0中好用的特性

    顶级语句 将类和类里面Main函数省略,只留下核心的逻辑代码就是顶级语句! 1.顶级语句1 await System.Threading.Tasks.Task.Delay(1000); System.Console.WriteLine(“Hi!”); return 0; static class $Program { static async Task&lt…

    C# 2023年4月24日
    00
合作推广
合作推广
分享本页
返回顶部