(只有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++ 写一个复数计算器相关推荐

  1. linux shell 计算器 除0,用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1....

    用shell写一个简易计算器,可以实现加.减.乘.除运算,假如脚本名字为1.sh,执行示例:./1.sh 1 + 2#!/bin/bash if [ $# -ne 3 ] then echo &quo ...

  2. linux脚本计算器加减乘除,用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1....

    用shell写一个简易计算器,可以实现加.减.乘.除运算,假如脚本名字为1.sh,执行示例:./1.sh 1 + 2#!/bin/bash if [ $# -ne 3 ] then echo &quo ...

  3. 用Java写一个年薪计算器,助你简单完成大量税前税后总薪计算量

    每个有规模一点的公司都会有会计部门这是毋庸置疑的,但是会计的工作真的如大部分人想的那么简单,只是在每个月的最后几天才忙得不可开交吗 ? 答案当然不是,不然这个岗位早就人满为患了. 目前就我了解到的会计 ...

  4. 用微信开发者小程序写一个加法计算器小程序

    文章目录 前言 一.calculator.wxml代码 二.calculator.js代码 结果 前言 提示:用软件微信开发者小程序写一个加法计算器小程序 一.calculator.wxml代码 &l ...

  5. python实现一个整数加法计算器_如何使用python编程写一个加法计算器-Python教程...

    一.关上idle.点击file,而后点击new file.这是创立一个新的文件. 新建一个文件之后,咱们输出第一行代码,应用print函数,正在屏幕上打印一句话,此中字符串要应用双引号,输出法要应用英 ...

  6. 用shell写一个简易计算器,可以实现加、减、乘、除运算,假如脚本名字为1.sh,执行示例:./1....

    用shell写一个简易计算器,可以实现加.减.乘.除运算,假如脚本名字为1.sh,执行示例:./1.sh 1 + 2 #!/bin/bash if [ $# -ne 3 ] thenecho &quo ...

  7. java简易计算器考察什么_练习:用java写一个简易计算器

    初学java中的选择,判断,循环和方法的概念,写一个简易的两位数计算器 思路推荐: 写4个方法:加减乘除 利用循环+switch进行用户交互 传递需要操作的两个数 输出结果 package com.j ...

  8. 用C语言写一个日期计算器

    首先,我们应知道日期计算器包括哪些功能 1.明天的日期 2 .n天后的日期 3.两个日期之间的天数 我们先从第一个功能开始,首先创建一个日期的结构体,包括:年.月.日. struct date {in ...

  9. 复数类 java_用java写一个复数类Complex

    由于java库中没有提供复数的操作,应同学的需求,写了一个复数的类.有两个构造方法不带参数和带参数的,不带参数时默认实部虚部都为0.还有这些基本的方法,看名字就知道了. public double g ...

  10. javascript从0到0.9手写一个windows计算器

    说实话,最初想用javascript模拟着windows的计算器写一个的时候,感觉也就是10分钟搞定,但写着写着发现,其实并不是那么容易的事,window的这个计算器逻辑挺多的. 而且还想给别人把这个 ...

最新文章

  1. String 类型的相关转换
  2. Concept3D推出交互式3D地图平台
  3. 使用 SYSENTER 和 SYSEXIT 指令执行对系统过程的快速调用
  4. 如何禁用特定css_通过CSS追踪用户
  5. Python Day47索引
  6. 【前端】【cornerstionjs】Cornerstone加载base64表示的jpg图像
  7. mysql报错:You must at least set –server-id to enable either a master or a slave
  8. java反射 泛型类型_【译】9. Java反射——泛型
  9. 58-最小乘积(基本型)
  10. 微信小程序富文本编辑器 editor 组件源码
  11. HTML 禁用Select下拉框的上下左右键盘按键默认事件
  12. python pysynth随机生成中国风音乐旋律
  13. 使用instrument-->Allocations进行内存分析
  14. 通过IMAP方式迁移U-Mail邮件到Exchange 2013之Exchange 2007 升级到Exchange 2013!
  15. Windows Sockets错误码方案
  16. iPadmini能运行c语言吗,一个移动固态硬盘,可以给iPad Pro2020和iPad Mini用是什么体验?...
  17. 多智能体强化学习- COMA
  18. Mac下command+R和shift+command+R的区别,在线恢复模式的选择
  19. Single shot object detection SSD using MobileNet and OpenCV
  20. python常用可视化技巧

热门文章

  1. C++根据旋转轴和角度求旋转矩阵
  2. 4.7开发者日:创业工场麦刚认为创业者活下去最重要
  3. 在web上制作动画(css3)
  4. Go解决报错 error obtaining VCS status: exit status 128 Use -buildvcs=false to disable VCS stamping
  5. PHP笔记——开发工具VS Code
  6. 计算机内打不开小米路由器,小米路由器登录界面打不开怎么办?
  7. win10用不了计算机一级,教你一招解决Win10计算器打不开的问题
  8. KMP 深入理解next数组
  9. python判断字符串包含中文、数字、英文
  10. 给定一个仅包含大小写字母和空格 ‘ ‘ 的字符串 s,