c++ 写一个复数计算器

26kb
(只有24kb !!!)
链接:https://pan.baidu.com/s/15upavBIQ8m5yI2kmC3skGg
提取码:hnqu
复制这段内容后打开百度网盘手机App,操作更方便哦
源代码在文末


高中学算法后,一直想写一个有用的 的程序,比如说计算器。
百度了一圈后发现复数计算器,貌似还没人写。那就写这个吧
当然,目前这个计算器还存在一些小问题,我也不一定会再改了 ()
但我觉得,还是有一定参考价值的
参考博客 “中序表达式”转换为“前序表达式”、“后序表达式”

大概需要的知识:
1.栈的概念
2.类的相关操作


一个计算器的类,应该有这三个功能:
1.输入一个表达式
2.开始计算
3.打印答案

由这三个功能,再思考具体的实现:
1.我应该怎么输入数据?
2.我该怎么存数据?
3.我该怎么打印答案?
4.我应该用什么算法?
5.怎么设计用户界面?
6.怎么测试?(建议实现每一个功能就独立测试一下)


第二版代码如下:现在修复了:不能直接输入负数和答案为0时无输出的bug
准备:添加输入角度与函数,更新菜单说明


全部代码大约500行

//calculator.h
#ifndef CALCULATOR_H
#include<string>
using namespace std;

struct element
{
	bool type;		//false 表示这个是数字,true 表示这个是操作
	double a, b;	//复数的实部和虚部
	int op;			//从 0 开始定义 分别为: 左括号、右括号、加、减、乘、除
};
class calculator
{
	static const int MAX_NUM = 10086;		//假设最多100086个操作数或操作符
	static const int priority[6];			//各运算符优先级
private:
	element all_element[MAX_NUM];			//下标[0,element_num)

	int element_num;						//有多少个元素
	int p_o_e_num;							//先序表达式有多少个元素
	int stack_num;							//栈里面带的元素

	int middel_order_expression[MAX_NUM];	//中序表达式
	int preorder_expression[MAX_NUM];		//先序表达式
	int stack[MAX_NUM];						//中序转先序需要用一个栈,从1开始放;计算过程也需要一个栈
	
	element ans;							//该计算式的答案
	void get_m_o_e();						//得到中序表达式
	void get_p_o_e();						//得到先序表达式

public:
	calculator();					//默认构造函数
	bool get(string);				//接受一个计算表达式并保存为中序表达式,如果表达式有语法错误,则返回false
	void print(int i);				//打印计算表达式(0 为中序,其它为前序)
	void calculate();				//开始计算
	void print_ans();				//得到答案
	void clear();					//清除上次运算

	string element_to_string(element&);		//将一个element 变成string

	bool Greater_than_equal_to_or_equal_to(element , element );
};

#endif // !CALCULATOR_H
//calculator.cpp
#include<cmath>
#include<string>
#include<cstring>
#include<iostream>
#include<iomanip>
#include"calculator.h"
using namespace std;

const int calculator::priority[6] = { 666,666,0,0,1,1 };

calculator::calculator()
{
	clear();
}
bool calculator::get(string t)
{
	int amazing = 0;	//括号数
	int tl = int (t.length());
	//依次处理字符
	for (int i = 0; i < tl; i++)
	{
		//处理完一个元素后,i 指向元素末尾
		//大胆地把一个复数拆成一个实数加一个纯虚数

		//负数 (当负号前面不是一个数字时,既判定为负数)
		if (t[i] == '-' && (t[i - 1] < '0' || t[i-1] > '9' ))
		{
			i++;
			//处理实数
			if (t[i] >= '0'&&t[i] <= '9')
			{
				all_element[element_num].type = false;
				double tsum = 0;
				int p1 = 10;	//整数部分的权
				double p2 = 0.1;//小数部分的权
				do
				{
					tsum = tsum * p1 + t[i] - '0';
					i++;
				} while (t[i] >= '0'&&t[i] <= '9');
				if (t[i] == '.')
				{
					i++;
					do
					{
						tsum = tsum + (t[i] - '0')*p2;
						p2 *= 0.1;
						i++;
					} while (t[i] >= '0'&&t[i] <= '9');
				}
				all_element[element_num].a = -tsum;
				i--;
				//cout << i <<" is "<< all_element[element_num].a << 'j' << all_element[element_num].b << endl;
			}

			//处理虚数
			else 
			{
				all_element[element_num].type = false;
				i++;
				double tsum = 0;
				int p1 = 10;	//整数部分的权
				double p2 = 0.1;//小数部分的权
				do
				{
					tsum = tsum * p1 + t[i] - '0';
					i++;
				} while (t[i] >= '0'&&t[i] <= '9');
				if (t[i] == '.')
				{
					i++;
					do
					{
						tsum = tsum + (t[i] - '0')*p2;
						p2 *= 0.1;
						i++;
					} while (t[i] >= '0'&&t[i] <= '9');
				}
				all_element[element_num].b = tsum;
				i--;
			}
		}
		else
		{
			//处理实数
			if (t[i] >= '0'&&t[i] <= '9')
			{
				all_element[element_num].type = false;
				double tsum = 0;
				int p1 = 10;	//整数部分的权
				double p2 = 0.1;//小数部分的权
				do
				{
					tsum = tsum * p1 + t[i] - '0';
					i++;
				} while (t[i] >= '0'&&t[i] <= '9');
				if (t[i] == '.')
				{
					i++;
					do
					{
						tsum = tsum + (t[i] - '0')*p2;
						p2 *= 0.1;
						i++;
					} while (t[i] >= '0'&&t[i] <= '9');
				}
				all_element[element_num].a = tsum;
				i--;
				//cout << i <<" is "<< all_element[element_num].a << 'j' << all_element[element_num].b << endl;
			}

			//处理虚数
			else if (t[i] == 'j')
			{
				all_element[element_num].type = false;
				i++;
				double tsum = 0;
				int p1 = 10;	//整数部分的权
				double p2 = 0.1;//小数部分的权
				do
				{
					tsum = tsum * p1 + t[i] - '0';
					i++;
				} while (t[i] >= '0'&&t[i] <= '9');
				if (t[i] == '.')
				{
					i++;
					do
					{
						tsum = tsum + (t[i] - '0')*p2;
						p2 *= 0.1;
						i++;
					} while (t[i] >= '0'&&t[i] <= '9');
				}
				all_element[element_num].b = tsum;
				i--;
			}

			//处理其他操作
			else
			{
				all_element[element_num].type = true;
				int op_type;
				switch (t[i])
				{
				case '(':
					op_type = 0;
					amazing++;
					break;
				case '(':
					op_type = 0;
					amazing++;
					break;
				case ')':
					op_type = 1;
					amazing++;
					break;
				case ')':
					op_type = 1;
					amazing++;
					break;
				case '+':
					op_type = 2;
					break;
				case '-':
					op_type = 3;
					break;
				case '*':
					op_type = 4;
					break;
				case '/':
					op_type = 5;
					break;
				default:
					return false;
					break;
				}
				all_element[element_num].op = op_type;
			}
		}

		//显然,现在的元素数量要加一个了
		element_num++;
	}
	p_o_e_num = element_num - amazing;
	//得到中序表达式
	get_m_o_e();
	//得到先序表达式
	get_p_o_e();
	return true;
}

void calculator::print(int choice)
{
	int *p = (choice == 0 ? middel_order_expression : preorder_expression);
	int t = (choice == 0 ? element_num : p_o_e_num);
	for (int i = 0; i < t; i++)
	{
		//如果是操作
		if (all_element[p[i]].type)
		{
			char op_type;
			switch (all_element[p[i]].op)
			{
			case 0:
				op_type = '(';
				break;
			case 1:
				op_type = ')';
				break;
			case 2:
				op_type = '+';
				break;
			case 3:
				op_type = '-';
				break;
			case 4:
				op_type = '*';
				break;
			case 5:
				op_type = '/';
				break;
			default:
				cout << "what?" << endl;
				return ;
				break;
			}
			cout << op_type;
		}
		//如果是数字
		else
		{
			//cout 默认输出double 的六位小数
			//这里由于参考资料上写double 有效位数为15 位, 故设之
			//默认实部或者虚部是0,则不输出实部或虚部
			if (all_element[p[i]].a != 0)
			{
				cout << setprecision(15) << all_element[p[i]].a;
				if (all_element[p[i]].b != 0)
				{
					cout << "+j" << setprecision(15) << all_element[p[i]].b;
				}
			}
			else
			{
				if (all_element[p[i]].b != 0)
				{
					cout << "j" << setprecision(15) << all_element[p[i]].b;
				}
				else
				{
					cout << '0';
				}
			}
		}
	}
	cout << endl;
}

void calculator::calculate()
{
	//计算会改变前序表达式和所有元素,所以在计算完在查看元素或表达式就会得到错误结果
	for (int i = p_o_e_num - 1 ; i >= 0; i--)
	{
		double ttt;
		if (all_element[preorder_expression[i]].type)
		{
			all_element[preorder_expression[i]].type = false;	//这个操作的结果存在这
			//下面的式子写的长了一点
			switch (all_element[preorder_expression[i]].op)
			{
			case 2:				// +
				all_element[preorder_expression[i]].a = all_element[stack[stack_num]].a + all_element[stack[stack_num - 1]].a;
				all_element[preorder_expression[i]].b = all_element[stack[stack_num]].b + all_element[stack[stack_num - 1]].b;
				stack_num -= 2;
				break;
			case 3:				// -
				all_element[preorder_expression[i]].a = all_element[stack[stack_num]].a - all_element[stack[stack_num - 1]].a;
				all_element[preorder_expression[i]].b = all_element[stack[stack_num]].b - all_element[stack[stack_num - 1]].b;
				stack_num -= 2;
				break;
			case 4:				// *
				all_element[preorder_expression[i]].a = all_element[stack[stack_num]].a * all_element[stack[stack_num - 1]].a - all_element[stack[stack_num]].b * all_element[stack[stack_num - 1]].b;
				all_element[preorder_expression[i]].b = all_element[stack[stack_num]].b * all_element[stack[stack_num - 1]].a + all_element[stack[stack_num]].a * all_element[stack[stack_num - 1]].b;
				stack_num -= 2;
				break;
			case 5:				// /
				ttt = all_element[stack[stack_num - 1]].a * all_element[stack[stack_num - 1]].a + all_element[stack[stack_num - 1]].b * all_element[stack[stack_num - 1]].b;

				all_element[preorder_expression[i]].a = (all_element[stack[stack_num]].a * all_element[stack[stack_num - 1]].a + all_element[stack[stack_num]].b * all_element[stack[stack_num - 1]].b)/ ttt;
				all_element[preorder_expression[i]].b = (all_element[stack[stack_num]].b * all_element[stack[stack_num - 1]].a - all_element[stack[stack_num]].a * all_element[stack[stack_num - 1]].b)/ ttt;
				
				stack_num -= 2;
				break;
			default:
				cout << "见鬼了" << endl;
				return;
				break;
			}
		}
		stack[++stack_num] = preorder_expression[i];
		/*
		look look stack
		cout << stack_num << endl;
		cout << all_element[stack[3]].a << " + j " << all_element[stack[3]].b << endl;
		cout << all_element[stack[2]].a << " + j " << all_element[stack[2]].b << endl;
		cout << all_element[stack[1]].a << " + j " << all_element[stack[1]].b << endl;
		*/
	}
		
	ans = all_element[preorder_expression[0]];
}

void calculator::print_ans()
{
	if (ans.a != 0)
	{
		cout << setprecision(15) << ans.a;
		if (ans.b != 0)
		{
			if (ans.b > 0)
			{
				cout << "+j" << setprecision(15) << ans.b;
			}
			else
			{
				cout << "-j" << setprecision(15) << -ans.b;
			}
		}
	}
	else
	{
		if (ans.b != 0)
		{
			if (ans.b > 0)
			{
				cout << "+j" << setprecision(15) << ans.b;
			}
			else
			{
				cout << "-j" << setprecision(15) << -ans.b;
			}
		}
		else
		{
			cout << '0';
		}
	}
	cout << endl;

	//角度制
	cout << "角度制为: " << sqrt(ans.a*ans.a + ans.b*ans.b);
	cout << '<' << atan2(ans.b, ans.a) * 180 / acos(-1) << endl;
}

void calculator::clear()
{
	element_num = 0;
	p_o_e_num = 0;
	stack_num = 0;
	ans.type = 0;
	ans.a = 0;
	ans.b = 0;
	memset(all_element,0,sizeof(all_element));
	memset(middel_order_expression, 0, sizeof(middel_order_expression));
	memset(preorder_expression, 0, sizeof(preorder_expression));
	memset(stack, 0, sizeof(stack));
}

void calculator::get_m_o_e()
{
	//现在的all_element 就是中序表达式
	for (int i = 0; i < element_num; i++)
	{
		middel_order_expression[i] = i;
	}
}

void calculator::get_p_o_e()
{
	/*
	Code highlighting produced by Actipro CodeHighlighter (freeware)
	http://www.CodeHighlighter.com/-->
	中序表达式转前序表达式步骤
	1、反转输入字符串,如“2*3/(2-1)+3*(4-1)” 反转后为“ )1-4(*3+)1-2(/3*2”,
	2、从字符串中取出下一个字符  
		2.1.如果是操作数,则直接输出  
		2.2.如果是“)”,压入栈中  
		2.3.如果是运算符但不是“(”,“)”,则不断循环进行以下处理    
			2.3.1.如果栈为空,则此运算符进栈,结束此步骤    
			2.3.2.如果栈顶是“)”,则此运算符进栈,结束此步骤    
			2.3.2.如果此运算符与栈顶优先级相同或者更高,此运算符进栈,结束此步骤    
			2.3.4.否则,运算符连续出栈,直到满足上述三个条件之一,然后此运算符进栈  
		2.4、如果是“(”,则运算符连续出栈,直到遇见“)”为止,将“)”出栈且丢弃之
	3、如果还有更多的字符串,则转到第2步
	4、不在有未处理的字符串了,输出栈中剩余元素
	5、再次反转字符串得到最终结果
	*/
	int t = 0;	//放先序表达式的位置
	for (int i = element_num - 1; i >= 0; i--)
	{
		if (all_element[i].type == false)
		{
			preorder_expression[t] = i;
			t++;
		}			
		else if (all_element[i].op == 1)	// )
		{
			stack[++stack_num] = i;
		}
		else if (all_element[i].op != 0 && all_element[i].op != 1)
		{
			while(1)
			{ 
				if (stack_num == 0)
				{
					stack[++stack_num] = i;
					break;
				}
				else if (all_element[stack[stack_num]].op == 1)
				{
					stack[++stack_num] = i;
					break;
				}
				else if (Greater_than_equal_to_or_equal_to(all_element[i], all_element[stack[stack_num]]))
				{
					stack[++stack_num] = i;
					break;
				}
				else
				{
					preorder_expression[t] = stack[stack_num];
					--stack_num;
					t++;
				}
			}
		}
		else
		{
			while (stack_num && all_element[stack[stack_num]].op != 1)
			{
				preorder_expression[t] = stack[stack_num];
				--stack_num;
				t++;
			}
			--stack_num;
		}
	}
	while (stack_num > 0)
	{
		preorder_expression[t] = stack[stack_num];
		--stack_num;
		t++;
	}
	int temp;
	for (int i = 0; i <= (p_o_e_num - 1) / 2; i++)
	{
		temp = preorder_expression[i];
		preorder_expression[i] = preorder_expression[p_o_e_num - 1 - i];
		preorder_expression[p_o_e_num - 1 - i] = temp;
	}
}

string calculator::element_to_string(element &t)
{
	if (t.type)
	{
		string op_type;
		switch (t.op)
		{
		case 0:
			op_type = '(';
			break;
		case 1:
			op_type = ')';
			break;
		case 2:
			op_type = '+';
			break;
		case 3:
			op_type = '-';
			break;
		case 4:
			op_type = '*';
			break;
		case 5:
			op_type = '/';
			break;
		default:
			cout << "what?" << endl;
			return to_string(t.op);
			break;
		}
		return op_type;
	}
	//未实现精度问题
	string tans = "";
	if (t.a != 0)
	{
		tans += to_string(t.a);
		if (t.b != 0)
		{
			tans += "+j";
			tans += to_string(t.b);
		}
	}
	else
	{
		if (t.b != 0)
		{
			tans += "j";
			tans += to_string(t.b);
		}
	}
	return tans;
}

bool calculator::Greater_than_equal_to_or_equal_to(element a, element b)
{
	return priority[a.op] >= priority[b.op];
}
//main.cpp
#include<iostream>
#include<cstdlib>
#include<string>
#include"calculator.h"
using namespace std;
int main()
{
	calculator cs;
	string t;
	cout << "复数计算器(第二版)" << endl
		<< "1.输入需要计算的式子,回车将显示答案,ctrl + z 退出程序" << endl
		<< "2.复数请表示为a+jb 的形式(b 若小于0,则写成a - j abs(b) )" << endl
		<< "3.目前还不支持直接输入角度和函数,以后版本会添加这个功能(也可能会忘了有这回事)" << endl;
	while (cin >> t)
	{
		cs.get(t);
		cs.calculate();
		cs.print_ans();
		cs.clear();
	}
	system("pause");
	return 0;
}

居然能看到这里!
那就直接把整个项目给你吧!
链接:https://pan.baidu.com/s/1zw1qQSbxaTvrbjPAfq-LXQ
提取码:guhp

发布了45 篇原创文章 · 获赞 14 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_34438779/article/details/89740902