(只有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