这是我的实验报告,原封不动地弄上来了,本来是给老师看的呢。
项目名称:实现四则运算:
项目实施方法:建立一个栈,并建立两个对象,用来对操作符和操作数进行操作。从左至右对输入的文本进行扫描,将相应的操作符和操作数进行压入,然后进行相应的运算。
我使用了memcpy函数,起初担心memcpy函数的效率问题,但是网络上是这样回答的。
“最近又听到有人在讲memcpy的效率问题,实在是忍不住了,基本上很多人对memcpy的原理都是一知半解,大部分认为memcpy是一个char到char的拷贝的循环,担心它的效率。
实际上,memcpy是一个效率最高的内存拷贝函数,他不会那么傻,来做一个一个字节的内存拷贝,在地址不对齐的情况下,他是一个字节一个字节的拷,地址对齐以后,就会使用CPU字长来拷(和dma类似),32bit或64bit,还会根据cpu的类型来选择一些优化的指令来进行拷贝。
总的来说,memcpy的实现是和CPU类型、操作系统、cLib相关的。毫无疑问,它是内存拷贝里效率最高的,请放心使用。”
因此在程序设计之初曾经想过两种方案:
副本一、使用memcpy函数,可以采用动态开辟数组来模拟顺序栈的实现;
副本二、不使用memcpy函数,对链表的操作会显得慢些。
最终选择了没有使用memcpy()函数。
压入栈的伪代码:
1 将top节点备份给temp;
2 开辟一个节点,赋给top指针;
3 将temp指针的值赋给top的成员link。
弹出栈的伪代码:
1 取出元素;
2 删除节点;
3 将top指针指向下一个节点;
4 返回元素。
处理当前字符的函数(CharProcess()函数)的伪代码:
1 若是字符,则直接返回;
2 若是数字,则取下一个字符,并循环判断
3 在判断中若是字符,则对数字进行压栈操作,并返回。
计算表达式的函数(EnvaluateExpression()函数)的伪代码:
1 定义对象,并初始化;
2 对存储操作符的栈压入“=”字符;
3 在字符不为“=”或者“)”,则运行CharProcess()函数;
4 若有括号匹配现象,消去括号;
5 运行Precede()函数,并对其产生不同的返回值进行不同的操作;
6 若未产生“=”匹配现象,则循环3~6步操作;
7 返回栈顶元素。
注意:
1 此程序仅表示了核心的代码,若用户误输入了错误的数据,则会产生各种的错误;
2 此程序仅支持“+-*/()”四则运算,尚不满足科学计算要求。
程序特点:链式栈、支持四则运算、支持一次性输入两位数及以上、支持浮点型数
程序代码:define.h代码:
- #ifndef _J_DEFINE_H_
- #define _J_DEFINE_H_
- //Using C++ style
- template<typename CustomType>//可将任意类型应用于此
- struct CustomStruct
- {
- CustomStruct():elem(0),link(0){}//默认构造函数
- CustomType elem;
- CustomStruct* link;
- };
- template<typename CustomType>
- class JStack
- {
- public:
- JStack():base(0),top(0),JStackSize(0){}//默认构造函数
- ~JStack(){}//默认析构函数
- bool InitJStack( void );//初始化栈
- CustomType GetTop( void );//取出栈顶的元素
- bool Pop( void );//将元素从栈中弹出
- bool Push(CustomType e);//将元素压入栈顶
- private:
- CustomStruct<CustomType>* base;//栈底
- CustomStruct<CustomType>* top;//栈顶
- int JStackSize;//栈的元素个数
- };//栈结构的定义
- //bool IsOperator(char c);
- char CharProcess( JStack<float>& opndStack );
- char Precede(char theta1, char theta2);
- float EvaluateExpression( void );
- float GetAnswer(float a,char c,float b);
- #endif
define.cpp代码:
- #include<iostream>
- #include<string.h>
- #include "define.h"
- using namespace std;
- template<typename CustomType>
- bool JStack<CustomType>::InitJStack( void )//初始化栈
- {
- base = top = new CustomStruct<CustomType>;
- if ( !base )
- return false;
- return true;
- }
- template<typename CustomType>
- bool JStack<CustomType>::Push(CustomType e)//将元素压入栈顶
- {
- CustomStruct<CustomType>* temp;
- temp = top;
- top = new CustomStruct<CustomType>;
- if ( !top )
- return false;
- top->elem = e;
- top->link = temp;
- return true;
- }//此方法相当于头插法
- template<typename CustomType>
- bool JStack<CustomType>::Pop( void )//将元素从栈中弹出
- {
- CustomStruct<CustomType> temp;
- temp.elem = top->elem;
- temp.link = top->link;
- delete top;
- top = temp.link;
- return true;
- }
- template<typename CustomType>
- CustomType JStack<CustomType>::GetTop( void )//取出栈顶的元素
- {
- return top->elem;
- }
- float EvaluateExpression( void )
- { //计算表达式的函数
- char c=0,operand;
- float a=0,b=0;//定义计算的操作数
- JStack<float> opndStack;//存储操作数的栈
- JStack<char> operStack;//存储操作符的栈
- opndStack.InitJStack();//初始化
- operStack.InitJStack();//初始化
- operStack.Push('=');
- do
- {
- if ( c != '=' && c != ')')//如果当前未到等号位置,则继续处理字符
- c = CharProcess( opndStack );
- if ( operStack.GetTop() == '(' && c == ')')
- { //消去括号
- operStack.Pop();
- cin.get( c );
- }
- switch( Precede(operStack.GetTop(), c) )
- { //对不同的情况进行操作
- case '<'://低优先级
- operStack.Push( c );break;
- case '='://优先级相等
- operStack.Pop();
- break;
- case '>'://高优先级
- b = opndStack.GetTop();//右操作数
- opndStack.Pop();//右操作数弹出
- operand = operStack.GetTop();//操作符
- operStack.Pop();//操作符弹出
- a = opndStack.GetTop();//左操作数
- opndStack.Pop();//左操作数弹出
- opndStack.Push( GetAnswer( a, operand, b) );
- if ( c != '=' && c != ')')//如果不是等号或者右边括号
- operStack.Push( c );//要将当前操作符入栈
- break;
- case ' ':
- break;
- }
- }
- while ( c != '=' || operStack.GetTop() != '=');//若未到等于符号,继续读取
- return opndStack.GetTop();
- }
- char CharProcess( JStack<float>& opndStack )
- {
- char temp[16] ={ 0 };//定义临时变量,用来存储字符串化的数字
- char c;//定义一个字符
- int i = 0;//定义一个自增的变量
- cin.get( c );//读取一个字符
- if ( c=='+'||c=='-'||c=='*'||c=='/'||c=='('||c==')' )
- return c;
- while ( c>= '0' && c <= '9' || c == '.')
- { //若是数字的话,将其放在临时的变量中
- temp[i++] = c;
- cin.get( c );//再取一个字符
- } //剩下的就是操作符了
- opndStack.Push( atof(temp) );
- return c;//返回当前操作符
- }
- char Precede(char theta1, char theta2)
- { //对运算符的优先级进行判断的函数
- if (theta1 == '+'||theta1 =='-')
- {
- if ( theta2 == '+'||theta2 == '-'|| theta2 ==')'||theta2 == '=')
- return '>';
- else return '<';
- }
- if (theta1 == '*'||theta1 =='/')
- {
- if ( theta2 == '(' )
- return '<';
- else return '>';
- }
- if (theta1 == '(')
- {
- if ( theta2 == ')' )
- return '=';
- else if ( theta2 == '=')
- return ' ';
- else return '<';
- }
- if (theta1 == ')')
- {
- if (theta2 == '(')
- return ' ';
- else return '>';
- }
- if (theta1 == '=')
- {
- if (theta2 == '=')
- return '=';
- else if (theta2 == ')')
- return ' ';
- else return '<';
- }
- return 0;//返回错误信息
- }
- float GetAnswer(float a,char operand,float b)
- {
- switch ( operand )
- {
- case '+':return a+b;
- case '-':return a-b;
- case '*':return a*b;
- case '/':return a/b;
- }
- return 0.0f;
- }
mainframe.cpp代码:
- #include <iostream>
- #include "define.h"
- int main(int arg, char** argv)
- {
- float answer;
- answer = EvaluateExpression();
- std::cout<<"上述式子的结果是:"<<answer<<'/n';
- return 0;
- }
程序的运行结果如图所示: