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日

相关文章

  • C# 迭代器分部类与索引器详情

    C#迭代器分部类与索引器是C#语言的两种重要特性,本文将详细讲解它们的使用方法和示例。 迭代器分部类的使用 迭代器分部类是将迭代器(Iterator)功能独立出来的一种分部类,该分部类包含一个枚举(Enumerator)和一个迭代器(Iterator)方法。使用迭代器分部类,可以更方便地进行迭代操作,提高代码的可读性和可维护性。 以下是迭代器分部类的使用示例…

    C# 2023年6月3日
    00
  • javaScript函数中执行C#代码中的函数方法总结

    下面是“javascript函数中执行C#代码中的函数方法”的完整攻略: 1. 我们需要的工具 在本教程中,我们至少需要以下工具和技能: JavaScript编程语言知识 C#编程语言知识 ASP.NET网站开发框架知识 Visual Studio开发环境和WebAssembly工具 2. 构建简单的ASP.NET Core应用程序 为了演示执行C#代码的J…

    C# 2023年6月8日
    00
  • C#实现移除字符串末尾指定字符的方法

    下面是C#实现移除字符串末尾指定字符的方法的完整攻略。 方法一:使用Substring方法 C#中的String类中提供了Substring方法,该方法可以从一个字符串中截取出指定位置的子字符串。利用此特性,可以实现移除字符串末尾指定字符的功能。 具体步骤如下: 判断字符串末尾是否是指定字符 使用String类中的EndsWith方法来判断字符串末尾是否是指…

    C# 2023年6月8日
    00
  • 不使用web服务(Service)实现文本框自动完成扩展

    实现文本框自动完成扩展是一种常见的Web开发任务,它可以帮助用户快速输入和选择文本。在本攻略中,我们将介绍如何不使用Web服务(Service)实现文本框自动完成扩展,并提供两个示例来说明其用法。 以下是两个示例,介绍如何不使用Web服务(Service)实现文本框自动完成扩展: 示例一:使用jQuery UI实现文本框自动完成扩展 首先,我们需要引入jQu…

    C# 2023年5月15日
    00
  • C# 命名空间(Namespace)相关知识总结

    下面我将为你详细讲解C# 命名空间相关知识总结的完整攻略。 什么是命名空间? 命名空间(Namespace)是一种组织代码的机制,可以将相关的类、结构体、接口、枚举等等归到一个命名空间下。在C#中,命名空间就是一组同一类型的程序集,它定义了一个命名上的隔离范围,可以避免命名冲突,同时也可以让代码更加清晰易懂。 如何定义命名空间? 在C#中,我们可以使用关键字…

    C# 2023年6月7日
    00
  • C#用timer实现背单词小程序

    下面是详细的攻略: 1. 准备工作 在开始编写C#背单词小程序之前,需要准备以下工作: 安装Visual Studio开发环境 确认安装了.NET Framework 4.5或以上版本 准备一个背单词的数据源 2. 创建Windows窗体应用 首先,我们需要在Visual Studio中创建一个Windows窗体应用程序,用来作为程序的容器。 3. 设计程序…

    C# 2023年6月1日
    00
  • C# GetEnumerator():返回 IEnumerator 对象,它可用于循环访问集合中的元素

    C#中的GetEnumerator()方法可用于实现自定义迭代器。它基本上是 .NET 迭代器的基础,并且为 LINQ 提供了一个极好的风格。 GetEnumerator()方法概述 GetEnumerator()方法返回一个实现了 IEnumerator 接口的对象。这个接口定义了当前集合中某个位置的元素,以及如何在一个集合中移动以访问其他元素。 实现方式…

    C# 2023年4月19日
    00
  • C# List的赋值问题的解决

    下面我来详细讲解 “C# List的赋值问题的解决” 的攻略。 问题描述 在 C# 中,我们经常需要对 List 进行赋值操作。但是有一些情况下,我们尝试赋值会遇到问题,如下: List<int> list1 = new List<int>{1, 2, 3}; List<int> list2 = list1; list2.…

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