08年9月入学,12年7月毕业,结束了我在软件学院愉快丰富的大学生活。此系列是对四年专业课程学习的回顾,索引参见:http://www.jb51.cc/article/p-srsfcefa-vo.html
顺序栈各种基本运算算法的实现
栈是只能在某一端插入和删除的特殊线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底(push),最后的数据在栈顶(top),需要读数据的时候从栈顶开始弹出数据(top)最后一个数据被第一个读出来。
【实验说明】
我选择的题目:书中calculator的编写与改进
1.分析栈要实现的功能从而确定栈类的几种基本成员函数——pop(),pop(),top(),clear(),确定栈中以数组实现数据的存储从而确定栈的成员函数——Stack_entry entry[],count(记录栈中数据数量)
2.编写栈的头文件及实现
3.选择书中计算器的程序以验证栈的各种基本运算。分析书中算法思路及对栈的运用,提出可以改进的地方——将计算器功能封装到类中,并增加清空栈的功能。
4.编写计算器类的头文件及类的实现
5.主函数中通过简单的创建MyClaculator验证程序,并试验各种基本功能。
1.分析栈要实现的功能从而确定栈类的几种基本成员函数——pop(),pop(),top(),clear(),确定栈中以数组实现数据的存储从而确定栈的成员函数——Stack_entry entry[],count(记录栈中数据数量)
2.编写栈的头文件及实现
3.选择书中计算器的程序以验证栈的各种基本运算。分析书中算法思路及对栈的运用,提出可以改进的地方——将计算器功能封装到类中,并增加清空栈的功能。
4.编写计算器类的头文件及类的实现
5.主函数中通过简单的创建MyClaculator验证程序,并试验各种基本功能。
【相关代码】
Stack.h#ifndef STACK_H #define STACK_H enum Error_code{success,underflow,overflow}; const int stackmax=10; typedef double Stack_entry; class Stack{ public: Stack(); bool empty() const; Error_code pop(); Error_code push(const Stack_entry &item); Error_code top(Stack_entry &item) ; Error_code clear(); private: Stack_entry entry[stackmax]; int count; }; #endifStack.cpp
#include"stack.h" //implemention //Stack() Stack::Stack(){ count=0; } //pop() Error_code Stack::pop(){ Error_code outcome=success; if(count==0) outcome=underflow; else count--; return outcome; } //push() Error_code Stack::push(const Stack_entry &item){ Error_code outcome=success; if(count>=stackmax) outcome=overflow; else entry[count++]=item; return outcome; } //top() Error_code Stack::top(Stack_entry &item){ Error_code outcome=success; if(count==0) outcome=underflow; else item=entry[count-1]; return outcome; } //clear() Error_code Stack::clear(){ count=0; return success; } //empty() bool Stack::empty() const{ bool outcome=true; if(count!=0) outcome=false; return outcome; }caculator.h
#ifndef CALCULATOR_H #define CALCULATOR_H #include"stack.h" class Calculator{ public: //constructor Calculator(); //public function to get command void get_command(); //pubblic funtion to do the command bool do_command(); protected: //As these functions will not be visible to the client //but should be derived classes to access so I declare it as protected functions void PutInNum(); void Add(); void Sub(); void Mul(); void Div(); void ShowResult(); void Clear(); void Quit(); private: //data members char command; Stack numbers; }; #endifcaculator.cpp
#include "calculator.h" #include <iostream> using namespace std; //construction Calculator::Calculator(){ command=' '; } //get_command void Calculator::get_command(){ bool waiting =true; cout<<"Select command and press <Enter>:"; while(waiting){ cin>>command; command=tolower(command); if(command=='?'||command=='='||command=='+'|| command=='-'||command=='*'||command=='/'|| command=='q'||command=='c') waiting=false; else cout<<"Please enter a valid command:"<<endl <<"[?]push to stack [=]print top "<<endl <<"[+][-][*][/] are arithmetic operations"<<endl <<"[c]clean the stack"<<endl <<"[Q] quit"<<endl; } } //do_command bool Calculator::do_command(){ get_command(); switch(command){ case '?': PutInNum(); break; case '+': Add(); break; case '-': Sub(); break; case '*': Mul(); break; case '/': Div(); break; case 'c': Clear(); break; case '=': ShowResult(); break; case 'q': return false; } return true; } //Once enter '?': put the next number into stack void Calculator::PutInNum(){ Stack_entry p; cout<<"Enter a real number: "<<flush; cin>>p; if(numbers.push(p)==overflow) cout<<"Warning:Stack full,lost number"<<endl; } //Once enter '+' : Add the numbers in the stack void Calculator::Add(){ Stack_entry p,q; if(numbers.top(p)==underflow) cout<<"Stack empty"<<endl; else{ numbers.top(p); numbers.pop(); if(numbers.top(q)==underflow){ cout<<"Stack has just one entry"<<endl; numbers.push(p); } else{ numbers.pop(); if(numbers.push(p+q)==overflow) cout<<"Warning:Stack full,lost result"<<endl; } } } //Once enter '-': Subtract the numbers in the stack void Calculator::Sub(){ Stack_entry p,q; if(numbers.top(p)==underflow) cout<<"Stack empty"<<endl; else{ numbers.top(p); numbers.pop(); if(numbers.top(q)==underflow){ cout<<"Stack has just one entry"<<endl; numbers.push(p); } else{ numbers.pop(); if(numbers.push(q-p)==overflow) cout<<"Warning:Stack full,lost result"<<endl; } } } //Once enter'*': Multiply the numbers in the stack void Calculator::Mul(){ Stack_entry p,q; if(numbers.top(p)==underflow) cout<<"Stack empty"<<endl; else{ numbers.top(p); numbers.pop(); if(numbers.top(q)==underflow){ cout<<"Stack has just one entry"<<endl; numbers.push(p); } else{ numbers.pop(); if(numbers.push(p*q)==overflow) cout<<"Warning:Stack full,lost result"<<endl; } } } //Once enter '/': Divide the numbers in the stack void Calculator::Div(){ Stack_entry p,q; if(numbers.top(p)==underflow) cout<<"Stack empty"<<endl; else{ numbers.top(p); numbers.pop(); if(p==0){ cout<<"Bed command! The second number is 0 and cannot finishi divide command!"<<endl; } else if(numbers.top(q)==underflow){ cout<<"Stack has just one entry"<<endl; numbers.push(p); } else{ numbers.pop(); if(numbers.push(q/p)==overflow) cout<<"Warning:Stack full,lost result"<<endl; } } } //Once enter '=':Show the result of least command void Calculator::ShowResult(){ Stack_entry p; if(numbers.top(p)==underflow) cout<<"Stack empty"<<endl; else cout<<p<<endl; } //Once enter 'q':Stop the calculation void Calculator::Quit(){ cout<<"Calculation finished!"<<endl; } //Once enter 'c':Clear the stack void Calculator::Clear(){ numbers.clear(); }
【过程记录】
实验截图:
【结果分析】
1.实验中我以课本中计算器的实验为例,实现并验证了顺序栈各种基本运算。
2.计算器的实现:当用户输入“?”时,程序将将即将输入的数压入栈中;当用户输入“+”“-”“*”“/”等基本运算符,弹出之前被压入的数字做相应的运算,并将结果压入栈中。当用户输入“=”时,弹出并显示上一步运算的结果。
3.依照书中的基本思想,我实现了计算器的运算,并做了一些相应的改变:
(1)将计算器作为一个类实现,从而将计算器中用以储存数据的栈作为私有数据成员,用以实现各种操作的函数作为保护成员函数更好的封装起来,对用户只留有命令接口。这样简化了主函数,也方便以后的使用。
(2)由于计算器中运算数据存储在有一定限制的栈中,多次元素按之后可能会使栈状态变为full,所以我增加了名为clear()的函数可以清空栈。
4.实验中我遇到的问题:
(1)要注意栈“先进后出”的特点,所以容易弄错运算数的顺序(加法、乘法并没有影响,但减法和除法运算就可能出现问题),即栈中第一次弹出的数据是第二个操作数,第二次弹出的数据是第一个操作数。
(2)编写计算器的构造函数时,发现数据成员command(char类型)并不能默认为‘’,但可以是空格‘ ’,之前并没有注意到这种区别。
(3)验证时,我发现当输入“?”之后,如果我输入的不是默认要输入的double类型,例如输入“a”等字母,程序没有报错,反而是出现死循环,对于这个问题我并没有解决。
2.计算器的实现:当用户输入“?”时,程序将将即将输入的数压入栈中;当用户输入“+”“-”“*”“/”等基本运算符,弹出之前被压入的数字做相应的运算,并将结果压入栈中。当用户输入“=”时,弹出并显示上一步运算的结果。
3.依照书中的基本思想,我实现了计算器的运算,并做了一些相应的改变:
(1)将计算器作为一个类实现,从而将计算器中用以储存数据的栈作为私有数据成员,用以实现各种操作的函数作为保护成员函数更好的封装起来,对用户只留有命令接口。这样简化了主函数,也方便以后的使用。
(2)由于计算器中运算数据存储在有一定限制的栈中,多次元素按之后可能会使栈状态变为full,所以我增加了名为clear()的函数可以清空栈。
4.实验中我遇到的问题:
(1)要注意栈“先进后出”的特点,所以容易弄错运算数的顺序(加法、乘法并没有影响,但减法和除法运算就可能出现问题),即栈中第一次弹出的数据是第二个操作数,第二次弹出的数据是第一个操作数。
(2)编写计算器的构造函数时,发现数据成员command(char类型)并不能默认为‘’,但可以是空格‘ ’,之前并没有注意到这种区别。
(3)验证时,我发现当输入“?”之后,如果我输入的不是默认要输入的double类型,例如输入“a”等字母,程序没有报错,反而是出现死循环,对于这个问题我并没有解决。