-
2021-01-07 22:58:47
基于标准C++的计算器实现。
一、需求实现
1、实现功能:
支持运算符:+, - , *, /, %(百分号), ^(幂次方), | |(绝对值),!(阶乘)。其他符号:( ) [ ] { }
支持数据类型:正负数、小数。
2、实现方法
符号优先级处理方法:符号等级制
运算表达式处理方法:后缀表达式法
后缀表达式转换及计算辅助方法:符号栈、数字栈
二、设计实现
总体设计:
计算器类
//计算器类 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; //最终计算结果 };
1、运算优先级功能实现
(1)运算符等级
声明为枚举常量(在整个类中恒定),便于数据管理、数据与程序分离。
//算术符号优先权等级 enum PRIO_LV { PRIO_LV0 = 0, PRIO_LV1 = 1, PRIO_LV2 = 2, PRIO_LV3 = 3, PRIO_LV4 = 4, };
(2)运算符优先级获取
用于运算优先级比较的依据。
//获取算术符号优先级 int Calculator::getPrior(char c) { if (c == '+' || c == '-') { return PRIO_LV1; } else if (c == '*' || c == '/') { return PRIO_LV2; } else if (c == '%' || c == '^') { return PRIO_LV3; } else if (c == '!') { return PRIO_LV4; } else { return PRIO_LV0; } //else { cout << c << 非法符号! << endl; } }
2、绝对值符号奇偶性实现
//绝对值符号个数的奇偶性 enum ABS_ODEVITY { ABS_ODD = 1, ABS_EVEN = 2, };
3、正负数运算实现
//表达式自定义标准格式化 void Calculator::getFormat() { stdInfix = infix; //实现正负数 //for (int i = 0; i < stdInfix.length(); i++) { //string下标调用运算符时可能会导致类型溢出 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'); } } } }
4、后缀表达式转换
要直接对表达式求值,首先要能够正确解释表达式,或者翻译成能正确求值的一个机器指令序列,以便计算机的处理执行。因此有前缀表达式和后缀表达式方法,此处采用较为广泛的后缀表达式方法。
//后缀表达式转换 void Calculator::getPostfix() { int absNumeber = ABS_ODD; //绝对值符号个数的奇偶性 string tmp; //for (int i = 0; i < stdInfix.length(); i++) { for (size_t i = 0; i < stdInfix.size(); i++) { //string.size()返回size_type类型,避免下标运算时的类型溢出 tmp = ""; switch (stdInfix[i]) { case '+': case '-': case '*': case '/': case '%': case '^': case '!': if (symStack.empty() || symStack.top() == '(' || symStack.top() == '[' || symStack.top() == '{' || (symStack.top() == '|' && absNumeber == ABS_ODD)) { symStack.push(stdInfix[i]); } else { while (!symStack.empty() && (getPrior(symStack.top()) >= getPrior(stdInfix[i]))) { tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); tmp = ""; } symStack.push(stdInfix[i]); } break; case '|': if (absNumeber == ABS_ODD) { symStack.push(stdInfix[i]); absNumeber = ABS_EVEN; } else{ while (!symStack.empty() && symStack.top() != '|') { tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); tmp = ""; } if (!symStack.empty() && symStack.top() == '|') { tmp += symStack.top(); postfix.push_back(tmp); //左绝对值符号'|'加入后缀表达式,用于绝对值的检测计算 symStack.pop(); absNumeber = ABS_ODD; } } break; case '(': case '[': case '{': symStack.push(stdInfix[i]); break; case ')': while (!symStack.empty() && symStack.top() != '(') { tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); tmp = ""; } if (!symStack.empty() && symStack.top() == '(') { symStack.pop(); //将左括号出栈丢弃 } break; case ']': while (!symStack.empty() && symStack.top() != '[') { tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); tmp = ""; } if (!symStack.empty() && symStack.top() == '[') { symStack.pop(); //将左括号出栈丢弃 } break; case '}': while (!symStack.empty() && symStack.top() != '{') { tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); tmp = ""; } if (!symStack.empty() && symStack.top() == '{') { symStack.pop(); //将左括号出栈丢弃 } break; default: if ((stdInfix[i] >= '0' && stdInfix[i] <= '9')) { tmp += stdInfix[i]; while (i + 1 < stdInfix.length() && (stdInfix[i + 1] >= '0' && stdInfix[i + 1] <= '9' || stdInfix[i + 1] == '.')) { //小数处理 tmp += stdInfix[i + 1]; //是连续的数字,则追加 i++; } if (tmp[tmp.length() - 1] == '.') { tmp += '0'; //将x.做x.0处理 } postfix.push_back(tmp); } break; }//end switch }//end for //if(!symStack.empty()) { while (!symStack.empty()) { //将栈中剩余符号加入后缀表达式 tmp = ""; tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); } }
5、计算后缀表达式
计算后缀表达式,得到最终计算结果,将结果传递到计算器类的
result
属性。//计算 void Calculator::calResult() { string tmp; double number = 0; double op1 = 0, op2 = 0; for (int i = 0; i < postfix.size(); i++) { tmp = postfix[i]; if (tmp[0] >= '0' && tmp[0] <= '9') { number = atof(tmp.c_str()); figStack.push(number); } else if (postfix[i] == "+") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(op1 + op2); } else if (postfix[i] == "-") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(op1 - op2); } else if (postfix[i] == "*") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(op1* op2); } else if (postfix[i] == "/") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } if (op2 != 0) { ///除数不为0,未做处理,默认 } figStack.push(op1 / op2); } else if (postfix[i] == "%") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(fmod(op1, op2)); //可进行小数求余 } else if (postfix[i] == "^") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(pow(op1, op2)); } else if (postfix[i] == "|") { if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(abs(op1)); } else if (postfix[i] == "!") { if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } if (op1 > 0) { //阶乘数应大于;为小数时(转化为整数求阶) double factorial = 1; for (int i = 1; i <= op1; ++i) { factorial *= i; } op1 = factorial; } figStack.push(op1); } }//end for if (!figStack.empty()) { result = figStack.top(); } }
6、对象的外部调用方法
//计算方法 void Calculator::calculate() { getFormat(); //表达式自定义标准格式化 getPostfix(); //后缀表达式转换 calResult(); //获取算术结果 }
//获取结果 double Calculator::getResult() { return result; }
三、完整代码
Calculator.h: 头文件
//Calculator.h: 头文件 #include <stack> #include <vector> #include <string> using namespace std; //计算器类 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; //最终计算结果 };
Calculator.cpp: 实现文件
//Calculator.cpp: 实现文件 #include <stack> #include <vector> #include <string> #include <cmath> using namespace std; //绝对值符号个数的奇偶性 enum ABS_ODEVITY { ABS_ODD = 1, ABS_EVEN = 2, }; //算术符号优先权等级 enum PRIO_LV { PRIO_LV0 = 0, PRIO_LV1 = 1, PRIO_LV2 = 2, PRIO_LV3 = 3, PRIO_LV4 = 4, }; Calculator::Calculator() { //构造函数,初始化成员变量 operatorSym = "支持运算符:+, - , *, /, %(百分号), ^(幂次方), | |(绝对值),!(阶乘)。其他符号:( ) [ ] { }"; result = 0.0; } //表达式自定义标准格式化 void Calculator::getFormat() { stdInfix = infix; //实现正负数 //for (int i = 0; i < stdInfix.length(); i++) { //string下标调用运算符时可能会导致类型溢出 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'); } } } } //获取算术符号优先级 int Calculator::getPrior(char c) { if (c == '+' || c == '-') { return PRIO_LV1; } else if (c == '*' || c == '/') { return PRIO_LV2; } else if (c == '%' || c == '^') { return PRIO_LV3; } else if (c == '!') { return PRIO_LV4; } else { return PRIO_LV0; } //else { cout << c << 非法符号! << endl; } } //后缀表达式转换 void Calculator::getPostfix() { int absNumeber = ABS_ODD; //绝对值符号个数的奇偶性 string tmp; //for (int i = 0; i < stdInfix.length(); i++) { for (size_t i = 0; i < stdInfix.size(); i++) { //string.size()返回size_type类型,避免下标运算时的类型溢出 tmp = ""; switch (stdInfix[i]) { case '+': case '-': case '*': case '/': case '%': case '^': case '!': if (symStack.empty() || symStack.top() == '(' || symStack.top() == '[' || symStack.top() == '{' || (symStack.top() == '|' && absNumeber == ABS_ODD)) { symStack.push(stdInfix[i]); } else { while (!symStack.empty() && (getPrior(symStack.top()) >= getPrior(stdInfix[i]))) { tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); tmp = ""; } symStack.push(stdInfix[i]); } break; case '|': if (absNumeber == ABS_ODD) { symStack.push(stdInfix[i]); absNumeber = ABS_EVEN; } else{ while (!symStack.empty() && symStack.top() != '|') { tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); tmp = ""; } if (!symStack.empty() && symStack.top() == '|') { tmp += symStack.top(); postfix.push_back(tmp); //左绝对值符号'|'加入后缀表达式,用于绝对值的检测计算 symStack.pop(); absNumeber = ABS_ODD; } } break; case '(': case '[': case '{': symStack.push(stdInfix[i]); break; case ')': while (!symStack.empty() && symStack.top() != '(') { tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); tmp = ""; } if (!symStack.empty() && symStack.top() == '(') { symStack.pop(); //将左括号出栈丢弃 } break; case ']': while (!symStack.empty() && symStack.top() != '[') { tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); tmp = ""; } if (!symStack.empty() && symStack.top() == '[') { symStack.pop(); //将左括号出栈丢弃 } break; case '}': while (!symStack.empty() && symStack.top() != '{') { tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); tmp = ""; } if (!symStack.empty() && symStack.top() == '{') { symStack.pop(); //将左括号出栈丢弃 } break; default: if ((stdInfix[i] >= '0' && stdInfix[i] <= '9')) { tmp += stdInfix[i]; while (i + 1 < stdInfix.length() && (stdInfix[i + 1] >= '0' && stdInfix[i + 1] <= '9' || stdInfix[i + 1] == '.')) { //小数处理 tmp += stdInfix[i + 1]; //是连续的数字,则追加 i++; } if (tmp[tmp.length() - 1] == '.') { tmp += '0'; //将x.做x.0处理 } postfix.push_back(tmp); } break; }//end switch }//end for //if(!symStack.empty()) { while (!symStack.empty()) { //将栈中剩余符号加入后缀表达式 tmp = ""; tmp += symStack.top(); postfix.push_back(tmp); symStack.pop(); } } //计算后缀表达式 void Calculator::calResult() { string tmp; double number = 0; double op1 = 0, op2 = 0; for (int i = 0; i < postfix.size(); i++) { tmp = postfix[i]; if (tmp[0] >= '0' && tmp[0] <= '9') { number = atof(tmp.c_str()); figStack.push(number); } else if (postfix[i] == "+") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(op1 + op2); } else if (postfix[i] == "-") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(op1 - op2); } else if (postfix[i] == "*") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(op1* op2); } else if (postfix[i] == "/") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } if (op2 != 0) { ///除数不为0,未做处理,默认 } figStack.push(op1 / op2); } else if (postfix[i] == "%") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(fmod(op1, op2)); //可进行小数求余 } else if (postfix[i] == "^") { if (!figStack.empty()) { op2 = figStack.top(); figStack.pop(); } if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(pow(op1, op2)); } else if (postfix[i] == "|") { if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } figStack.push(abs(op1)); } else if (postfix[i] == "!") { if (!figStack.empty()) { op1 = figStack.top(); figStack.pop(); } if (op1 > 0) { //阶乘数应大于;为小数时(转化为整数求阶) double factorial = 1; for (int i = 1; i <= op1; ++i) { factorial *= i; } op1 = factorial; } figStack.push(op1); } }//end for if (!figStack.empty()) { result = figStack.top(); } } //计算方法 void Calculator::calculate() { getFormat(); //表达式自定义标准格式化 getPostfix(); //后缀表达式转换 calResult(); //获取算术结果 } //获取结果 double Calculator::getResult() { return result; }
Main.cpp:主程序
#include <iostream> using namespace std; //const int MAX_EXP_LEN = 1000; //最大表达式长度 防止内存溢出 //main函数 int main() { Calculator cal; cout << cal.operatorSym << endl; cout << "----------" << endl; while (true) { getline(cin, cal.infix); /* if (cal.infix.length() > MAX_EXP_LEN) { cout << "超出最大长度!" << endl; system("pause"); } else { cal.calculate(); } */ cal.calculate(); cout << cal.getResult() << endl; } return 0; }
资源获取
-
计算器整体项目打包 及 项目设计说明书(含总结) csdn下载地址:Calculator.rar
-
百度网盘链接: https://pan.baidu.com/s/19uDZHTOITeStOaUZdgIy8Q 提取码: xyda
-
另基于此程序的mfc计算器(用户界面)实现,请转文章 mfc计算器实现
更多相关内容 -
-
C++图形界面计算器
2012-12-22 21:42:22C++语言 编写的带图形界面的计算器,能实现加减乘除和清零功能。代码清晰,适合初学者学习。 -
两种用C++实现计算器界面设计的工程
2019-10-05 09:30:48两种用C++实现计算器界面设计的工程,用qt-creator编辑,一种是直接声明QWidget变量的方式,一种是继承QWidget的方式。 -
C++计算器可视化.rar
2021-03-20 12:55:13基于MFC界面的计算器,可以实现简单的加减乘除,代码简单易懂,下载可以直接运行 -
C++计算器界面程序及详细注释
2010-05-15 10:48:08使用C++程序编辑的计算器界面,程序有详细的注释。 -
计算器(C++控制台界面)
2018-10-22 00:19:46C++数据结构实习。使用双栈实现计算器计算功能,除基本运算外,支持幂运算,开方运算和三角函数运算。原创,如有问题请联系我 -
C++语言 编写的带图形界面的计算器
2021-10-06 21:21:43C++语言 编写的带图形界面的计算器,能实现加减乘除和清零功能。代码清晰,适合初学者学习。 -
带界面的计算器
2019-06-13 20:53:28数据结构课程设计计算器,带界面,具有报错功能,可以进行加减乘除括号混合运算,与或非逻辑运算。开发环境vs2017。上传为整个计算器设计工程,可以用vs2017打开。 -
C++计算器课程设计报告
2013-05-24 21:05:52C++计算器课程设计报告,含有部分代码,真实,调试成功的! -
用c++写出带交互界面的简单计算器
2020-05-21 15:53:59利用devc++和QT写交互界面的计算器 一.先下载一个QT 下载地址 http://download.qt.io/archive/qt/ 我下载的是 5.12.8 版本的 第四个是windos的 第五个是mac的 第六个是linux的 按需下载就行了 这里有一篇下载安装...利用devc++和QT写交互界面的计算器
一.先下载一个QT
下载地址
http://download.qt.io/archive/qt/
我下载的是 5.12.8 版本的
第四个是windos的
第五个是mac的
第六个是linux的
按需下载就行了这里有一篇下载安装教程可以看看
https://blog.csdn.net/cfan927/article/details/98115783?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-5&depth_1-utm_source=distribute.pc_releva
(转@Cfan927)
比较详细二. 学习Qt
b站有个教学视频,可以先看看,他讲的比较详细
https://www.bilibili.com/video/BV1g4411H78N
我个人感觉看到 P10 就行了,因为我知道看我这篇文章的多半都是合工大的孩子被数据结构作业逼疯才来的,先学这么多
弄懂怎么实现按钮的操作,弄懂什么是信号,什么是槽就可以了三.实现计算器代码
有两点可能要注意一下(没有这个大作业的可以不看后面这段)
我们的大作业里面有&& || !三种逻辑运算符
!问题不大
主要是&&和||
这个到时候在计算器输入的时候要输入两个&&
但是我们只入栈一个& 这样方便后面运算
那怎么实现呢?
我们用a来代表你的输入的算式
a[i]遍历这个式子,当 i 指向第一个&时,i++
再入栈运算符,这样就只入栈了一个运算符|| 和上面的处理方式一样
但是要注意的时 | 的ascii码是 124 ,判断运算符和数字时要注意其次要注意&& || !之间的优先级,还有运算联系等
else if(a[i]=='&') { if(a[i+1]=='&') i++; }
类似于上面这样的代码来让它判断
下面放上源码
#include<iostream> #include<string> #include<cmath> #include<stack> using namespace std; int symbol(char c) //赋予优先级 { switch (c) { case '#': return 0; case '+': return 2; case '-': return 2; case '*': return 3; case '/': return 3; case '(': return 6; case ')': return 1; case '&': return 4; case '|': return 4; case '!': return 5; default: break; } return 0; } double jisuan( char c='#',double b=1,double a=1) { switch (c) { case '+': return b + a; case '-': return b - a; case '*': return b * a; case '/': return b / a; case '&': if(a!=0&&b!=0) return 1; else return 0; case '|': if(a==0&&b==0) return 0; else return 1; default: break; } return 0; } double js(double a) { if(a==0) return 1; else return 0; } int main() { stack<double>s1; stack<char>s2; string a; cout << "请输入" << endl; cin >> a; a = a + '#'; s2.push('#'); for (int i = 0;i<a.size(); i++) { if (a[i] <= 47||a[i]==124) //用阿斯克码判断扫描到的是数字还是运算符 { if (a[i] == '#'&&s2.top() == '#') break; //两个#碰到一起运算结束 if (s2.top() == '(') //括号特殊讨论 { if (a[i] == ')') { s2.pop(); continue; } s2.push(a[i]); continue; } else if(a[i]=='&') { if(a[i+1]=='&') { i++; } } else if(a[i]=='|') { if(a[i+1]=='|') { i++; } } if (symbol(s2.top()) >= symbol(a[i])) //判断运算符优先级 { if(s2.top()=='!') { double vel=js(s1.top()); s1.pop(); s2.pop(); s1.push(vel); i--; } else { char temp1 = s2.top(); s2.pop(); double temp2 = s1.top(); s1.pop(); double temp3 = s1.top(); s1.pop(); s1.push(jisuan(temp1, temp3, temp2)); i--;//要把a[i]再走一遍 不然同级运算a[i]不能push continue; } } else { s2.push(a[i]); continue; } } else //对数字的运算 { double sum = static_cast<int>(a[i]) - 48; for (; a[i + 1] > 47&& a[ i + 1 ] != 124 ; i++) //实现多位数的运算 sum = sum * 10 + static_cast<int>(a[i + 1]) - 48; if(static_cast<int>(a[i+1])==46) //计算小数 { int j=1; i=i+2; for(;a[i]>47&&a[ i ] != 124;i++) { sum=sum+pow(10,-j)*(static_cast<int>(a[i]) - 48); j++; } i--; } s1.push(sum); } } double result = s1.top(); cout << "计算结果:" << endl; cout << result ; }
四.实现QT代码
1. 创立一个widge类型的项目
注意这里把那个Generate form 勾选上,方便后面设计界面
创建好以后就是这样 注意左上角那个板块 要有这几个文件夹如果没有那就把QT关了 然后点开刚刚创立的路径的文件夹 把那个文件打开
再打开QT
出现如下页面
点击右下方的按钮就好了
如果这还没好,那就说明可能你的QT没有下载完整 有的插件没下
重新下吧2.开始写代码
2.1 首先我们要想一个问题 如何把计算器按钮上面输入的式子和自己的计算器源码连接起来
我们可以创立一个 QString 类型的字符串 s (QT的头文件一般都是QString,QStack什么的)
每输入一个字符,就把他加入到 s 中
这样最后再把 s 传入你的源码中,进行后面的计算
那他的结果我们也可以用一个QString 类型来记录,我们记为 res
我们再来想一个问题
那个教学视频中也说到过
QT中 widget是一个类,他有头文件,我们想要 s 再每一次按下按钮后都记录
所以我们就可以把 s 定为这个类的私有 ,res 也一样在widget.h文件中就有这样一段代码
private: Ui::Widget *ui; QString s; QString res;
在widget.cpp文件中的构造函数对它们初始化
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); s=""; //初始化 res=""; //初始化 setWindowTitle("肝到昏天黑地的计算器"); //这是个改变界面名称的函数 }
2.2 我们现在可以来编辑界面了
点开
这个文件
我们就进入了设计界面
这是我已经设计好的注意背景图(我是男生,这不是我的自拍)
背景图有个链接 讲的也很清楚 https://blog.csdn.net/nb_zsy/article/details/104136793
上面两个白框框 我选择的是 TextEdit,在左边的工具栏能找到
按钮选择的是PUsh button
鼠标选中以后 拖过来就好了
(b站视频按钮是自己输入坐标的,这里的ui直接是自己选位置,方便了很多,这就是在创立新项目时让你们勾选那个Generate form 的原因)2.3 开始实现按钮
鼠标放到你的按钮上 点击右键
有个 转到槽 的选项
之后选择clicked 这就是点击的信号
点一下之后就跳到了代码页面
之后就在这个函数里面实现你的按钮就可以了这里我们举一个例子
void Widget::on_pushButton_clicked() { s+="1"; ui->textEdit->setText(s); }
s前面解释过了
ui就是你这个设计页面,textedit就是第一个白框框,setText(s)就是在这个白框框里面输入s
那么这个连起来的意思就是
在你的设计页面中的 textEdi t这个对象中输入 s
具体怎么看对象名,在设计页面,点击你的按钮或者文本框,右上角有显示他的对象名再说三个特殊的
①后退键 :void Widget::on_pushButton_20_clicked() { s=s.left(s.length()-1); ui->textEdit->setText(s); }
②清除键 :
void Widget::on_pushButton_19_clicked() { s=""; res=""; ui->textEdit->setText(s); ui->textEdit_2->setText(res); }
res是在第二个文本框中的字符串
③ 等号键 :
下面 “= ”的按钮是个特例
我们有两种想法
第一就是直接把你的计算器源码整个放在这个槽函数里面
也可以在外面单独写一个函数,最后return一个值,把这个值传入 = 的槽函数但是值得注意的有两点
第一
如果你的计算器源码其中一个栈是char类型的,而你的s又是string类型,这样是过不了QT的编译器的
因此要把string转成char型char *a=s.toLocal8Bit().data();
第二
最后传到设计界面的文本框中的数据应该是Qstring类型
如果你最后的计算结果是 int 或者 double 类型的
要把它转成Qstring的double num = s1.top(); res = QString::number(num); ui->textEdit_2->setText(res);
num是我的最后计算结果
textEdit_2是我的第二个文本框的对象名到现在我们的计算器基本上就完成了
还有两点也要注意一下
第一就是我们在写槽函数的时候 输入文本框的字符一定时英文键盘下的字符,不然程序不会进行的
第二就是QT有的错误不会报错,只会警告,尽量把所有的警告也改了,有的警告不影响结果,有的警告会让最后的程序异常关闭,虽然能编译通过
上面两条都是我血的教训,好几个小时看不出到底是那错了,程序一直异常关闭我能说的也就这么多了,如果还有什么问题可以发在下面
****有一种营销号的感觉****我的这个计算器的文件在这里
https://gitee.com/jinhesuannaijiaofu/jisuanqi
进去下载那个计算器的文件就好了
下载完成以后用QT打开就OK了
要是看主要部分的代码的话,点开untit 文件里面的widget.cpp文件就行
不用下载就能看如果能点个赞就更好了!!!
-
简单的计算器界面
2018-03-07 19:24:15有关于计算器界面的代码,方便取用有关于计算器界面的代码,方便取用有关于计算器界面的代码,方便取用 -
利用Visual Studio(C++)实现简易计算器
2020-12-01 20:43:43计算器外观的制作 打开资源文件中的.rc文件: 选择视图中的工具箱选项: 主要用到下面三个工具: Botton:按键功能 Edit Control(编辑框):编辑控制功能 Static Text:存放静态文本 插入任意一个对话框,单击...创建MFC应用
设置项目名称及项目存放位置:
选择基于对话框,其余均为默认选项:
按自己的制作目标勾选相应的样式:
其余均为默认,最后完成创建。计算器外观的制作
打开资源文件中的.rc文件:
选择视图中的工具箱选项:
主要用到下面三个工具:
Button:按键功能
Edit Control(编辑框):编辑控制功能,显示输入或输出的数字
Static Text:存放静态文本
插入任意一个对话框,单击鼠标右键,选中属性,即可实现对编辑框的设计与命名:
可通过Ctrl+c、Ctrl+v可实现对话框的复制粘贴。(不推荐使用,因为我就是用了复制粘贴最后把自己搞乱的)最好插入一个对话框就对其处理,不要插入好几个之后一起处理,很容易乱掉!!! 也是因为这个把自己搞乱了重做了三四遍!一开始可以随意插入想要的对话框,位置属性可以在代码写完之后再做调整,不然真的很浪费时间!
下面是我最终设计好的界面:
-
基于C++的计算器有界面.zip
2021-12-15 17:28:35自己学习C++的时候写的项目: 基于C++的计算器有界面 -
多项式计算器c++实现,Qt界面
2016-05-30 12:44:20(1)问题描述 设计一个简单的一元稀疏多项式计算器。 (2)基本要求 一个简单的一元稀疏多项式计算器...计算器仿真界面。 (3)数据结构及算法分析 可用带表头结点的单链表存储多项式,多项式的项数存放在头结点中。 -
c++带界面计算器
2013-04-02 02:58:11c++builder6.0 开发的计算器,带界面,希望能帮助学生朋友 -
用C++实现计算器
2020-11-30 21:22:062、安装了QT(虽然我不知道怎么用),用QT来实现计算器的界面设计。3、从b站看了相关的QT课程,为下一步实现第一个属于自己的作品做好铺垫。 今天看的内容仅仅了解一些计算方法的思路和使用QT的基本知识。明天还得再...day-1
今天主要做了3件事。1、了解了实现算数表达式求值底层逻辑的三种方法:(a)用栈和队列分别存储运算符和操作数;(b)双栈算符优先级法 (c)用二叉树求解后缀表达式的值。个人感觉第二种方法思路比较好,操作性强。2、安装了QT(虽然我不知道怎么用),用QT来实现计算器的界面设计。3、从b站看了相关的QT课程,为下一步实现第一个属于自己的作品做好铺垫。
今天看的内容仅仅了解一些计算方法的思路和使用QT的基本知识。明天还得再看看相关视屏,争取开始写实现算数表达式的代码
day-2
今天开始了计算器的界面设计,完成了基本按钮的设置,结果如图所示
相关的C++头文件
#ifndef WIDGET_H
#define WIDGET_Henum BtnType{
Num,//数字
Op,//操作符
Dot,//点
Back,//退格
Equl,//等于
Clear//清除
};
#includenamespace Ui {
class Widget;
}class Widget : public QWidget
{
Q_OBJECTpublic:
explicit Widget(QWidget *parent = nullptr);
~Widget();private:
Ui::Widget *ui;
QString num1;//操作数1
QString num2;//操作数2
QString op;//操作符
};#endif // WIDGET_H
用枚举对按钮进行说明。没有“( )”操作符是因为这是我初步对计算器的设计,后面还要添加相应的模块
主要收获:
学会使用QT中的pushbutton
个人感觉还是很好用的,首先将需要使用的按钮创建出来,然后调节按钮的大小。
下面就是对按钮的精细调节
接下来就是要实现按钮的功能,在头文件中定义按钮。用枚举的方式实现按钮的分类。
具体的算数运算明天实现,后续内容明天更新,,,,,
day-03
今天实现了简单的四则运算,结果如下:
#include "Widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); //数字按钮绑定 connect(ui->Num0,&QPushButton::clicked,[this](){onclicked(Num,"0");}); connect(ui->Num1,&QPushButton::clicked,[this](){onclicked(Num,"1");}); connect(ui->Num2,&QPushButton::clicked,[this](){onclicked(Num,"2");}); connect(ui->Num3,&QPushButton::clicked,[this](){onclicked(Num,"3");}); connect(ui->Num4,&QPushButton::clicked,[this](){onclicked(Num,"4");}); connect(ui->Num5,&QPushButton::clicked,[this](){onclicked(Num,"5");}); connect(ui->Num6,&QPushButton::clicked,[this](){onclicked(Num,"6");}); connect(ui->Num7,&QPushButton::clicked,[this](){onclicked(Num,"7");}); connect(ui->Num8,&QPushButton::clicked,[this](){onclicked(Num,"8");}); connect(ui->Num9,&QPushButton::clicked,[this](){onclicked(Num,"9");}); //运算符按钮绑定 connect(ui->Sum,&QPushButton::clicked,[this](){onclicked(Op,"+");}); connect(ui->Sub,&QPushButton::clicked,[this](){onclicked(Op,"-");}); connect(ui->Mul,&QPushButton::clicked,[this](){onclicked(Op,"*");}); connect(ui->Div,&QPushButton::clicked,[this](){onclicked(Op,"/");}); //其他 connect(ui->Back,&QPushButton::clicked,[this](){onclicked(Back,"back");}); connect(ui->Clear,&QPushButton::clicked,[this](){onclicked(Clear,"clear");}); connect(ui->Dot,&QPushButton::clicked,[this](){onclicked(Dot,".");}); connect(ui->Equ,&QPushButton::clicked,[this](){onclicked(Equ,"=");}); } Widget::~Widget() { delete ui; } void Widget::onclicked(BtnType _type,QString _btn){ switch(_type){ //按钮类型 case Num: { if(mOp.isEmpty())//如果操作数为空,则为操作数一 { mNum1+=_btn; } else //如果操作数不空,则为操作数二 { mNum2+=_btn; } break; } case Op://运算符 { mOp=_btn; break; } case Dot: { if(mOp.isEmpty()) { //操作数一的点 if(!mNum1.isEmpty() && !mNum1.contains("."))//操作数1非空且不包含"." { mNum1+=_btn; } } else { if(!mNum2.isEmpty() && !mNum2.contains("."))//操作数2非空且不包含"." { mNum2+=_btn; } } break; } case Back: { if(!mNum1.isEmpty()&&!mOp.isEmpty()&&!mNum2.isEmpty())//删除操作数二 { mNum2.chop(1);//尾部删除,删除指定字符个数 } else if (!mNum1.isEmpty()&&!mOp.isEmpty()) { mOp.chop(1); } else if (!mNum1.isEmpty()) { mNum1.chop(1); } break; } case Clear://清除 { mNum1.clear(); mNum2.clear(); mOp.clear(); } case Equ://等于 { if(mNum1.isEmpty()||mNum2.isEmpty()||mOp.isEmpty()) return; double num1=mNum1.toDouble();//将字符串转化为小数 double num2=mNum2.toDouble();//将字符串转化为小数 double result=0.0; if(mOp=="+") { result=num1+num2; } else if (mOp=="-") { result=num1-num2; } else if (mOp=="*") { result=num1*num2; } else if (mOp=="/") { if(num2==0.0){ ui->lineEdit->setText("除数不能为0"); return; } else { result=num1/num2; } } ui->lineEdit->setText(QString::number(result));//QString::number 数字转字符串 mNum1.clear(); mNum2.clear(); mOp.clear(); return; } } ui->lineEdit->setText(mNum1+mOp+mNum2);}
##这里暂时没有加入计算器扩号运算,明天会继续优化一下。
主要掌握了一些类的函数,和字符串转换函数。逻辑实现主要靠switch实现,结构比较清晰;在涉及到除法的时候需要分类。
然后主要就是对按钮进行了绑定,通过lineEdit实现输出
day 04
今天主要处理操作符的优先级问题,主要难点在于将中缀表达式正确的转化为后缀表达式,然后按照优先级出栈,再将结果入栈,最后出栈。
主要代码如下:void Exp(const char *S,char OPS[],int &len)//将中缀表达式转变为后缀表达式 { QStack<char> OPE;//符号栈 unsigned int i,j=0; unsigned int tmp = strlen(S); for (i = 0; i < tmp; i++) { switch (S[i]) { case'+': if(OPE.isEmpty())//栈为空 OPE.push(S[i]); else if (OPE.top() == '*' || OPE.top() == '/') { OPS[j++] = OPE.pop();//弹出比'+'运算符优先级高和相等的运算符,依次加入后缀表达式 i--; } else OPE.push(S[i]); break; case'-': if(i!=0 && '('!=S[i-1])//正数 { if(OPE.isEmpty())//栈为空 OPE.push(S[i]); else if (OPE.top() == '*' || OPE.top() == '/')//弹出比'-'运算符优先级高和相等的运算符,依次加入后缀表达式 { OPS[j++] = OPE.pop(); i--; } else OPE.push(S[i]); } else//负数 { while ((S[i] >= '0'&&S[i] <= '9' ) || S[i] == '.' || ('-'==S[i]&&(S[i-1]<'0'||S[i-1]>'9'))) { OPS[j++] = S[i]; if('-'==S[i]) OPS[j++]='@'; i++; } i--; OPS[j++] = '#'; //数字中的间隔符 } break; case'*': if(OPE.isEmpty())//栈为空 OPE.push(S[i]); else OPE.push(S[i]); break; case'/': if(OPE.isEmpty())//栈为空 OPE.push(S[i]); else OPE.push(S[i]); break; case'(': OPE.push(S[i]); break; case')': while (OPE.top() != '(')//依次把栈中的运算符加入后缀表达式并将其出栈 { OPS[j++] = OPE.pop(); } OPE.pop();//从栈中弹出'(' break; default: while ((S[i] >= '0'&&S[i] <= '9') || S[i] == '.' || ('-'==S[i]&&S[i-1]<'0'&&S[i-1]>'9')) { OPS[j++] = S[i]; i++; } i--; OPS[j++] = '#'; //数字中的间隔符 break; } } while (!OPE.isEmpty()) { OPS[j++] = OPE.pop(); } len = j; } void PostExp(char B[], int len, double &result,bool &flag)//用后缀表达式计算结果 { int i; double a; double b; double c; QStack<double>SZ; for (i = 0; i < len; i++) { switch (B[i]) { case'+': { a = SZ.pop(); b = SZ.pop(); c = b + a; SZ.push(c); } break; case'-': { if('@'!=B[i+1]) { a = SZ.pop(); b = SZ.pop(); c = b - a; SZ.push(c); } else { int jx = 0; double dx; char *stx = new char[10]; while (B[i] != '#') { if('@'!=B[i]) stx[jx++] = B[i]; i++; } dx = atof(stx);//把字符串转换成浮点数 SZ.push(dx); delete stx; } } break; case'*': { a = SZ.pop(); b = SZ.pop(); c = b*a; SZ.push(c); } break; case'/': { a = SZ.pop(); b = SZ.pop(); if (a == 0) { flag = false; return; } c = b / a; SZ.push(c); } break; default: int j = 0; double d; char *st = new char[10]; while (B[i] != '#') { st[j++] = B[i]; i++; } d = atof(st);//把字符串转换成浮点数 SZ.push(d); delete st; break; } } result=SZ.top(); }`
运行结果:
-
C++ 程序图形界面计算器(波兰表达式)
2009-10-25 13:45:37这是一个C++(windows forms)编写的表达式计算器,具有图形化界面,采用正常的波兰表达式输入 -
C++科学计算器加实验报告
2012-12-21 16:18:46大一下学期的优秀作品,请每位下载的同志,给下评论!谢谢 -
基于c++ 的 计算器设计
2018-10-16 18:04:48实现一个简单的计算器,它类似于带有Windows附件的计算器。...该系统界面友好,交互性强,健壮性强,操作简单快捷,能快速准确地获得所需计算结果,完全减少了数字计算的难度,节省了时间,有助于人们的生活 -
使用MFC仿照Win10科学计算器界面做的简易计算器
2020-01-13 17:34:54仿照Win10科学计算器界面,能进行基本加减乘除、三角函数、反三角函数、指数对数、取余、开根号、阶乘等运算。 -
C#计算器,界面很美观
2020-06-15 11:48:50C#计算器功能,完成老师布置的大作业,页面很好看,没有缺陷。 各种运算都已涵盖 包括异常处理等等 。作业老师已经给了满分,大家可以下载下来参考 嗯嗯嗯,非常棒 -
c++计算器课程设计
2011-08-22 23:17:13按照系统设计要求,用Visual C++设计和开发一个MFC应用程序---高级计算器,提交由需求分析;系统设计说明(包括主菜单、子菜单、模块功能简介、数据字典、系统结构图);系统技术文档 (包括系统各模块主要流程图,... -
c++ 图形界面线性代数计算器
2015-05-31 17:01:49c++ 图形界面计算器使用vistualc++6.0打开 可计算出矩阵的基础解系 矩阵需要按格式输入 -
简易计算器的c++实现
2022-04-03 11:00:221 开发环境 vs2019 easyx头文件 2 设计思路 1 设置窗口大小以及缓冲区大小 ...实现了一部分计算器界面上的功能 4 未实现功能 1 大数计算 2 部分界面上功能 3 历史记录 代码: erash.h: #pr. -
c++计算器运用堆栈
2013-04-02 21:49:10就是运用了堆栈的方法实现的计算器,但是没有图形界面,只能在cmd上进行计算 -
计算器用户界面与业务逻辑的分离
2020-02-28 13:50:41文章目录1 计算器用户界面与业务逻辑的分离1.1 分析1.2 代码实现 1 计算器用户界面与业务逻辑的分离 1.1 分析 界面与逻辑: 基本程序架构一般包含: 用户界面模块(UI):接受用户输入及呈现数据。 业务逻辑模块... -
复数计算器(附源码带界面).rar
2019-09-16 22:32:53一、复数的表达方式 a.直角坐标:a+jb,其中a为实部,b为虚部,j为虚数符号 b.极坐标:a,其中a为模长,b为角度(单位:度),"为角符号 二、直角坐标和极坐标的转换 得到答案后,点击左上...三、其它操作同普通计算器 -
C++ 计算器课设计
2010-11-28 23:00:02用Visual C++设计和开发一个MFC应用程序---高级计算器,提交由需求分析;系统设计说明(包括主菜单、子菜单、模块功能简介、数据字典、系统结构图);系统技术文档 (包括系统各模块主要流程图,软件总体测试方案与... -
C++实现简单计算器
2021-10-01 00:26:56数据结构课后的实验作业 主要模块为: ...实现图形操作界面 使用了GNU的开源readline库来实现比较人性化的行编辑器功能,具体的操作在这篇博客中 源码: #include <iostream> #include <ss -
C++&QT实现计算器图形界面交互
2020-05-10 14:49:49一、实验目的和要求 要求:在实验-03、实验-05的作业内容基础上 (1)增加图形交互功能。 (2)增加3个逻辑运算符 &&、||、 !,并能处理逻辑运算符和算术运算符的混合... DevC++&QT creator 系统: