热门标签 | HotTags
当前位置:  开发笔记 > 小程序 > 正文

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

这篇文章主要介绍了C#利用栈实现加减乘除运算的实现方法,需要的朋友可以参考下

还是有一些小问题....懒得改了,但大体思路还是清晰的,首先定义一个运算符栈,一个数栈。

关于优先级,两个括号(,)优先级最低,其次是+、-,最高的是*、/

关于运算法则,打个比方,"(3+5*4)+3"这个串

首先遇到左括号,直接压入运算符栈,然后是3,直接压入数栈,然后遇到5,压入数栈,遇到*,将其压入运算符栈,遇到右括号,将运算符栈顶的*取出,取出两个数栈栈顶的数,进行乘法运算,将运算结果压入数栈,因为此时运算符栈顶仍不是左括号,取出栈顶的+号,拿出数栈栈顶的两个数,进行加法运算,并将结果压入数栈。此时栈顶是左括号了,那么将左括号弹出栈。此时数栈里还有一个23,运算符栈为空。接着来。此时轮到了+号,直接压入数栈,遇到3,直接压入数栈。此时发现串已经结尾了,但是运算符栈还没有清空。那么就清空吧,把+号拿出来,数栈的23和3拿出来,加法运算,结果压入数栈。此时运算符栈清空,数栈剩个26。这就是最后的结果。是不是很简单但是有一点云里雾里。。

说一下运算规则吧。优先级大家都知道了,优先级从高到低依次是 "*/","+-","()",每当要压运算符时,首先得看看运算符栈里有什么,如果没有,肯定是可以直接压入的,左括号也是可以不管三七二十一直接压入的,除此之外,如果遇到栈顶运算符优先级更高时,是必须将栈顶运算符先取出来运算,直到栈顶元素优先级小于或者等于要压入的运算符的优先级才可压入。比如3*5+5+5,在压入第一个+号时,必须先将栈里的*号先拿出来运算结束后,才能放进去,否则计算结果将是错误的。当压入的是右括号时,必须一直弹运算符栈进行运算,直到遇到左括号为止。当串扫描到末尾时,也必须将运算符栈清空,最后留在数栈的数就是结果。关于小数点,关于复数加减运算,我写的小程序里有了一定的处理

就类似于这样的简单功能。。。。恩,将就看看吧。。程序不完善,不过也懒得改了,毕竟是练习,最近事又多。

下面贴一下源码

主要用到的几个类和方法:

   类Parser   的parse方法,比如给一个“3+4i”的字符串,返回给你一个3个结点的队,队列第一个元素是一个ComplexNumber对象,实数域为3,队列的第二个元素是“+”号,队列第三个元素是一个ComplexNumber对象,实数域为0,虚数域为4。

    类Operators    用于测试字符是否是运算符,用来进行控制运算,比较运算符优先级....

    类Handler   给一个字符串,他帮你处理,返回给你一个结果。其实就是调一下Parser类的方法去解析一下字符串,然后算一下结果,然后返回结果。

 类ComplexNumber,就是复数类啊,不用说了,提供实数域虚数域,getset方法,加减乘除以及toString()方法

using System;
using System.Collections;
using System.Text;
namespace MySpace{
	class Parser{
		public static Queue Parse(string input){
			char[] arr = input.ToCharArray();
			Queue queue = new Queue();
			foreach(char x in arr){
				queue.Enqueue(x);
			}
			queue = ParseStringQueue(queue);
			return queue;
		}
		
		//传入字符串队列,返回封装好的队列。
		//ComplexNumber对象或char类型运算符各占用一个结点
		private static Queue ParseStringQueue(Queue queue){
			Queue secOndQ= new Queue();
			char c;
			StringBuilder sb = null;
			string temp;
			int count = queue.Count;
			bool flag = false; //false表示允许创建新SB对象进行缓存数字字符串
			for(int i=0;i

Don_Yao整合修复一些bug后的代码

using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

// 解析计算字符串公式
namespace CalcuStrFormula
{
  // 处理类
  class Handler
  {
    private Stack _complexNumberStack = new Stack();
    private Stack _operatorStack = new Stack();
    private Parser _parser = new Parser();
    private Operators _operators = new Operators();

    private static Handler _instance;
    public static Handler instance
    {
      get
      {
        if (_instance == null)
        {
          _instance = new Handler();
        }
        return _instance;
      }
    }

    public ComplexNumber Process(string inputString)
    {
      _complexNumberStack.Clear();
      _operatorStack.Clear();

      Queue queue = _parser.Parse(inputString);
      ComplexNumber complexNumber = null;
      char op, topOp;
      int count = queue.Count;
      for (int i = 0; i  queueChar = new Queue();
      foreach (char x in arr)
      {
        queueChar.Enqueue(x);
      }
      Queue queueResult = ParseStringQueue(queueChar);
      return queueResult;
    }

    // 传入字符串队列,返回封装好的队列。
    // ComplexNumber对象或char类型运算符各占用一个结点
    private Queue ParseStringQueue(Queue queue)
    {
      Queue secOndQ= new Queue();
      char c;
      StringBuilder sb = null;
      string temp;
      int count = queue.Count;
      bool flag = false; // false表示允许创建新SB对象进行缓存数字字符串
      for (int i = 0; i = c.GetRealPart()) return this;
      return c;
    }
    // 转int
    public ComplexNumber ToFloorInt()
    {
      _realPart = Math.Floor(_realPart);
      return this;
    }

    public override string ToString()
    {
      return "(" + _realPart + " + " + _imaginPart + " i" + ")";
    }
  }

  // 操作符类
  class Operators
  {
    private char[][] _signOperator;

    public Operators()
    {
      // 从上到下,优先级由高到低
      _signOperator = new char[4][];
      _signOperator[0] = new char[4];
      _signOperator[0][0] = '^';
      _signOperator[0][1] = 's'; // 最小值
      _signOperator[0][2] = 'b'; // 最大值
      _signOperator[0][3] = 'i'; // int值
      _signOperator[1] = new char[2];
      _signOperator[1][0] = '*';
      _signOperator[1][1] = '/';
      _signOperator[2] = new char[2];
      _signOperator[2][0] = '+';
      _signOperator[2][1] = '-';
      _signOperator[3] = new char[2];
      _signOperator[3][0] = '(';
      _signOperator[3][1] = ')';
    }

    // 比较操作符优先级
    public int ComparePriority(char firstSign, char secondSign)
    {
      int priorityF = 0, priorityS = 0;
      for (int i = 0; i <_signOperator.Length; i++)
      {
        foreach (char x in _signOperator[i])
        {
          if (firstSign == x)
          {
            priorityF = i;
          }
          if (secOndSign== x)
          {
            priorityS = i;
          }
        }
      }

      return (priorityF - priorityS);
    }

    // 是否是需要两个参数的操作符
    public bool IsTwoNumOperator(char op)
    {
      if (op == 'i') return false;
      return true;
    }

    public bool Contains(char x)
    {
      if (x == '(' || x == ')')
      {
        UnityEngine.Debug.LogError(x + "为中文字符,请改为英文字符");
      }

      foreach (char[] arr in _signOperator)
      {
        foreach (char y in arr)
        {
          if (x == y)
          {
            return true;
          }
        }
      }
      return false;
    }

    public ComplexNumber Compute(char op, ComplexNumber c1, ComplexNumber c2)
    {
      ComplexNumber result = null;
      switch (op)
      {
        case '+': result = c1.ComplexAdd(c2); break;
        case '-': result = c1.ComplexMinus(c2); break;
        case '*': result = c1.ComplexMulti(c2); break;
        case '/': result = c1.ComplexDivision(c2); break;
        case '^': result = c1.ComplexPow(c2); break;
        case 's': result = c1.ComplexMinimum(c2); break;
        case 'b': result = c1.ComplexMaximum(c2); break;
        case 'i': result = c2.ToFloorInt(); break;
      }
      return result;
    }
  }
}

这篇文章就介绍到这了,希望能帮助到你。


推荐阅读
  • 程序员如何优雅应对35岁职业转型?这里有深度解析
    本文探讨了程序员在职业生涯中如何通过不断学习和技能提升,优雅地应对35岁左右的职业转型挑战。我们将深入分析当前热门技术趋势,并提供实用的学习路径。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • 在项目中使用 Redis 时,了解其不同架构模式(如单节点、主从复制、哨兵模式和集群)对于确保系统的高可用性和扩展性至关重要。本文将详细探讨这些模式的特点和应用场景。 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
  • 本文详细介绍了Java的安装、配置、运行流程以及有效的学习方法,旨在帮助初学者快速上手Java编程。 ... [详细]
  • 深入解析Android自定义View面试题
    本文探讨了Android Launcher开发中自定义View的重要性,并通过一道经典的面试题,帮助开发者更好地理解自定义View的实现细节。文章不仅涵盖了基础知识,还提供了实际操作建议。 ... [详细]
  • C语言基础入门:7个经典小程序助你快速掌握编程技巧
    本文精选了7个经典的C语言小程序,旨在帮助初学者快速掌握编程基础。通过这些程序的实践,你将更深入地理解C语言的核心概念和语法结构。 ... [详细]
  • 2020初级电工模拟题库与实操视频指南
    本文提供2020年初级电工模拟考试题库及实操视频资源,涵盖最新大纲和真题解析,帮助考生高效备考。内容包括理论知识、实操技能以及详细答案解析,适用于全国各地区电工(初级)考试。 ... [详细]
  • 本教程将详细介绍Python中的包、模块、类和函数的概念,探讨它们在程序中的作用及相互关系,帮助读者更好地理解Python的结构化编程。 ... [详细]
  • 云函数与数据库API实现增删查改的对比
    本文将深入探讨使用云函数和数据库API实现数据操作(增删查改)的不同方法,通过详细的代码示例帮助读者更好地理解和掌握这些技术。文章不仅提供代码实现,还解释了每种方法的特点和适用场景。 ... [详细]
  • 国庆头像生成小程序体验
    介绍一个可以快速生成带有国旗元素的国庆头像的小程序,带您回顾这一流行趋势。 ... [详细]
  • 微信小程序:授权登录与手机号绑定
    本文详细介绍了微信小程序中用户授权登录及绑定手机号的流程,结合官方指引和实际开发经验,提供了一套完整的实现方案,帮助开发者更好地理解和应用。 ... [详细]
  • 在使用Netty 4.1.48版本运行自带的HTTP服务器示例时,观察到大量本地IP环回连接。本文将探讨这些环回连接的原因,并解释其与TCP连接的关系。 ... [详细]
  • 使用JS、HTML5和C3创建自定义弹出窗口
    本文介绍如何结合JavaScript、HTML5和C3.js来实现一个功能丰富的自定义弹出窗口。通过具体的代码示例,详细讲解了实现过程中的关键步骤和技术要点。 ... [详细]
  • 本文深入探讨了小程序中父组件与子组件之间的数据传递方式,特别是通过事件触发和属性绑定实现的值传递机制。文中详细介绍了如何从子组件向父组件传递数据,并进一步由父组件传递给其他子组件。 ... [详细]
author-avatar
书友31617792
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有