/********************************************************************************/
/* 计算器程序 */
/* */
/* 2010-3-8 */
/* */
/* 说明: Calculator类,用于通过给定四则运算表达式, 求出表达式的代数值 */
/* */
/* 示例: #include <iostream> */
/* #include <string> */
/* #include "Calculator.h" */
/* void main() */
/* { */
/* string expression="2.3+(25-0.6*3.2^1.6)/(5-1.5^2)"; */
/* Calculator c(expression); */
/* cout<<c.Run()<<endl; */
/* getchar(); */
/* } */
/* */
/* 输出:9.98791 */
/* */
/********************************************************************************/
//节点类, 用于保存浮点数[flag=0],或者运算符[flag=1]
#pragma region
class Item
{
public:
Item(){} //构造函数
Item(string _value,int _flag) //重载构造函数
{
value=_value; flag=_flag;
}
string value; //保存浮点数,或者运算符
int flag; //标志位
Item& operator=(Item& item) //运算符重载
{
value=item.value;
flag=item.flag;
return *this;
}
};
#pragma endregion
/*===================================================================================*/
/* */
/* 各个算术操作符的优先级 */
/* ------------------------------------------------------------------------------ */
/* | 操作符 | # | ( | ^ | * / % | + - | ) | */
/* ------------------------------------------------------------------------------ */
/* | isp | 0 | 1 | 7 | 5 | 3 | 8 | */
/* ------------------------------------------------------------------------------ */
/* | icp | 0 | 8 | 6 | 4 | 2 | 1 | */
/* ------------------------------------------------------------------------------ */
/* */
/*===================================================================================*/
#pragma region
int isp(string s)
{
if(s=="#")
return 0;
if(s=="(")
return 1;
if(s=="^")
return 7;
if(s=="*"||s=="/"||s=="%")
return 5;
if(s=="+"||s=="-")
return 3;
if(s==")")
return 8;
return -1;
}
int icp(string s)
{
if(s=="#")
return 0;
if(s=="(")
return 8;
if(s=="^")
return 6;
if(s=="*"||s=="/"||s=="%")
return 4;
if(s=="+"||s=="-")
return 2;
if(s==")")
return 1;
return -1;
}
#pragma endregion
#pragma region
class Calculator
{
public:
string expression; //要计算的表达式
DCirList<Item> inlist; //存储中缀表达式的链表
DCirList<Item> postlist; //存储后缀表达式的链表
LinkStack<Item> stack; //存储符号的栈
LinkStack<float> result; //存储结果
Calculator(string _expression); //构造函数
void GetInfix(); //取得中缀表达式
void GetPostfix(); //取得后缀表达式
float Run(); //求结果
};
#pragma endregion
#pragma region
Calculator::Calculator(string _expression)
{
expression=_expression;
expression.append(1,'#');
}
/*====================================================================================*/
/* 字符串转中缀表达式算法: */
/* */
/* 一.从字符串第一个字符开始扫描,遇到数字或小数点,累加该字符到value中,直到遇到运算符. */
/* 将value, 以及此运算符存入到中缀表达式链表. */
/* 二.如果字符串的最后一位为数字, 则扫描完后,直接将value存入到中缀表达式链表. */
/* */
/*====================================================================================*/
void Calculator::GetInfix()
{
string value=""; int flag=0; Item node1,node2;
for(int i=0;i<expression.length();i++)
{
if( (int)expression[i]==46||((int)expression[i]>=48&&(int)expression[i]<=57) )
{
flag=0;
value.append(1,expression[i]);
if(i!=expression.length()-1)
continue;
else
{
node1.value=value; node1.flag=0;
inlist.PushBack(node1);
break;
}
}
if(value!="")
{
node1.value=value; node1.flag=0;
inlist.PushBack(node1);
}
node2.value=expression[i]; node2.flag=1;
inlist.PushBack(node2);
value="";
}
}
/*====================================================================================*/
/* 中缀表达式转化成后缀表达式算法: */
/* */
/* 一.操作符栈初始化,将结束符#进栈,然后读取中缀表达式链表的首个结点元素item. */
/* 二.重复执行以下步骤,直到读到item.value='#', 同时栈顶的操作符也是#, 停止循环. */
/* 1.若item是操作数, 则存入后缀表达式链表,并读取下一个元素. */
/* 2.若item是操作符, 判断item的优先级icp和当前位于栈顶的操作符oper的优先级isp. */
/* 3.(1)若icp(item.value)>isp(oper.value), 令item进栈,并读取下一个元素. */
/* (2)若icp(item.value)<isp(oper.value), 退栈, 并将此元素存入后缀表达式链表. */
/* (3)若icp(item.value)=isp(oper.value), 退栈, 若退出的是'(', 则读取下一个元素. */
/* */
/*====================================================================================*/
void Calculator::GetPostfix()
{
Item item("#",1);
stack.Push(item);
item=inlist.PopFront();
while(!stack.IsEmpty())
{
if(item.flag==0)
{
postlist.PushBack(item);
item=inlist.PopFront();
}
else
{
Item oper=stack.GetTop()->data;
if(isp(oper.value)<icp(item.value))
{
stack.Push(item);
item=inlist.PopFront();
}
else if(isp(oper.value)>icp(item.value))
{
postlist.PushBack(stack.Pop());
}
else
{
if(stack.Pop().value=="(")
item=inlist.PopFront();
}
}
}
}
/*====================================================================================*/
/* 通过后缀表达式计算表达式的值算法: */
/* */
/* 顺序扫描后缀表达式链表的每一项,然后根据它的类型,做如下相应操作: */
/* 1.如果该项是操作数,则将其压入栈中; */
/* 2.如果该项是操作符<op>,则连续从栈中弹出两个操作数Y,X,形成运算指令X<op>Y; */
/* 3.将计算结果重新压入栈中; */
/* 4.当表达式的所有项都扫描或处理完之后,栈顶存放的就是最后的计算结果. */
/*====================================================================================*/
float Calculator::Run()
{
float num1,num2;
while(!postlist.IsEmpty())
{
Item item=postlist.PopFront();
if(item.flag==0)
result.Push(atof(item.value.c_str()));
else
{
if(result.IsEmpty())
Error("取右操作数失败!");
num2=result.Pop();
if(result.IsEmpty())
Error("取左操作数失败!");
num1=result.Pop();
switch(item.value[0])
{
case '+': result.Push(num1+num2); break;
case '-': result.Push(num1-num2); break;
case '*': result.Push(num1*num2); break;
case '/':
{
if(num2==0.0)
{
result.ClearStack();
Error("Divide by 0 !");
}
else
result.Push(num1/num2); break;
}
case '%': result.Push((int)num1%(int)num2); break;
case '^': result.Push(pow(num1,num2)); break;
}
}
}
if(result.IsEmpty())
Error("计算失败!");
return result.Pop();
}
#pragma endregion
分享到:
相关推荐
在本项目中,"数据结构--简易计算器" 是一个基于C语言实现的计算器程序,它展示了数据结构在实际问题中的应用。数据结构是计算机科学中一个核心的概念,它研究如何组织和存储数据,以便高效地访问和操作这些数据。在...
通过这个课程设计,学生不仅能掌握数据结构的运用,还能提升编程技能,理解算法在实际问题中的应用。同时,这也是对软件工程基本原则的实践,包括模块化、测试和文档编写等。总的来说,这个项目是一个全面的编程挑战...
很多涉及计算器程序的的算法都是以栈的相关操作为基础,通过计算器的设计,有利于在学习中更好的理解栈及其相关的操作。 通过对计算器计算过程演示,看到了到它的一些性能及相关优势。 我们在写程序时,大框架已成的...
在本数据结构实验中,我们将探索如何实现一个基于LISP的简易计算器。LISP,全称为“List Processor”,是一种古老而强大的编程语言,以其独特的语法和对递归的高度支持而闻名。这个实验将帮助我们深入理解数据结构,...
总的来说,这个项目涵盖了C++编程、数据结构(栈的实现和应用)、基本的计算逻辑以及UI设计等多个方面,是学习和实践计算机科学基础的好例子。通过完成这样的项目,开发者可以提高编程技巧,理解数据结构的重要性,...
这通常涉及到栈数据结构,因为计算器的运算逻辑遵循后进先出(LIFO)原则。每次点击数字或运算符时,都会将它们压入栈中,当点击等号时,进行计算并弹出结果。这个过程需要理解优先级和括号处理,以确保正确的计算...
在这个“数据结构-科学计算器”的项目中,我们看到一个实际应用,即如何利用数据结构,特别是栈,来实现一个功能丰富的科学计算器。这个计算器不仅能够进行基本的算术运算,还能处理更复杂的科学计算,如对数、指数...
在计算机科学中,数据结构和算法是核心组成部分,它们直接影响程序的效率和功能。本案例主要探讨了如何设计一个计算器的进制转换功能,特别是从十进制到其他进制(如二进制)的转换。以下是这个功能的详细解析: 1....
- 实现一个解析表达式的方法,例如使用栈(Stack)数据结构来处理运算符和操作数,实现逆波兰表示法(Reverse Polish Notation,RPN)算法,也可以称为后缀表达式。 4. **事件处理**: - 在C#中,每个控件都有与...
在这个“数据结构课程设计-计算器”项目中,开发者使用Java编程语言实现了一个能够解析和计算用户输入表达式的计算器程序。这个程序涉及到的主要知识点包括: 1. **数据结构**:计算器的核心是解析和处理数学表达式...
在这个项目中,学生将通过实际操作加深对Java编程语言的理解,同时掌握数据结构的实用技巧,尤其是栈的应用。完成这个项目后,不仅可以提高编程技能,还能为后续的学习和工作中处理更复杂的算法和系统设计打下坚实的...
通过完成这项作业,学生将能够深入理解数据结构(如栈和哈希表)的应用,掌握解析和求解表达式的技术,并熟悉编程语言中的数值处理。同时,这也是一个很好的实践,可以锻炼问题解决、逻辑思考和调试技能。
在本文件中,通过使用C++编程语言,实现了一个基于栈的计算器。该计算器采用两个栈,一个用于...通过这些知识点的学习和理解,我们可以掌握如何使用栈来实现一个基本的计算器程序,并对栈这种数据结构有更深入的认识。
总的来说,这个“数据结构计算器”工程包充分展示了C语言与数据结构的结合应用,尤其是栈的运用,以及如何在Windows环境下构建一个功能丰富的图形用户界面。它对于学习C语言、数据结构和Windows编程的初学者来说,是...
总之,这个实验是一个很好的机会,让学习者亲身体验数据结构如何影响算法的效率和功能,同时加深对堆栈操作的理解。通过这样的实践,我们可以更好地掌握计算机科学的核心概念,并为解决更复杂的问题打下坚实基础。
这个压缩包文件“数据结构课件--严蔚敏”很可能包含了他关于数据结构的教学材料,如PPT课件、讲义、习题解答等,旨在帮助学生深入理解和掌握数据结构的基本概念、算法和应用。 在数据结构的学习中,有以下几个...
在这个实验中,我们将学习如何使用数据结构中的栈来模拟一个简单的计算器,实现加减乘除的功能。这个实验来自武汉理工大学计算机科学与技术学院,旨在帮助学生深入理解数据结构的应用。 首先,栈是一种线性数据结构...
在计算器的实现中,可能用到的数据结构有栈,用于存储计算表达式的运算符和操作数。例如,当我们处理中缀表达式(如2 + 3 * 4)时,可以使用两个栈,一个用于存储运算符,另一个用于存储操作数。通过这种方式,我们...
综合以上信息,我们可以推测这个计算器程序使用C语言编写,采用命令行界面,通过栈来处理括号表达式,其源代码分布在多个文件中,包括主要的计算逻辑(Calc.cpp)、测试代码(test.cpp)、栈实现(Stack.cpp),以及...
总之,数据结构计算器是一个很好的实践项目,它展示了如何利用基础的数据结构——栈,来解决实际问题,同时也为我们提供了学习和理解数据结构及其应用的一个实例。通过分析和实现这样的项目,开发者可以提升在算法...