我用了三天时间一共700行代码实现了这个复数计算器。

为什么会这么久呢?

其实我之前也做过一个复数计算器只不过那个只能一项一项输入数据而且只能对两个数进行运算

就像这样

请输入第一个复数的实部:

请输入第一个复数的虚部:

请输入第二个复数的实部:

请输入第二个复数的虚部:

请输入要进行加减乘除的哪个运算:

这是我第一版的复数运算器。这个太low了。

我在数据结构的书里看到了表达式求值的算法。于是我就在想怎样才能写出一个可以像平时用科学计算器那样写一串算数表达式让程序自己去提取这串表达式中的实部和虚部,于是我从第一天的了解复数运算性质然后写出复数运算的基本加减乘除,乘方的算法,到第二天花一天时间研究表达式的求值的算法,第二天晚上开始着手写这个算法。直到第三天才运行成功。

数据结构书中只有对实数进行运算的表达式求值算法所以我还不能直接借鉴上面的代码,我必须要从文字看起一点一点的理解这个算法

算法如下:

我的具体实现的代码如下

先是实现这个代码前的数据构造,开始写这个的时候我也没想到要从造轮子开始

存储数学符号的栈

char链栈.h

//蔚明
//char链栈.h#pragma oncetypedef char strElemType;
typedef struct CHAR_STACK_NODE
{strElemType data;CHAR_STACK_NODE* next;
}stack_st, * stack_pst;bool sInitStack(stack_pst& S);//初始化一个链栈
bool sPush(stack_pst& S, strElemType e);//入栈
bool sPop(stack_pst& S, strElemType& e);//出栈
bool sGetTop(stack_pst S, strElemType& e);//引用方式得到栈顶元素

char链栈.c

//蔚明
//char链栈.c#include "复数计算器.h"
#include "char链栈.h"using namespace std;bool sInitStack(stack_pst& S)//初始化一个链栈
{S->next = NULL;return true;
}bool sPush(stack_pst& S, strElemType e)//入栈
{stack_pst p = new stack_st;//为入栈的元素分配空间p->data = e;//把要入栈的元素赋给新结点p->next = S;//新结点指向原来的栈顶元素S = p;//让新结点成为栈顶元素return true;
}bool sPop(stack_pst& S, strElemType& e)//出栈
{if (S == NULL)//检查是否为空栈{cout << "字符栈空,出栈失败!!!\n" << endl;return false;}stack_pst temp;e = S->data;//把要弹出的结点的内容赋给etemp = S;//临时保存要弹出的结点S = S->next;//修改栈顶指针delete temp;//把原来的栈顶的内存释放。return true;
}bool sGetTop(stack_pst S,strElemType &e)//引用方式得到栈顶元素
{if (S != NULL){e = S->data;return true;}else{cout << "栈空" << endl;return false;}
}

//复数计算器.h

//蔚明
//复数计算器.h#pragma once#include <iostream>

//复数类的定义

ComplexNum.h

//蔚明
//ComplexNum.h#pragma once#include <cmath>
#include "复数计算器.h"#define RAD_WAY 0
#define DEG_WAY 1typedef char Cmplxnum_expression[40];
typedef char strToDouble[19];extern const double PI;class ComplexNum
{
public:ComplexNum();//把一个复数初始化为实部为零,虚部为零ComplexNum(double dRPart,double dIPart);//把一个复数初始化为指定的实部和虚部double GetRealPart();//获取实部double GetImaginaryPart();//获取虚部double GetLength();//获取模长double GetDeg();//获取角度double GetRad();//获取弧度void SetComplexNum(double dRPart, double dIPart);//把一个复数置为指定的实部和虚部void SetComplexNum(Cmplxnum_expression str);//以表达式的形式为复数赋值void SetComplexNum_Deg(double dlength, double dDegree);//把一个复数置为指定的模长和幅角(角度)void SetComplexNum_Rad(double dlength, double dRadree);//把一个复数置为指定的实部和虚部(弧度)void SetComplexNum_RI(Cmplxnum_expression str);//实部虚部形式的表达式void SetComplexNum_Index(Cmplxnum_expression str);//指数形式的表达式void AddComplexNin(ComplexNum num);//把此复数和括号中的复数相加void SubComplexNin(ComplexNum num);//把此复数和括号中的复数相减void MultipComplexNin(ComplexNum num);//把此复数和括号中的复数相乘void DiviComplexNin(ComplexNum num);//把此复数和括号中的复数相除void AddComplexNin(double dRPart, double dIPart);//把此复数和括号中实部为dRPart,虚部为dIPart相加void SubComplexNin(double dRPart, double dIPart);//把此复数和括号中实部为dRPart,虚部为dIPart相减void MultipComplexNin(double dRPart, double dIPart);//把此复数和括号中实部为dRPart,虚部为dIPart相乘void DiviComplexNin(double dRPart, double dIPart);//把此复数和括号中实部为dRPart,虚部为dIPart相除void AddComplexNin_Deg(double dlength,double dDegree);//把此复数和括号中模长为dlength,幅角(角度)为dDegree相加void SubComplexNin_Deg(double dlength, double dDegree);//把此复数和括号中模长为dlength,幅角(角度)为dDegree相减void MultipComplexNin_Deg(double dlength, double dDegree);//把此复数和括号中模长为dlength,幅角(角度)为dDegree相乘void DiviComplexNin_Deg(double dlength, double dDegree);//把此复数和括号中模长为dlength,幅角(角度)为dDegree相除void AddComplexNin_Rad(double dlength, double dRadree);//把此复数和括号中模长为dlength,幅角(弧度)为dRadree相加void SubComplexNin_Rad(double dlength, double dRadree);//把此复数和括号中模长为dlength,幅角(弧度)为dRadree相减void MultipComplexNin_Rad(double dlength, double dRadree);//把此复数和括号中模长为dlength,幅角(弧度)为dRadree相乘void DiviComplexNin_Rad(double dlength, double dRadree);//把此复数和括号中模长为dlength,幅角(弧度)为dRadree相除void NumToPower(double iNum,int &resultNum);//这个数的INum次方。void PrintRI();//以a+i*b形式打印复数。void PrintTrigon(int way);//以三角形式a*(cos(b)+i*sin(b))。void PrintIndex(int way);//以指数形式a*e^i*b。void ComplexNumCopy(ComplexNum B);//把B复制给Afriend ComplexNum AddComplexNum(ComplexNum CmplxNm1, ComplexNum CmplxNm2);//计算两数相加,返回结果。friend ComplexNum SubComplexNum(ComplexNum CmplxNm1, ComplexNum CmplxNm2);//计算两数相减,返回结果。friend ComplexNum MultiComplexNum(ComplexNum CmplxNm1, ComplexNum CmplxNm2);//计算两数相乘,返回结果。friend ComplexNum DiviComplexNum(ComplexNum CmplxNm1, ComplexNum CmplxNm2);//计算两数相除,返回结果。private:double dRealPart;//复数的实部double dImaginaryPart;//复数的虚部double dLength();//复数的模长double dDegree();//复数的角度double dRadian();//复数的弧度
};ComplexNum GetComplexNum(Cmplxnum_expression str);//以字符串的形式得到复数

ComplexNum.c

这个源文件中涉及的函数都是有关复数运算的,里面有很多复数的性质所以这个原文件几乎没有注释懂得人自然懂不懂得,要么自己去看复变函数的书籍要么不用管他

//蔚明
//ComplexNum.c#include "ComplexNum.h"
#include <cmath>
#include <iostream>using namespace std;const double PI = 3.1415926535;double RadToDeg(double _Rad)//弧度变角度。
{return _Rad / PI * 180;
}double DegToRad(double _Deg)//角度变弧度。
{return _Deg / 180 * PI;
}double ComplexNum::dLength()//复数的模长
{return sqrt(dRealPart * dRealPart + dImaginaryPart * dImaginaryPart);
}double ComplexNum::dDegree()//复数的角度
{return dRadian() / PI * 180;
}double ComplexNum::dRadian()//复数的弧度
{return atan2(dImaginaryPart,dRealPart);
}ComplexNum::ComplexNum()//把一个复数初始化为实部为零,虚部为零:dRealPart(0), dImaginaryPart(0)
{}ComplexNum::ComplexNum(double dRPart, double dIPart)//把一个复数初始化为指定的实部和虚部: dRealPart(dRPart), dImaginaryPart(dIPart)
{}void ComplexNum::SetComplexNum(double dRPart, double dIPart)//把一个复数置为指定的实部和虚部
{dRealPart = dRPart;dImaginaryPart = dIPart;
}//@ RI  % 指数void ComplexNum::SetComplexNum_RI(Cmplxnum_expression str)//实部虚部形式的表达式
{//@dRelPart+idImPart如(@1.58+i7.89)或dRelPart+idImPart如(1.58+i7.89)int i = 0, j = 0;//循环控制变量strToDouble strRelprt;//表示实部的字符串strToDouble strImprt;//表示虚部的字符串if (str[0] == '@') i = 1;else i = 0;for (i,j=0; str[i] != '+' || str[i] == '-' && j < 18;j++, i++)//在找到‘+’之前而且没有到达字符数组的末端之前一直录入字符到储存实部的字符串中{strRelprt[j] = str[i];}strRelprt[j] = '\0';//手动为此字符串添加修制符dRealPart = atof(strRelprt); //字符串转化为双精度浮点数if (str[i] == '+')//如果和虚部连接的符号是‘+’{for (i += 2, j = 0; str[i] != '\0' && j < 18; i++, j++){strImprt[j] = str[i];}strImprt[j] = '\0'; //手动为此字符串添加修制符dImaginaryPart = atof(strImprt);//字符串转化为双精度浮点数return;}else if (str[i] == '-')//如果和虚部连接的符号是‘-’{for (i += 2, j = 0; str[i] != '\0' && j < 18; i++, j++){strImprt[j] = str[i];}strImprt[j] = '\0';//手动为此字符串添加修制符dImaginaryPart = 0 - atof(strImprt);//字符串转化为双精度浮点数同时取负后赋值return;}else{cout << "表达式错误,赋值失败" << endl;return;}
}void ComplexNum::SetComplexNum_Index(Cmplxnum_expression str)//指数形式的表达式
{//弧度:%dlength*E^i*rdrad如(%1.72*e^i*r3.28或%1.72*e^i*R3.28),角度:%dlength*E^i*ddrad如(%1.72*e^i*r3.28或%1.72*e^i*R3.28)int i = 0, j = 0;//循环控制变量strToDouble strLength;//表示模长的字符串for (i = 1,j=0; str[i] != '*'  && j < 18;j++, i++)//在找到‘+’之前而且没有到达字符数组的末端之前一直录入字符到储存实部的字符串中{strLength[j] = str[i];}strLength[j] = '\0';//手动为此字符串添加休止符if (str[i + 5] == 'r' || str[i + 5] == 'R'){strToDouble strRad;//表示幅角的字符串for (i += 6, j = 0; str[i] != '\0' && j < 18; i++, j++)//在找到‘+’之前而且没有到达字符数组的末端之前一直录入字符到储存实部的字符串中{strRad[j] = str[i];}strRad[j] = '\0';//手动为此字符串添加休止符SetComplexNum_Rad(atof(strLength), atof(strRad));}else if (str[i + 5] == 'D' || str[i + 5] == 'd'){strToDouble strDeg;//表示幅角的字符串for (i += 6, j = 0; str[i] != '\0' && j < 18; i++, j++)//在找到‘+’之前而且没有到达字符数组的末端之前一直录入字符到储存实部的字符串中{strDeg[j] = str[i];}strDeg[j] = '\0';//手动为此字符串添加休止符SetComplexNum_Rad(atof(strLength),DegToRad(atof(strDeg)));}else//默认弧度{strToDouble strRad;//表示幅角的字符串for (i += 5, j = 0; str[i] != '\0' && j < 18; i++, j++)//在找到‘+’之前而且没有到达字符数组的末端之前一直录入字符到储存实部的字符串中{strRad[j] = str[i];}strRad[j] = '\0';//手动为此字符串添加修制符SetComplexNum_Rad(atof(strLength), atof(strRad));}
}void ComplexNum::SetComplexNum(Cmplxnum_expression str)//以表达式的形式为复数赋值
{if(str[0] == '%') SetComplexNum_Index(str);else if (str[0] == '@') SetComplexNum_RI(str);else  SetComplexNum_RI(str);
}void ComplexNum::SetComplexNum_Deg(double dlength, double dDegree)//把一个复数置为指定的模长和幅角(角度)
{dRealPart = dlength * cos(DegToRad(dDegree));dImaginaryPart = dlength * sin(DegToRad(dDegree));
}void ComplexNum::SetComplexNum_Rad(double dlength, double dRadree)//把一个复数置为指定的实部和虚部(弧度)
{dRealPart = dlength * cos(dRadree);dImaginaryPart = dlength * sin(dRadree);
}double ComplexNum::GetRealPart()//获取实部
{return dRealPart;
}double ComplexNum::GetImaginaryPart()//获取虚部
{return dImaginaryPart;
}double ComplexNum::GetLength()//获取模长
{return dLength();
}double ComplexNum::GetDeg()//获取角度
{return dDegree();
}double ComplexNum::GetRad()//获取弧度
{return dRadian();
}void ComplexNum::AddComplexNin(ComplexNum num)//把此复数和括号中的复数相加
{dRealPart += num.GetRealPart();dImaginaryPart += num.GetImaginaryPart();
}void ComplexNum::SubComplexNin(ComplexNum num)//把此复数和括号中的复数相减
{dRealPart -= num.GetRealPart();dImaginaryPart -= num.GetImaginaryPart();
}void ComplexNum::MultipComplexNin(ComplexNum num)//把此复数和括号中的复数相乘
{SetComplexNum_Rad(dLength() * num.GetLength(),dRadian() + num.GetRad());
}void ComplexNum::DiviComplexNin(ComplexNum num)//把此复数和括号中的复数相除
{SetComplexNum_Rad(dLength() / num.GetLength(), dRadian() - num.GetRad());//实部虚部计算方式//dRealPart = (dRealPart * num.GetRealPart()+dImaginaryPart*num.GetImaginaryPart()) / (num.GetRealPart() * num.GetRealPart() + num.GetImaginaryPart() * num.GetImaginaryPart());//dImaginaryPart = (dImaginaryPart* num.GetRealPart()- dRealPart *num.GetImaginaryPart())/ (num.GetRealPart() * num.GetRealPart() + num.GetImaginaryPart() * num.GetImaginaryPart());
}void ComplexNum::AddComplexNin(double dRPart, double dIPart)//把此复数和括号中实部为dRPart,虚部为dIPart相加
{dRealPart += dRPart;dImaginaryPart += dIPart;
}void ComplexNum::SubComplexNin(double dRPart, double dIPart)//把此复数和括号中实部为dRPart,虚部为dIPart相减
{dRealPart -= dRPart;dImaginaryPart -= dIPart;
}void ComplexNum::MultipComplexNin(double dRPart, double dIPart)//把此复数和括号中实部为dRPart,虚部为dIPart相乘
{SetComplexNum_Rad(dLength() * sqrt(dRPart* dRPart+dIPart* dIPart), dRadian() + atan2(dIPart,dRPart));
}void ComplexNum::DiviComplexNin(double dRPart, double dIPart)//把此复数和括号中实部为dRPart,虚部为dIPart相除
{SetComplexNum_Rad(dLength() / sqrt(dRPart * dRPart + dIPart * dIPart), dRadian() - atan2(dIPart, dRPart));
}void ComplexNum::AddComplexNin_Deg(double dlength, double dDegree)//把此复数和括号中模长为dlength,幅角(角度)为dDegree相加
{double dRPart = dlength * cos(DegToRad(dDegree));double dIPart = dlength * sin(DegToRad(dDegree));AddComplexNin(dRPart, dIPart);
}void ComplexNum::SubComplexNin_Deg(double dlength, double dDegree)//把此复数和括号中模长为dlength,幅角(角度)为dDegree相减
{double dRPart = dlength * cos(DegToRad(dDegree));double dIPart = dlength * sin(DegToRad(dDegree));SubComplexNin(dRPart, dIPart);
}void ComplexNum::MultipComplexNin_Deg(double dlength, double dDegree)//把此复数和括号中模长为dlength,幅角(角度)为dDegree相乘
{SetComplexNum_Rad(dLength() * dlength, dRadian() + DegToRad(dDegree));
}void ComplexNum::DiviComplexNin_Deg(double dlength, double dDegree)//把此复数和括号中模长为dlength,幅角(角度)为dDegree相除
{SetComplexNum_Rad(dLength() / dlength, dRadian() - DegToRad(dDegree));
}void ComplexNum::AddComplexNin_Rad(double dlength, double dRadree)//把此复数和括号中模长为dlength,幅角(弧度)为dRadree相加
{double dRPart = dlength * cos(dRadree);double dIPart = dlength * sin(dRadree);AddComplexNin(dRPart, dIPart);
}void ComplexNum::SubComplexNin_Rad(double dlength, double dRadree)//把此复数和括号中模长为dlength,幅角(弧度)为dRadree相减
{double dRPart = dlength * cos(dRadree);double dIPart = dlength * sin(dRadree);SubComplexNin(dRPart, dIPart);
}void ComplexNum::MultipComplexNin_Rad(double dlength, double dRadree)//把此复数和括号中模长为dlength,幅角(弧度)为dRadree相乘
{SetComplexNum_Rad(dLength() * dlength, dRadian() + dRadree);
}void ComplexNum::DiviComplexNin_Rad(double dlength, double dRadree)//把此复数和括号中模长为dlength,幅角(弧度)为dRadree相除
{SetComplexNum_Rad(dLength() / dlength, dRadian() - dRadree);
}void ComplexNum::NumToPower(double iNum, int& resultNum)//这个数的INum次方。
{SetComplexNum_Rad(pow(dLength(),iNum), dRadian()*iNum);
}ComplexNum GetComplexNum(Cmplxnum_expression str)//以字符串的形式得到复数
{ComplexNum cmplexNum;cmplexNum.SetComplexNum(str);return cmplexNum;
}void ComplexNum::PrintRI()//以a+i*b形式打印复数。
{if (dImaginaryPart > 0){printf("%.2f+i*%.2f", dRealPart, dImaginaryPart);}else if (dImaginaryPart < 0){printf("%.2fi*%.2f", dRealPart, dImaginaryPart);}else{printf("%.2f", dRealPart);}
}void ComplexNum::PrintTrigon(int way)//以三角形式a*(cos(b)+i*sin(b))。
{if (way == RAD_WAY){printf("%.2f*(cos(%.2fPI)+i*sin(%.2fPI))", dLength(), dRadian() / PI, dRadian() / PI);}else if (way == DEG_WAY){printf("%.2f*(cos(%.2f)+i*sin(%.2f))", dLength(), dDegree(), dDegree());}else return;
}void ComplexNum::PrintIndex(int way)//以指数形式a*e^i*b。
{if (way == RAD_WAY){printf("%.2f*e^i*%.2fPI", dLength(), dRadian() / PI);}else if (way == DEG_WAY){printf("%.2f*e^i*%.2f", dLength(), dDegree());}else return;
}void ComplexNum::ComplexNumCopy(ComplexNum B)//把B复制给A
{dRealPart = B.GetRealPart();dImaginaryPart = B.GetImaginaryPart();
}ComplexNum AddComplexNum(ComplexNum CmplxNm1, ComplexNum CmplxNm2)//计算两数相加,返回结果。
{ComplexNum cmplxnm_result;cmplxnm_result.SetComplexNum(CmplxNm1.GetRealPart() + CmplxNm2.GetRealPart(), CmplxNm1.GetImaginaryPart() + CmplxNm2.GetImaginaryPart());return cmplxnm_result;
}ComplexNum SubComplexNum(ComplexNum CmplxNm1, ComplexNum CmplxNm2)//计算两数相减,返回结果。
{ComplexNum cmplxnm_result;cmplxnm_result.SetComplexNum(CmplxNm1.GetRealPart() - CmplxNm2.GetRealPart(), CmplxNm1.GetImaginaryPart() - CmplxNm2.GetImaginaryPart());return cmplxnm_result;
}ComplexNum MultiComplexNum(ComplexNum CmplxNm1, ComplexNum CmplxNm2)//计算两数相乘,返回结果。
{ComplexNum cmplxnm_result;cmplxnm_result.SetComplexNum_Rad(CmplxNm1.GetLength() * CmplxNm2.GetLength(), CmplxNm1.GetRad() + CmplxNm2.GetRad());return cmplxnm_result;
}ComplexNum DiviComplexNum(ComplexNum CmplxNm1, ComplexNum CmplxNm2)//计算两数相除,返回结果。
{ComplexNum cmplxnm_result;cmplxnm_result.SetComplexNum_Rad(CmplxNm1.GetLength() * CmplxNm2.GetLength(), CmplxNm1.GetRad() + CmplxNm2.GetRad());return cmplxnm_result;
}

ComplexNum_Stack_Node.h

ComplexNum_Stack_Node是一个以公有继承ComplexNum的类是一个链栈,在表达式求值中存储复数。

//蔚明
//ComplexNum_Stack_Node.h#pragma once
#include "ComplexNum.h"
#include <iostream>typedef class ComplexNum_Stack_Node* cmplxNm_stack_pst;
typedef class ComplexNum_Stack_Node cmplxNm_stack_st;class ComplexNum_Stack_Node :public ComplexNum
{
public:bool sInitStack_cmplxNm();//初始化一个链栈bool sPush_cmplxNm(cmplxNm_stack_pst& S, ComplexNum e);//入栈bool sPop_cmplxNm(cmplxNm_stack_pst& S, ComplexNum& e);//出栈bool sGetTop_cmplxNm(cmplxNm_stack_pst S, ComplexNum& e);//引用方式得到栈顶元素ComplexNum_Stack_Node* next=NULL;
};

ComplexNum_Stack_Node.c

//蔚明
//ComplexNum_Stack_Node.c#include "ComplexNum_Stack_Node.h"using namespace std;bool ComplexNum_Stack_Node::sInitStack_cmplxNm()//初始化一个链栈
{next = NULL;return true;
}bool ComplexNum_Stack_Node::sPush_cmplxNm(cmplxNm_stack_pst& S, ComplexNum e)//入栈
{cmplxNm_stack_pst p = new ComplexNum_Stack_Node;//为入栈的元素分配空间p->ComplexNumCopy(e);//把要入栈的元素赋给新结点p->next = S;//新结点指向原来的栈顶元素S = p;//让新结点成为栈顶元素return true;}bool ComplexNum_Stack_Node::sPop_cmplxNm(cmplxNm_stack_pst& S, ComplexNum& e)//出栈
{if (S == NULL)//检查是否为空栈{cout << "复数栈空,出栈失败!!!\n" << endl;return false;}cmplxNm_stack_pst temp;e.ComplexNumCopy(*S);//把要弹出的结点的内容赋给etemp = S;//临时保存要弹出的结点S = S->next;//修改栈顶指针delete temp;//把原来的栈顶的内存释放。return true;
}bool ComplexNum_Stack_Node::sGetTop_cmplxNm(cmplxNm_stack_pst S, ComplexNum& e)//引用方式得到栈顶元素
{if (S != NULL){e.ComplexNumCopy(*S);return true;}else{cout << "栈空" << endl;return false;}
}

上述是在造轮子

下面是让计算机理解表达式的算法

从理解这个算法到写出这个算法到一步一步的完善这个算法的细节,虽然这个文件里面的代码不是最长的,但却是最难写的,着实花了我好一番心思才写出来,

//蔚明
//输入表达式分析#include "char链栈.h"
#include "ComplexNum_Stack_Node.h"
#include "复数计算器.h"using namespace std;char MthPriorcmp(char ch1, char ch2)//数学符号优先级对比函数
{int i = 0, j = 0;//循环控制变量bool flag1=false, flag2 = false;char cMathChar[] = { '+','-','*','/','(',')','#' ,'\0' };//输入表达式中可接纳的运算符char cMathCharPriority[7][7] ={//ch1\ch2 +   -    *   /    (   )   #/*+*/{'>','>', '<','<', '<','>','>'},/*-*/{'>','>', '<','<', '<','>','>'},/***/{'>','>', '>','>', '<','>','>'},/*/*/{'>','>', '>','>', '<','>','>'},/*(*/{'<','<', '<','<', '<','=',' '},/*)*/{'>','>', '>','>', ' ','>','>'},/*#*/{'<','<', '<','<', '<',' ','='}};//比较ch1和ch2的优先级的依据for (i = 0; i < 7; i++)//用i找到ch1是cMathChar[]的第几个{if (ch1 == cMathChar[i]){flag1 = true;//只有找到才把flag1置1break;//成功找到退出循环}else flag1 = false;}for (j = 0; j < 7; j++)//与上同理{if (ch2 == cMathChar[j]){flag2 = true;break;}else flag2 = false;}if (flag1 && flag2) return cMathCharPriority[i][j];//成功找到了ch1和ch2是cMathChar[]的第几个,返回在cMathCharPriority中的优先级else return '~';//如果没找到ch1或ch2返回错误标志
}ComplexNum CalculateComplexNum(ComplexNum cmplxNum1, ComplexNum cmplxNum2, char cMathCh)//计算cmplxNum1(复数1) cMathCh(运算符) cmplxNum2(复数2)并返回他的值
{if (cMathCh == '+') return AddComplexNum(cmplxNum1, cmplxNum2);else if (cMathCh == '-') return SubComplexNum(cmplxNum1, cmplxNum2);else if (cMathCh == '*') return MultiComplexNum(cmplxNum1, cmplxNum2);else if (cMathCh == '/') return DiviComplexNum(cmplxNum1, cmplxNum2);else { cout << "符号错误1"; exit(1); }//如果运算符不是+-*/说明输入有误,需要异常退出
}ComplexNum EvaluateExpression(const char *expression)
{stack_pst OPTR=new stack_st;//储存数学符号的工作栈cmplxNm_stack_pst OPND=new ComplexNum_Stack_Node;//储存复数的工作栈Cmplxnum_expression strCmplxnum1;//储存复数的字符表达式的字符串ComplexNum cmplxNum1, cmplxNum2;//储存要操作的复数和要被操作的复数的复数char cMathCh;//临时储存要工作的数学符号sInitStack(OPTR);//初始化一个数学符号工作栈OPND->sInitStack_cmplxNm();//初始化一个储存复数工作栈sPush(OPTR, expression[0]); //把表达式中第一个#号压入数学符号工作栈for (int i = 1; true; i++)//开始执行死循环,这个死循环会通过循环语句内满足的条件使用break语句退出{if (expression[i] == '[')//判断他是否为复数表达式的起始标志{i++;//读[后的内容int k = 0;for (k = 0; expression[i] != ']'; i++, k++)//如果是,则在遇到复数表达式休止符]之前,增加表达式的浮标,并复制给储存复数的字符表达式的字符串{strCmplxnum1[k] = expression[i];}strCmplxnum1[k] = '\0';OPND->sPush_cmplxNm(OPND, GetComplexNum(strCmplxnum1)); //将刚刚录入的复数表达式转换成复数对象,并压入复数工作栈中}else if (expression[i] == '#' && OPTR->data == '#') break;//如果遇到#号并且符串工作栈中也只剩#号说明表达式计算完毕,退出死循环else{sGetTop(OPTR, cMathCh);//将字符工作栈栈顶元素赋给临时数学符号变量switch (MthPriorcmp(cMathCh, expression[i]))//使用数学符号优先级对比函数对比数学符号工作栈栈顶元素和表达式浮标所指的元素{case '<': sPush(OPTR, expression[i]); break;//优先级小则把浮标所指元素压入字符工作栈中case '>':{//从复数工作栈中弹出两个复数第一个弹出来的复数作为操作数,第二个弹出来的复数作为被操作数,从数学符号工作栈中弹出一个数学符号sPop(OPTR, cMathCh);OPND->sPop_cmplxNm(OPND, cmplxNum2);OPND->sPop_cmplxNm(OPND, cmplxNum1);OPND->sPush_cmplxNm(OPND, CalculateComplexNum(cmplxNum1, cmplxNum2, cMathCh));//把弹出来的两个复数和一个数学符号进行运算并把他的值重新压入复数工作栈i--;//由于浮标目前所指的数学符号还没有发挥作用所以要把浮标减一进入下一次循环的时候,浮标会加一这样子就可以让浮标原地踏步一次break;}case '='://如果优先级相等,则括号匹配成功把左括号弹出{sPop(OPTR, cMathCh);break;}default: {cout << MthPriorcmp(cMathCh, expression[i]) << "符号错误2"; exit(1); }//如果是异常字符则说明表达式输入错误。异常退出程序}}}OPND->sPop_cmplxNm(OPND, cmplxNum2);//把最终结果赋给复数二return cmplxNum2;//返回复数二
}

运行结果如图

我定义的所有变量,除了循环控制变量,以外,都是有英文意思的,看不懂代码的可以直接查一下它的英文意思。

C++边学边用,使用类完成复数运算,可自动识别表达式(详细注释)相关推荐

  1. 【零基础学Java】—Socket类(五十五)

    [零基础学Java]-Socket类(五十五) Socket类:该类实现客户端套接字,套接字是指两台设备之间通讯的端点. 在Java中,提供了两个类用于实现TCP通信程序 客户端:java.net.S ...

  2. 【零基础学Java】—System类(三十五)

    [零基础学Java]-System类(三十五) java.lang.System 类中提供了大量的静态方法,可以获取与系统相关的信息或系统级操作 在System类的API文档中,常用的方法有: pub ...

  3. 【零基础学Java】—Calendar类(三十四)

    [零基础学Java]-Calendar类(三十四) java.util.Calendar日历类 Calendar类是一个抽象类,里面提供了很多操作日历字段的方法 Calendar类无法直接创建对象,里 ...

  4. 【零基础学Java】—Scanner类的使用( 十)

    [零基础学Java]-Scanner类的使用( 十) Scanner类的功能:可以实现键盘输入数据,到程序中去. 引用类型的一般使用步骤: 1️⃣ 导包 import 包路径.类名称: 如果需要使用的 ...

  5. 测绘类专业计算机要学什么科目,测绘类专业选考科目要求是什么

    测绘类专业选考科目要求是什么2019-08-23 14:49:46文/尹乙晴 高考综合改革实施方案"3+1+2"模式已经逐步实施,大家都很想知道各专业对科目的要求是什么样的,以下是 ...

  6. 阿翔编程学-Axis日志服务类

    阿翔编程学-Axis日志服务类 //=========================================================== //日志服务类程序 author:曹翔 // ...

  7. 《手把手陪您学Python》42——类的魔法方法

    在上一篇<手把手陪您学Python>41--类方法与实例方法中,我们引入了类方法的概念,并介绍了类方法与实例方法在语法规则和引用方面的差异.今天,我们将会继续介绍实例方法的应用,并介绍一种 ...

  8. AI之NLP:自然语言处理技术简介(是什么/学什么/怎么用)、常用算法、经典案例之详细攻略(建议收藏)

    AI之NLP:自然语言处理技术简介(是什么/学什么/怎么用).常用算法.经典案例之详细攻略(建议收藏) 目录 NLP是什么? 1.NLP前置技术解析 2.python中NLP技术相关库 3.NLP案例 ...

  9. AI之NLP:自然语言处理技术简介(是什么/学什么/怎么用)、常用算法、经典案例之详细攻略(建议收藏)daiding

    AI之NLP:自然语言处理技术简介(是什么/学什么/怎么用).常用算法.经典案例之详细攻略(建议收藏) 目录 NLP是什么? 1.NLP前置技术解析 2.python中NLP技术相关库 3.NLP案例 ...

最新文章

  1. php去除中间空格,php删除字符串中间空格的方法
  2. 【每周CV论文推荐】 掌握残差网络必读的10多篇文章
  3. WLAN产品形态之分层架构
  4. 微信小程序小模块界面,边框带阴影
  5. C和汇编混合编程---do while
  6. java枚举比较大小写_字符串与Java枚举的不区分大小写的匹配
  7. Python __init__.py 作用详解
  8. Oracle Sql关于case-when,if-then,decode
  9. 导论II大作业提交-辩论计时器代码
  10. 计算机系统安装操作,电脑安装操作系统的3种方法,好好看看,以后装系统你说了算!...
  11. windows 一键切换ip dns脚本
  12. 数据中心基础设施运维有哪些项目?哪些系统?如何实施?
  13. java技术cad转图片_一键完成百张图纸转换,教你最简单CAD转JPG格式方法,只需三步...
  14. Vue项目:电商后台管理管理系统
  15. 窃取5亿雅虎用户信息的黑客 被判处5年有期徒刑
  16. 一个由“2020年1月7日 京东出现的重大 Bug 漏洞“引起的思考......
  17. python(3.6) django(1.11.1)问题积累
  18. thinkphp使用migration/Seeder
  19. python生成一个四位数字的随机数
  20. 安利几本好看的书给你

热门文章

  1. LuoguP4313 BZOJ3894 文理分科——最小割
  2. BZOJ 3894 文理分科
  3. 职业发展,选择大都市还是回老家?
  4. iOS让App后台运行方法小结
  5. 学习html的心得总结
  6. 恐怖的广告推送。其实,我们每天都在“裸奔”!
  7. Jmeter的Html报告汉化及解析
  8. s_p_a_r_k_内核
  9. ListView--QQ联系人样式
  10. 《基于短时分数阶傅里叶变换的时频分析方法》