C++计算器 支持复数运算

1. 计算器类

整体框架采用面向对象的方法,计算方法采用“算符优先算法”和“后缀表达式算法”。

定义一个计算器类。利用计算器类的实例化对象调用类中定义的运算方法以实现表达式的计算。

class Calculator
{
public:
	Calculator();
	void getFormat();					//表达式自定义标准格式化
	int getPrior(char c);				//获取算术符号优先级
	void getPostfix();					//后缀表达式转换
	void calResult();					//计算结果
	void calculate();					//计算方法
	double getResult();					//获取结果

	string operatorSym;					//运算符号
	string infix;						//表达式缓存

private:
	vector<string> postfix;				//后缀表达式向量
	stack<char> symStack;				//符号栈
	stack<double> figStack;				//数字栈
	string stdInfix;					//自定义标准格式化表达式
	double result;						//最终计算结果
};

整个计算方法大体划分为3个模块,实现一个总的计算方法,用来调用相关计算模块。

//计算方法
void Calculator::calculate(string infix) {
getFormat(infix);			//表达式自定义标准格式化
getPostfix();				//后缀表达式转换
calResult();				//计算结果
}

1 功能实现

  1. 符号功能实现

a) ‘+’、‘-’、‘*’、‘/’:加减乘除运算。

b) ‘^’:幂次方运算。

c) “( )、 [ ] 、{ }”:三种括号的实现。

  1. 数字功能实现

a) 0~9。

b) 小数运算。

c) 正负数运算。

2 运算优先级功能实现

运算的规则和顺序由运算符的优先级关系确定,这是运算的核心,因此首先必须明确符号之间的优先级关系。

  1. 基本符号优先级:

5个优先级分别对应0~3。

enum PRIO_LV {

   PRIO_LV0 = 0,

   PRIO_LV1 = 1,

   PRIO_LV2 = 2,

   PRIO_LV3 = 3,

};

获取符号优先级函数,用于转换后缀表达式时对符号优先级的比较。

//获取算术符号优先级
int Calculator::getPrior(char c) {

	if (c == '+' || c == '-') {
		return PRIO_LV1;
	}
	else if (c == '*' || c == '/') {
		return PRIO_LV2;
	}
	else if (c == '%' || c == '^' || c == '~') {
		return PRIO_LV3;
	}
	else {
		return PRIO_LV0;
	}
	//else { cout << c << 非法符号! << endl; }
}
  1. 括号型符号优先级:

( )、[ ]、{ } 括号型,左括号优先级再、在所有符号中为最低优先级,右括号为最高优先级。4种括号型暂无相对优先级,为同等优先级。

1 构造函数,初始化成员变量

Calculator::Calculator() {           

    result = 0.0;

    cal_ErrorImfo = "";

}

2 正负数格式化模块

该模块用来实现表达式的正负数形式。通过在正负数的‘+’或‘-’符号前加一个0实现,以便于整个表达式的计算。即:-x转换为0-x,+x转化为0+x。

Created with Raphaël 2.3.0 开始 遍历表达式 是否为 + 或 - 在表达式开头或前面是左括号 在+ -号前插入0 结束框 yes no yes
//表达式自定义标准格式化
void Calculator::getFormat() {

	stdInfix = infix;

	//实现正负数
	
	for (size_t i = 0; i < stdInfix.size(); i++) {					//string.size()返回size_type类型,避免下标运算时的类型溢出
		if (stdInfix[i] == '-' || stdInfix[i] == '+') {				//-x转换为0-x,+x转化为0+x
			if (i == 0) {
				stdInfix.insert(0, 1, '0');
			}
			else if (stdInfix[i - 1] == '(') {
				stdInfix.insert(i, 1, '0');
			}
		}
	}

}

3 后缀表达式转换

计算机处理中缀表达式的计算比较复杂,应转换为前缀或后缀表达式。该程序改用后缀表达式法,利用定义的符号栈按照算术符号的优先级来做中缀表达式到后缀表达式的转换。

转换如下:

中缀表达式a + b*c + (d * e + f) * g,其转换成后缀表达式则为a b c * + d e * f + g * +。

转换过程需要用到栈,具体过程如下:

1)如果遇到操作数,我们就直接将其输出。

2)如果遇到操作符,则我们将其放入到栈中,遇到左括号时我们也将其放入栈中。

3)如果遇到一个右括号,则将栈元素弹出,将弹出的操作符输出直到遇到左括号为止。注意,左括号只弹出并不输出。

4)如果遇到任何其他的操作符,如(“+”, “*”,“(”)等,从栈中弹出元素直到遇到发现更低优先级的元素(或者栈为空)为止。弹出完这些元素后,才将遇到的操作符压入到栈中。有一点需要注意,只有在遇到" ) “的情况下我们才弹出” ( “,其他情况我们都不会弹出” ( "。

5)如果我们读到了输入的末尾,则将栈中所有元素依次弹出。

4 计算后缀表达式

遍历后缀表达式,创建数字栈,是数字则入栈,是算术符号则出栈响应的数字个数并利用相应的符号计算得出结果数后,将该结果数入栈,以此循环直到后缀表达式遍历完成,栈中最后一个数即为最终结果。

Created with Raphaël 2.3.0 开始 i = 0 i < size ? 是数字? 入栈 i++ 数字出栈, 对应计算 结束框 yes no yes no

2. 复数类

建立Complex类, 并根据复数加减乘除规则进行了操作符的重写

class Complex {
private:
	float Real, Imag;
public:
	Complex(float r = 0, float i = 0) {
		Real = r;
		Imag = i;
	}
	//显示输出复数
	void show() {
		cout << Real << "+" << Imag << "i";
	}
	Complex operator +(Complex& c);//"+"运算符重载完成复数间的加法运算
	Complex operator +(float s);//"+"完成实部与实数的加法运算
	Complex operator -(Complex& c);
	Complex operator -(float s);
	Complex operator *(Complex& c);
	Complex operator *(float s);
	Complex operator /(Complex& c);
	Complex operator / (float s);
	Complex conj(void);
};
Complex Complex::operator +(float s) {
	Complex t;
	t.Real = Real + s;
	t.Imag = Imag;
	return t;
}

Complex Complex::operator-(Complex& c) {
	Complex t;
	t.Real = Real - c.Real;
	t.Imag = Imag - c.Imag;
	return t;
}

Complex Complex::operator-(float s) {
	Complex t;
	t.Real = Real + s;
	t.Imag = Imag - s;
	return t;
}

Complex Complex::operator *(Complex& c) {
	Complex t;
	t.Real = Real * c.Real - Imag * c.Imag;
	t.Imag = Real * c.Imag + Imag * c.Real;
	return t;
}

Complex Complex::operator *(float s) {
	Complex t;
	t.Real = Real * s;
	t.Imag = Imag * s;
	return t;
}

Complex Complex::operator /(Complex& c) {
	Complex t;
	if (c.Real != 0 && c.Imag != 0) {
		t.Real = (Real * c.Real + Imag * c.Imag) / (c.Real * c.Real + c.Imag * c.Imag); //实部除积
		t.Imag = (Imag * c.Real - Real * c.Imag) / (c.Real * c.Real + c.Imag * c.Imag); //虚部除积
		return t;
	}
	else {
		cout << "分母为0,不能执行命令";
		return -1;
	}
}

Complex Complex::operator /(float s) {
	Complex t;
	if (s != 0.0) {
		t.Real = Real / s;
		t.Imag = Imag / s;
		return t;
	}
	else {
		cout << "分母为0,不能执行命令";
		return -1;
	}
}

Complex Complex::conj(void) {
	Complex t;
	t.Real = Real;
	t.Imag = -Imag;
	return t;
}

3. 主函数

通过用户输入来控制进行实数域的计算还是复数域的计算, 分别调用相应的语句执行相关计算

cout << "欢迎来到高性能计算器!" << endl;
	Calculator cal;

	while (true) {
		
		cout << "实数运算输入1, 复数运算输入2" << endl;

		int choice = 1;
		cin >> choice;
		cin.ignore(); // 清除换行符

		if (choice == 1) {
			cout << cal.operatorSym << endl;
			cout << "-----------------------" << endl;
			
			getline(cin, cal.infix);
			cal.calculate();
			cout << cal.getResult() << endl;
			cout << "-----------------------" << endl;
		}
		if (choice == 2)
		{
			cout << "虚数运算部分:" << endl;
			cout << "-----------------------" << endl;
			float a, b, c, d;
			cout << "请输入第一个复数的实部与虚部:";
			cin >> a >> b;
			cout << "请输入第二个复数的实部与虚部:";
			cin >> c >> d;
			Complex A(a, b), B(c, d), C, D, E, F, G, H;
			C = A + B, D = A - B, E = A * B, F = A / B, G = A.conj(), H = B.conj();
			cout << "加法:"; A.show(); cout << "+"; B.show(); cout << "="; C.show(); cout << endl;
			cout << "减法:"; A.show(); cout << "-"; B.show(); cout << "="; D.show(); cout << endl;
			cout << "乘法:("; A.show(); cout << ")*("; B.show(); cout << ")="; E.show(); cout << endl;
			cout << "除法:("; A.show(); cout << ")/("; B.show(); cout << ")="; F.show(); cout << endl;
			cout << "-----------------------" << endl;
		}

	}
	return 0;
		cout << "减法:"; A.show(); cout << "-"; B.show(); cout << "="; D.show(); cout << endl;
		cout << "乘法:("; A.show(); cout << ")*("; B.show(); cout << ")="; E.show(); cout << endl;
		cout << "除法:("; A.show(); cout << ")/("; B.show(); cout << ")="; F.show(); cout << endl;
		cout << "-----------------------" << endl;
	}

}
return 0;

#include #include #include #include #include #include #define EPS 1e-5 //定义精度常数 using namespace std; //使用标准空间命名std namespace NameCComplex //定义命名空间NameCComplex { class CComplex ////定义一个CComplex类 { private: double Real,Image; public: CComplex(double real=0,double image=0) //构造函数 { Real=real; Image=image; } friend istream & operator>>(istream &is,CComplex &com); //重载输入 friend ostream & operator<(CComplex &com); int operator(CComplex &com) //重载运算符">",比较模的大小 { if(mod()>com.mod()) return 1; else return 0; } int CComplex::operator<(CComplex &com) { if(mod()>(istream &is,CComplex &com) //重载输入,可以输入a+bi的形式 { cout<>s; //用字符串的形式接受复数 int len=strlen(s); //求出字符串的长度 int n=0,sign=1; //n为当前从字符串中提取出来的数字,初始化为0;sign是难道符号,初始化为正 com.Image=com.Real=0; for(int k=0;k<len;k++) //判断接受的字符串是否合法 { if((s[k] '9') && (s[k]!='+' && s[k]!='-' && s[k]!='i')) { cout<<"error"<<endl; return is; //错误,输出出错信息并返回 } } for(k=0;k<len;) //顺序识别字符串中各字符 { if(n!=0 &&(s[k]=='-'||s[k]=='+')) //当前字符是否是符号位 { com.Real=sign*n; //是符号位,且n!=0,即n已被赋值,表明当前读取的是虚部的符号 n=0; //将原n*sign值赋给实部,将n清零,准备接受虚部的值 } if(s[k]=='-') //当前字符为负号 { sign=-1;k++; //给符号标志赋值 } if(s[k]=='+') //当前字符为正号 { sign=1;k++; //给符号标志赋值 } if(s[k]=='i') //当前字符为'I' { if(k!=len-1) //判断字符'I'是否为字符串中作后一个字符 cout<='0' && s[k]<='9') //当前字符在0~9之间,将数字字符转换成数字数值 { n=n*10+s[k]-'0'; k++; } } if(s[len-1]!='i' && n!=0) //如果最后一个字符不是'I',表示复数对象内只有实部,没有虚部 { com.Real=n*sign; } return is; } ostream & operator<<(ostream &os,CComplex &com) //重载输入 { if(fabs(com.Image)<EPS) // 如果虚部为0 os<<com.Real; //只输出实部 else if((fabs(com.Real)<EPS)) //如果实部为0 os<<com.Image<0) os<<com.Real<<"+"<<com.Image<<"i"; else os<<com.Real<<com.Image<<"i"; //虚部为正 return os; } CComplex CComplex::operator+(CComplex &com) //加法重载 { CComplex sum; sum.Real=Real+com.Real; //实部相加 sum.Image=Image+com.Image; //虚部相加 return sum; } CComplex CComplex::operator*(CComplex &com) //乘法重载 { CComplex multi; multi.Real=Real*com.Real-Image*com.Image; //乘积实部 multi.Image=Real*com.Image+Image*com.Real; //乘积虚部 return multi; } CComplex CComplex::operator-(CComplex &com) //减法重载 { CComplex sub; sub.Real=Real-com.Real; sub.Image=Image-com.Image; return sub; } CComplex CComplex::operator+=(CComplex &com) //重载加法赋值 { Real=Real+com.Real; Image=Image+com.Image; return *this; } CComplex CComplex::operator-=(CComplex &com) //重载减法赋值 { Real=Real-com.Real; Image=Image-com.Image; return *this; } CComplex CComplex::operator*=(CComplex &com) //重载乘法赋值 { double nReal=Real*com.Real-Image*com.Image; double nImage=Real*com.Image+Image*com.Real; Real=nReal; Image=nImage; return *this; } int CComplex::operator==(CComplex &com) //重载等于 { if(Real==com.Real && Image==com.Image) return 1; else return 0; } void Test(void) //测试函数 { user.nTest++; cout<<"共10道题,做100以内的加减运算,满分100分:\n"; double real1,real2,image1,image2,real3,real4,image3,image4; CComplex answer,temp; int score=0; char op; for(int i=0;i<=9;i++) { /////为复数产生随机值 real1=rand()%200-100; image1=rand()%200-100; real2=rand()%200-100; image2=rand()%200-100; CComplex a(real1,image1),b(real2,image2); real3=rand()%20-10; image3=rand()%20-10; real4=rand()%20-10; image4=rand()%20-10; CComplex c(real3,image3),d(real4,image4); op=rand()%3; //产生随机加减乘法运算的三个值 switch(op) { case 0: answer=a+b; cout<<a<<"加上"<<b<<"等于"; break; case 1: answer=a-b; cout<<a<<"减去"<<b<<"等于"; break; case 2: answer=c*d; cout<<c<<"乘以"<<d<>temp; //输入用户计算值 if(answer==temp) //比较用户计算值 { score+=10; } else { cout<<"此题做错了\n"; cout<<"正确答案为:"<<answer<<endl; } } cout<<"你的最后得分是:"<<score<<endl; if(user.nTest<=3) { user.alAve=0; user.dlScore[user.nTest-1]=score; for(int i=0;i<user.nTest;i++) user.alAve+=user.dlScore[i]; user.alAve=user.alAve/user.nTest; } else { user.dlScore[0]=user.dlScore[1]; user.dlScore[1]=user.dlScore[2]; user.dlScore[2]=score; for(i=0,user.alAve=0;i<3;i++) user.alAve+=user.dlScore[i]; user.alAve=user.alAve/3; } cout<<"请按任意键继续\n"; cout.flush(); cin.get(); cin.get(); } void Add() //复数加法运算函数 { user.nAdd++; CComplex num1,num2,sum,Zero(0,0); cout<<"加法计算\n"<<"最少输入两个复数,并且以0结束\n"; cout<>num1; cout<>num2; sum=num1+num2; cout<>num1; int i=4; while(!(num1==Zero)) { sum=sum+num1; cout<<"第"<<i<>num1; i++; } cout<<"加法结果是:"<<sum<<endl; cout<<"请按任意键继续\n"; cout.flush(); cin.get(); cin.get(); } void Sub() //复数减法预算函数 { user.nSub++; CComplex num1,num2,sub,Zero(0,0); cout<<"最少输入两个复数,并且以0结束\n"; cout<>num1; cout<>num2; sub=num1-num2; cout<>num1; int i=4; while(!(num1==Zero)) { sub=sub-num1; cout<<"第"<<i<>num1; i++; } cout<<"减法结果是:"<<sub<<endl; cout<<"请按任意键继续\n"; cout.flush(); cin.get(); cin.get(); } void Mul() //复数乘积函数 { user.nMul++; CComplex num1,num2,mul,Zero(0,0); cout<<"乘法计算\n"<<"最少输入两个复数,并且以零结束\n"; cout<>num1; cout<>num2; mul=num1*num2; cout<>num1; int i=4; while(!(num1==Zero)) { mul*=num1; cout<<"第"<<i<>num1; i++; } cout<<"乘法结果是:"<<mul<<endl; cout<>num1; ++num1; cout<<"自加的结果为"<<num1<<endl; cout<>num1; --num1; cout<<"自减的结果为"<<num1<<endl; cout<<"按任意键结束\n"; cout.flush(); cin.get(); cin.get(); } void compare() //两复数比较函数 { CComplex num1,num2; cout<<"输入两个复数\n"; cout<>num1; cout<>num2; if(num1==num2) cout<num2) cout<<num1<<"的模大于"<<num2<<"的模\n"; else if(num1<num2) cout<<num2<<"的模大于"<<num1<<"的模\n"; else cout<<"这两个复数的模相等\n"; cout<<"按任意键继续\n"; cin.get(); cin.get(); } void userprint() //输出用户信息函数 { cout<<user.szName<<"使用的次数为:"<<user.nTime<<endl; cout<<"其中:\t加法的次数:"<<user.nAdd<<"\t减法的次数:"<<user.nSub<<"\t乘法的次数:"<<user.nMul<<endl; cout<<"\t测试次数:"<<user.nTest<<"\t平均成绩:"<<user.alAve<<endl; } void Login() //当前用户信息函数 { char szName[20]; cout<<"请输入您的姓名:"; cin.getline(szName,20); ifstream infile; User user1; infile.open("user.dat",ios::binary|ios::in); if(!infile) { cout<<"没有原始记录文件,您是第一个用户!\n"; strcpy(user.szName,szName); user.nTest++; return; } infile.read((char *)&user1,sizeof(User)); while(!infile.eof()) { if(strcmp(user1.szName,szName)==0) { user=user1; user.nTime++; cout<<"欢迎您再次使用复数计算器!"; userprint(); cin.get(); infile.close(); return; } infile.read((char *) &user1,sizeof(User)); } cout<<"欢迎您再次使用复数计算器!"; strcpy(user.szName,szName); user.nTime++; infile.close(); return; } void SaveFile() //用户资料保存函数 { userprint(); fstream file; User user1; file.open("user.dat",ios::binary|ios::in|ios::out); if(!file) { cout<<"文件打开错误,不能进行更新!\n"; return; } file.seekp(0,ios::beg); while(!file.eof()) { file.read((char *)&user1,sizeof(User)); if(strcmp(user1.szName,user.szName)==0) { file.seekp(-(sizeof(User)),ios::cur); file.write((char *)&user,sizeof(User)); file.close(); return; } } file.close(); fstream outfile; outfile.open("user.dat",ios::binary|ios::app); outfile.write((char *)&user,sizeof(User)); outfile.close(); return; } } using namespace NameCComplex; int main(void) //主函数开始 { srand(time(NULL)); //初始化随机数“种子”语句 Login(); //当前用户信息函数 char strChoise[20]; //定义字符串名 do { system("cls"); cout<<"\t这是一个简单的复数计算器程序,可以实现以下功能,请按对应的按键(1-7)\n\n\n"; cout<<"\t=========================MENU===========================\n"; cout<<"\t1:多复数加法,以0结束\n"; cout<<"\t2:多复数减法,以0结束\n"; cout<<"\t3:测试100以内的复数加减乘法运算,1次测试10道题\n"; cout<<"\t4:多复数乘法,以0结束\n"; cout<<"\t5:复数自加\n:"; cout<<"\t6:复数自减\n:"; cout<<"\t7:复数比较\n:"; cout<<"\t0:退出程序\n\n:"; cout<>strChoise; if(strcmp(strChoise,"1")==0) //用户选1则调用Add()函数 Add(); else if(strcmp(strChoise,"2")==0) //用户选2则调用Sub()函数 Sub(); else if(strcmp(strChoise,"3")==0) //用户选3则调用Test()函数 Test(); else if(strcmp(strChoise,"4")==0) //用户选4则调用Add()函数 Mul(); else if(strcmp(strChoise,"5")==0) //用户选5调用Add1()函数 Add1(); else if(strcmp(strChoise,"6")==0) //用户选6则调用Sub1()函数 Sub1(); else if(strcmp(strChoise,"7")==0) //用户选7则调用Compare()函数 compare(); else if(strcmp(strChoise,"0")==0) //用户选0则结束调用函数 { cout<<"\n\n\t欢迎下次继续使用复数计算器!\n\n"; break; } else { cout<<"\n\t输入错误,请按任意键继续!\n"; cin.get(); cin.get(); } } while((strcmp(strChoise,"0"))); SaveFile(); //调用用户资料保存函数 return 0; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值