c++ 写一个复数计算器
(只有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); //接受一个计算表达式并保存为中序表达式,如果表达式有语法错误,则返回falsevoid print(int i); //打印计算表达式(0 为中序,其它为前序)void calculate(); //开始计算void print_ans(); //得到答案void clear(); //清除上次运算string element_to_string(element&); //将一个element 变成stringbool 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 stackcout << 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
c++ 写一个复数计算器相关推荐
- linux shell 计算器 除0,用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1....
用shell写一个简易计算器,可以实现加.减.乘.除运算,假如脚本名字为1.sh,执行示例:./1.sh 1 + 2#!/bin/bash if [ $# -ne 3 ] then echo &quo ...
- linux脚本计算器加减乘除,用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1....
用shell写一个简易计算器,可以实现加.减.乘.除运算,假如脚本名字为1.sh,执行示例:./1.sh 1 + 2#!/bin/bash if [ $# -ne 3 ] then echo &quo ...
- 用Java写一个年薪计算器,助你简单完成大量税前税后总薪计算量
每个有规模一点的公司都会有会计部门这是毋庸置疑的,但是会计的工作真的如大部分人想的那么简单,只是在每个月的最后几天才忙得不可开交吗 ? 答案当然不是,不然这个岗位早就人满为患了. 目前就我了解到的会计 ...
- 用微信开发者小程序写一个加法计算器小程序
文章目录 前言 一.calculator.wxml代码 二.calculator.js代码 结果 前言 提示:用软件微信开发者小程序写一个加法计算器小程序 一.calculator.wxml代码 &l ...
- python实现一个整数加法计算器_如何使用python编程写一个加法计算器-Python教程...
一.关上idle.点击file,而后点击new file.这是创立一个新的文件. 新建一个文件之后,咱们输出第一行代码,应用print函数,正在屏幕上打印一句话,此中字符串要应用双引号,输出法要应用英 ...
- 用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1....
用shell写一个简易计算器,可以实现加.减.乘.除运算,假如脚本名字为1.sh,执行示例:./1.sh 1 + 2 #!/bin/bash if [ $# -ne 3 ] thenecho &quo ...
- java简易计算器考察什么_练习:用java写一个简易计算器
初学java中的选择,判断,循环和方法的概念,写一个简易的两位数计算器 思路推荐: 写4个方法:加减乘除 利用循环+switch进行用户交互 传递需要操作的两个数 输出结果 package com.j ...
- 用C语言写一个日期计算器
首先,我们应知道日期计算器包括哪些功能 1.明天的日期 2 .n天后的日期 3.两个日期之间的天数 我们先从第一个功能开始,首先创建一个日期的结构体,包括:年.月.日. struct date {in ...
- 复数类 java_用java写一个复数类Complex
由于java库中没有提供复数的操作,应同学的需求,写了一个复数的类.有两个构造方法不带参数和带参数的,不带参数时默认实部虚部都为0.还有这些基本的方法,看名字就知道了. public double g ...
- javascript从0到0.9手写一个windows计算器
说实话,最初想用javascript模拟着windows的计算器写一个的时候,感觉也就是10分钟搞定,但写着写着发现,其实并不是那么容易的事,window的这个计算器逻辑挺多的. 而且还想给别人把这个 ...
最新文章
- String 类型的相关转换
- Concept3D推出交互式3D地图平台
- 使用 SYSENTER 和 SYSEXIT 指令执行对系统过程的快速调用
- 如何禁用特定css_通过CSS追踪用户
- Python Day47索引
- 【前端】【cornerstionjs】Cornerstone加载base64表示的jpg图像
- mysql报错:You must at least set –server-id to enable either a master or a slave
- java反射 泛型类型_【译】9. Java反射——泛型
- 58-最小乘积(基本型)
- 微信小程序富文本编辑器 editor 组件源码
- HTML 禁用Select下拉框的上下左右键盘按键默认事件
- python pysynth随机生成中国风音乐旋律
- 使用instrument-->Allocations进行内存分析
- 通过IMAP方式迁移U-Mail邮件到Exchange 2013之Exchange 2007 升级到Exchange 2013!
- Windows Sockets错误码方案
- iPadmini能运行c语言吗,一个移动固态硬盘,可以给iPad Pro2020和iPad Mini用是什么体验?...
- 多智能体强化学习- COMA
- Mac下command+R和shift+command+R的区别,在线恢复模式的选择
- Single shot object detection SSD using MobileNet and OpenCV
- python常用可视化技巧
热门文章
- C++根据旋转轴和角度求旋转矩阵
- 4.7开发者日:创业工场麦刚认为创业者活下去最重要
- 在web上制作动画(css3)
- Go解决报错 error obtaining VCS status: exit status 128 Use -buildvcs=false to disable VCS stamping
- PHP笔记——开发工具VS Code
- 计算机内打不开小米路由器,小米路由器登录界面打不开怎么办?
- win10用不了计算机一级,教你一招解决Win10计算器打不开的问题
- KMP 深入理解next数组
- python判断字符串包含中文、数字、英文
- 给定一个仅包含大小写字母和空格 ‘ ‘ 的字符串 s,