因为类的.cpp部分太长,这里仅贴出Fraction类的完整代码。
类图编码(框架)
这里贴出VS资源管理器的源文件和头文件的截图作为框架的大致展现,.h文件和.cpp文件对应分离。具体可看的头文件实现和。
类图编码(Fraction类)
由于代码过长,无法全部粘贴,这里只贴出Fraction类的代码,其余部分可在中查看。
/*************************************************************文件名:fraction.h作者:许郁杨 日期:2017/05/07描述: fraction.cpp对应头文件*************************************************************/#pragma once#include"assistant_functions.h"#includeusing namespace std;class Fraction{private: int m_nnumerator; int m_ndenominator; string m_snumerator; string m_sdenominator;public: Fraction(); void GetFraction(int l, int h); bool isDivisorZero(); bool IsInt(); void TransferIntIntoFraction(int up, int down); void Simplify(); string TransferIntoStringNoInt(); string TransferIntoString(); friend const Fraction operator +(Fraction frac1, Fraction frac2); friend const Fraction operator -(Fraction frac1, Fraction frac2); friend const Fraction operator *(Fraction frac1, Fraction frac2); friend const Fraction operator /(Fraction frac1, Fraction frac2);};
/*************************************************************文件名:fraction.cpp作者:许郁杨 日期:2017/05/07描述: 分数类主要功能包括:分数的生成、转换和四则运算作者:许郁杨 日期:2017/05/10更新:补充了注释,对格式排版进行一些调整*************************************************************/#include"fraction.h"#include#include using namespace std;Fraction::Fraction() { }/*生成分数 日期:2017/05/07*/void Fraction::GetFraction(int l, int h){ int ntmp1 = 0, ntmp2 = 0; stringstream sstmp1, sstmp2; while (Max(ntmp1, ntmp2) == 0) { ntmp1 = RandomNumber(l, h); ntmp2 = RandomNumber(l, h); } m_nnumerator = Min(ntmp1, ntmp2); m_ndenominator = Max(ntmp1, ntmp2); sstmp1 << m_nnumerator; sstmp1 >> m_snumerator; sstmp2 << m_ndenominator; sstmp2 >> m_sdenominator;}/*检查除数是否为零,是为true,否为false 日期:2017/05/07 更新:格式调整 日期:2017/05/10*/bool Fraction::isDivisorZero(){ if (m_nnumerator == 0) { return true; } else { return false; }}/*检查是否可化简整数,是为true,否为false 日期:2017/05/07 更新:注释补充,格式调整 日期:2017/05/10*/bool Fraction::IsInt(){ if (m_ndenominator == 1)//如果除数为一,即可化简为整数 { return true; } else//如果不可化简为整数 { return false; }}/*将整数转换为分数形式 日期:2017/05/07*/void Fraction::TransferIntIntoFraction(int up, int down){ stringstream sstmp1, sstmp2; m_nnumerator = up; m_ndenominator = down; sstmp1 << m_nnumerator; sstmp1 >> m_snumerator; sstmp2 << m_ndenominator; sstmp2 >> m_sdenominator; sstmp1.clear(); sstmp2.clear();}/*化简分数 日期:2017/05/07 更新:注释补充,格式调整 日期:2017/05/10*/void Fraction::Simplify(){ int ntmp; stringstream sstmp1, sstmp2; if (m_ndenominator < 0)//如果分母为负数 { m_ndenominator = -m_ndenominator; m_nnumerator = -m_nnumerator; } if (m_nnumerator == 0)//如果分子为零 { m_ndenominator = 1; } else { ntmp = GreatestCommonDivisor(abs(m_ndenominator), abs(m_nnumerator)); m_nnumerator /= ntmp; m_ndenominator /= ntmp; } sstmp1 << m_nnumerator; sstmp1 >> m_snumerator; sstmp2 << m_ndenominator; sstmp2 >> m_sdenominator; sstmp1.clear(); sstmp2.clear();}/*将分数转换为字符串形式(不区分整数) 日期:2017/05/07*/string Fraction::TransferIntoStringNoInt(){ return "(" + m_snumerator + "\\" + m_sdenominator + ")";}/*将分数转换为字符串形式(区分整数) 日期:2017/05/07 更新:注释补充,格式调整 日期:2017/05/10*/string Fraction::TransferIntoString(){ if (m_ndenominator == 1)//如果分母为一 { return m_snumerator; } else { return "(" + m_snumerator + "\\" + m_sdenominator + ")"; }}/*重载加法运算符 日期:2017/05/07*/const Fraction operator +(Fraction frac1, Fraction frac2){ Fraction answer; answer.m_nnumerator = frac1.m_nnumerator*frac2.m_ndenominator + frac1.m_ndenominator*frac2.m_nnumerator; answer.m_ndenominator = frac1.m_ndenominator*frac2.m_ndenominator; answer.Simplify(); return answer;}/*重载减法运算符 日期:2017/05/07*/const Fraction operator -(Fraction frac1, Fraction frac2){ Fraction answer; answer.m_nnumerator = frac1.m_nnumerator*frac2.m_ndenominator - frac1.m_ndenominator*frac2.m_nnumerator; answer.m_ndenominator = frac1.m_ndenominator*frac2.m_ndenominator; answer.Simplify(); return answer;}/*重载乘法运算符 日期:2017/05/07*/const Fraction operator *(Fraction frac1, Fraction frac2){ Fraction answer; answer.m_nnumerator = frac1.m_nnumerator*frac2.m_nnumerator; answer.m_ndenominator = frac1.m_ndenominator*frac2.m_ndenominator; answer.Simplify(); return answer;}/*重载除法运算符 日期:2017/05/07*/const Fraction operator /(Fraction frac1, Fraction frac2){ Fraction answer; answer.m_nnumerator = frac1.m_nnumerator*frac2.m_ndenominator; answer.m_ndenominator = frac1.m_ndenominator*frac2.m_nnumerator; answer.Simplify(); return answer;}
栈的定义
栈作为一种常见的数据结构,其最主要的特点为后进先出(区别于队列的先进先出)。栈与线性表类似,都可以用数组和链表两种方式来实现。通常情况下,我们用数组来进行栈的实现。
需要注意的是,栈无法遍历。
栈的结构特点如下图所示:
标准库的栈
下面对c++ STL中的栈(stack)的用法进行一定说明。
头文件:#include< stack >;
声明:stack<类型> 变量名;
push(a)
在栈顶压入新元素a;
pop()
出栈;empty()
判断栈是否为空,如果栈为空返回true,否则返回false;size()
返回栈中元素的个数;top()
返回栈顶元素; 示例:
#include#include using namespace std;int main(){ stack a; a.push(1);//进栈 a.push(2); a.pop();//出栈 cout << a.top() << endl;//返回栈顶元素 cout << a.size() << endl;//返回栈中元素的个数 cout << a.empty() << endl;//判断栈是否为空,如果栈为空返回true,否则返回false return 0;}
栈的代码实现(数组)
class Stack{private: int *m_data; int m_point;public: Stack(); bool push(int n); bool pop(); bool empty(); int top(); int size();};Stack::Stack(){ m_data = new int[1000];}bool Stack::push(int n){ if (m_point < 1000) { m_data[m_point] = n; m_point++; return true; } else { return false; }}bool Stack::pop(){ if (m_point > 0) { m_point--; return true; } else { return false; }}bool Stack::empty(){ if (m_point == 0) { return true; } else { return false; }}int Stack::size(){ return m_point;}int Stack::top(){ if (!empty()) { return m_data[m_point - 1]; } else { return -1; }}
栈的代码实现(链表)
class Stack{private: struct Node { int data; Node *next; }; Node *m_head; Node *m_present; int m_size;public: Stack() { m_head = NULL; m_size = 0; } void push(int n); bool pop(); bool empty(); int top(); int size();};void Stack::push(int n){ Node *tmp = new Node; tmp->data = n; if (m_head == NULL) { tmp->next = m_head; m_head = tmp; m_present = tmp; } else { tmp->next = m_present; m_present = tmp; } m_size++;}bool Stack::pop(){ if (m_size <= 0) { return false; } else { Node *tmp; int data; tmp = m_present; data = m_present->data; m_present = m_present->next; delete(tmp); m_size--; return true; }}bool Stack::empty(){ if (m_size == 0) { return true; } else { return false; }}int Stack::size(){ return m_size;}int Stack::top(){ if (!empty()) { return m_present->data; } else { return -1; }}
栈的简单应用示例
栈在算法中的基本应用主要是数制转换、符号匹配检查、表达式求值、行编辑以及二叉树的遍历。其中,符号匹配在之前c语言的学习中有做过相关的题目,而在这次的四则运算程序就能够直接运用的就是表达式求值。栈的相关应用网络上资源很多,我就不再赘述。接下来,我以后缀表达式求值为示例体现一下栈在编程当中的实际应用。
后缀表达式求值的步骤:
- 初始化一个空操作数栈;
- 从前到后读取后缀表达式的元素。如果是操作数直接入栈;如果读到操作符,弹出栈顶元素a,对新的栈顶元素b,执行b 操作符 a,将结果压入栈中;
- 最后的栈顶元素即为表达式的值。
代码示例如下:
//string postfix;int CalculateResult(){ int i = 0; stack numberStack; while (postfix[i] != '\0') { if ((postfix[i] >= '0') && (postfix[i] <= '9')) { double k = 0; while ((postfix[i] >= '0') && (postfix[i] <= '9')) { k = 10 * k + postfix[i] - '0'; i++; } numberStack.push(k); } else { int tmp = numberStack.top(); switch (postfix[i]) { case '+': { numberStack.push(tmp + numberStack.top()); break; } case '-': { numberStack.push(tmp - numberStack.top()); break; } case '*': { numberStack.push(tmp * numberStack.top()); break; } case '/': { numberStack.push(tmp / numberStack.top()); } } } i++; } return numberStack.top();}