陆陆续续更新这个计算器用了一个礼拜了,今天无论如何也要把它更完。笔者有点追求完美,再者每天都有课,晚上还有作业,还有每晚都会写一些其他的博文。

  上一次漏了写如何实现计算的。思路如下:

  之前得到一个栈2stack2,里面存的是逆波兰式。但是注意了,式子是反过来的。因为栈只能从栈顶写入,从栈顶拿出。所以,必须把栈2的数反过来。

  下面是转换的代码:

        //
//将栈2数值倒过来
//
private void UpSideDown()
{
string[] strTemp = stack2.ToArray(); //将栈stack2数值临时存储在数组里
stack2.Clear(); //将栈stack2清空
for(int i=strTemp.Length-;i>=;i--)
{
stack2.Push(strTemp[i]);
}
}

  将栈的数值倒过来之后,我们就可以进行计算了,计算的思路如下:按下图步骤

  1:从栈顶取元素,如果是数字直接存入新栈 2:如果是操作符,则不存入,将新栈的前两个元素依次取出,先取出的数字放在运算符右边,后取出的放在左边 3:计算的结果放回新栈。重复以上步骤,知道计算完。

  注意!新栈保存的数字,所以要注意栈的类型。

        //
//计算四则运算
//
public double DoMath()
{
var stackTemp = new Stack<double>();
try
{
while (myStack2.Count != )
{
if (!IfNumber(myStack2.Peek()))
{
double d1 = stackTemp.Pop();
double d2 = stackTemp.Pop();
switch (myStack2.Pop())
{
case "+":
stackTemp.Push(d2 + d1);
break;
case "-":
stackTemp.Push(d2 - d1);
break;
case "*":
stackTemp.Push(d2 * d1);
break;
case "/":
stackTemp.Push(d2 / d1);
break;
}//end switch
}//end if
else
{
stackTemp.Push(Convert.ToDouble(myStack2.Pop()));
}
}//end while
return stackTemp.Pop();
}
catch
{
return ;
}
}

  四则混合运算的大体步骤和解决思路就这么多,现在开始解决如何确保用户在乱输入公式以及得到的公式该怎么解析(前面提到的问题:就是当接受了加括号的一元运算符比如:1+(-2)。转换得到的式子是不能正确计算的。)

  思路一:怎么解决用户乱输入数字

  用栈保存用户每次按的按键内容,除了第一次输入外,在每次输入的时候与栈顶元素进行比较。如果连续两次输入操作符,则视第二次有效:

        private string str = "";                                    //声明切定义一个空字符串,用于在label显示用户输入
Stack<string> tempStack = new Stack<string>(); //声明一个数组,用去存储用户输入 //判断用户点击是否有效
public void IfValid(string s)
{
if (tempStack != null)
{
if (Calculate.IfNumber(s)) //如果用户按得是数字,则输入有效
{
tempStack.Push(s);
}
else
{
if (!Calculate.IfNumber(tempStack.Peek())) //如果用户连续两次按的是操作符,则视第二次有效
{
tempStack.Pop();
tempStack.Push(s);
}
else
tempStack.Push(s);
} }//end if
else
{
tempStack.Push(s);
}
str = "";
string[] tempStr = tempStack.ToArray();
//将得到的数组反转
for (int i = ; i < tempStr.Length / ; i++)
{
string temp = tempStr[i];
tempStr[i] = tempStr[tempStr.Length - i - ];
tempStr[tempStr.Length - i - ] = temp;
}
foreach (var item in tempStr)
str += item;
label1.Text = str; }
private void button1_Click(object sender, EventArgs e)
{
IfValid(button1.Text);
} private void button2_Click(object sender, EventArgs e)
{
IfValid(button2.Text);
}

  笔者有很多地方都用到将数组元素前后倒过来的代码,但却没有将其写成独立函数,造成代码的冗余。

  这里代码是写在Form1里的,用到了ReversePolish的IsNumber的方法,因为是不同类的,而且没有ReversePolish就直接调用,所以要把之前定义的修饰private 改成public static修饰才能直接调用。

  思路二:当接受了加括号的一元运算符比如:1+(-2)。通过逆波兰法则转换得到的式子是不能正确计算的。

  把式子进行解析,写成:1+(0-2)的形式!

  代码如下:

  

       string[] strAnalysis;                                           //存放解析完原始计算公式之后的公式
string[] str; //string数组str用于存放原始计算公式//
//解析原始计算公式
//
public void Analysis()
{
var stackTemp = new Stack<string>(); int count = ;
try
{
while (count < strAnalysis.Length)
{
if (strAnalysis[count] == "(" && (strAnalysis[count + ] == "-" || strAnalysis[count + ] == "+")) //如果公式操作数(的后一位操作数是+或则-,
{
stackTemp.Push(strAnalysis[count]);
stackTemp.Push("");
count++;
}
else if (!IfNumber(strAnalysis[count]))
{
stackTemp.Push(strAnalysis[count]);
count++;
}
else if (IfNumber(strAnalysis[count]))
{
string strTemp = "";
while (count < strAnalysis.Length && IfNumber(strAnalysis[count])) //如果是数字,包括小数点.,则拼成一个字符串,直到遇到一个操作符或则数组遍历完毕
{
strTemp += strAnalysis[count];
count++;
}
stackTemp.Push(strTemp);
}
}
}
catch
{
stackTemp = null;
} str = stackTemp.ToArray();
//反转字符串数组
for (int i = ; i < str.Length / ; i++)
{
string temp = str[i];
str[i] = str[str.Length - i - ];
str[str.Length - i - ] = temp;
}
}

  大体思路思路就这么多了,总之是问题逐一突破,把解决的问题方案写成方法,最后凑在一起就成功了。以上的代码并不是所有的代码,笔者只是想把自己的思路分享一下。因为我猜如果我把所有代码都贴出来是要花很长时间看的。毕竟每个人的思维不一样。本人就不擅长读别人的代码T T。

  提示:一般遇到访问内存,比如取栈压栈访问栈顶的代码,最好上异常处理,因为很容易就出现错误。

  欢迎大家提出质疑!

Windows Form简易计算器实现(下)的更多相关文章

  1. C#Windows Form简易计算器实现(上)

    第一次写博客,来分享一个简易计算器的代码.作为一名准程序员,就是要多写代码才能孰能生巧.重视基础知识才能飞的更快更高以及更稳. 代码可能会写的很糟糕,不完美不安全之处希望发现的越多越好 c#编写计算器 ...

  2. C#Windows Form简易计算器实现(中)

    昨天花了一天的时间弄计算器.也算是做出来了,还是简易的(怀疑猿生!!).在此先感谢昨天被我骚扰的朋友. 先贴一张界面看看 其实健壮性还是挺差的,用户体验也是极差的.比如说用户输入了不合理运算式子,我就 ...

  3. 自制c#简易计算器

    这是一个课堂作业,我觉得作为一个简易的计算器不需要态度复杂的东西,可能还有一些bug,有空再慢慢加强. using System;using System.Collections.Generic;us ...

  4. JavaScript简易计算器

    JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标 ...

  5. Windows Form 中快捷键设置

    在Windows Form程序中使用带下划线的快捷键只需要进行设置: 就能够工作.

  6. VS2008 Windows Form项目安装包生成详解

    2008 Windows Form项目的发布对有经验的程序员来说,可能不值一提,但对很多新手来说却不知道如何操作,因为在很多关于Visual Studio的书籍中也没有相关介绍,权威如<C# 2 ...

  7. VISUAL STUDIO 2008 WINDOWS FORM项目发布生成安装包详解(转)

    转自:http://www.cnblogs.com/killerofyang/archive/2012/05/31/2529193.html Visual Studio 2008 Windows Fo ...

  8. PHP学习笔记02——简易计算器

    <!DOCTYPE html> <html> <head> <title>PHP简易计算器</title> </head> &l ...

  9. 菜鸟学习Struts——简易计算器

    这是学习Struts的一个简单的例子文件结构如下: 1.配置Struts环境 2.新建input.jsp,success.jsp,error.jsp input.jsp代码如下: <%@ pag ...

随机推荐

  1. 手机发送短信JS验证

    function tj() { var phone = jQuery('#phone').val(); var code = jQuery('#verificationcode').val(); va ...

  2. SQL Server 后续去除功能汇总

    原文:SQL Server 后续去除功能汇总 功能更新去除汇总 字段类型 在 Microsoft SQL Server 的未来版本中将删除 ntext.text 和 image 数据类型. 请避免在新 ...

  3. 1951: [Sdoi2010]古文字猪

    1951: [Sdoi2010]古代猪文 链接:Click Here~ 题目: 一道非常好的组合数学题.!!.题目非常长.只是就以下几段话实用. iPig认为仅仅要符合文献,每一种能整除N的k都是有可 ...

  4. windows系统SVN和apache的下载和安装

    原文:windows系统SVN和apache的下载和安装 版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明http://ejb3.blogbus.com/logs/107443052. ...

  5. 【分享】史上最全的Python电子书教程资源下载

    网上搜集的,点击即可下载,希望提供给有需要的人^_^   O'Reilly.Python.And.XML.pdf 2.02 MB   OReilly - Programming Python 2nd. ...

  6. 附加被分离DB

    如何附加被分离的质疑数据库?   简介 有些时间,由于日志损坏等原因,导致了数据库质疑.如果此时你分离了数据库,那你会发现你无法再附加上数据库,那后果还是很严重的.因此本文提供了一种方式,可以使得当数 ...

  7. Lazy Scheduler

    Lazy Scheduler:我的轻量级任务调度框架   一.背景 工作中经常涉及任务调度,一直都是采用while(true) => if hitted DO => Thread.Slee ...

  8. soket.io.js + angular.js + express.js(node.js)

    soket.io.js + angular.js + express.js(node.js) 今天搭建个soket.io.js + angular.js + express.js的环境, 采坑无数,特 ...

  9. [置顶] WPF数据修改demo

    今天晚上研究了下wpf,现在把代码贴出来供大家学习参考 sql语句: create table userinfos ( ContactID  int primary key identity(1,1) ...

  10. MySql数据库连接操作

    主要封装为MySqlHelper类 namespace CiWong.LearningLevelApi.MySqlHelp { /// <summary> /// MySqlHelper ...