应用 qt 的 c++ 计算器项目

程序框架参考 Whitemeen太白 的帖子 C++计算器实现 ——(完整功能实现、设计分析)

代码较长,可点击目录查看各部分~

支持运算符:

  • +, -, *, /, %(取余), ^(幂次方), !(阶乘), sqrt(平方根), ln(自然对数);
  • 三角函数 sin cos tan, 反三角函数 arcsin arccos acrtan;
  • 圆周率 pi, 自然常数 e;
  • 括号 ( ) [ ] { },| |(绝对值)

实现方法:

  • 符号优先级处理方法:符号等级
  • 运算表达式处理方法:后缀表达式
  • 后缀表达式转换及计算辅助方法:符号栈、数字栈

程序界面:

程序文件结构:

运行环境:

C++ 14 (Visual Studio 2022)

Qt 6.7.2

  •  除零、负数开方等没有编写报错提醒~

calculator.h

#pragma once
// calculator.h: 头文件
#include <stack>
#include <vector>
#include <string>


//计算器类
class Calculator
{
public:
	Calculator();
	bool getFormat();					// 表达式判断合法性及自定义标准格式化
	int getPrior(char c);				// 获取算术符号优先级
	void getPostfix();					// 后缀表达式转换
	void calResult();					// 计算后缀表达式
	double calculate();					// 计算并返回结果
	void clearContainer();              // 清空用到的容器

	std::string operatorSym;			// 运算符号
	std::string infix;					// 表达式缓存

private:
	std::vector<std::string> postfix;	// 后缀表达式向量
	std::stack<char> symStack;			// 符号栈
	std::stack<double> figStack;		// 数字栈
	std::string stdInfix;				// 自定义标准格式化表达式
	double result;						// 最终计算结果
	std::string legalCharacter = "+-*/^lq%!|sctSCTep()[]{} 0123456789.";  // 合法字符
};

 calculator.cpp

// calculator.cpp: 实现文件
#define _USE_MATH_DEFINES
#include <cmath>
#include <stack>
#include <vector>
#include <map>
#include <cmath>
#include <string>
#include <algorithm>
#include <iostream>
#include <functional>

#include "calculator.h"


// 重要数学常量
const double pi = M_PI;  // 圆周率 pi
const double e = M_E;  // 自然常数 e

// 绝对值符号个数的奇偶性
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,
	PRIO_LV5 = 5,
	PRIO_LV6 = 6,
};

// 要替换的三角函数等长标识
std::map<std::string, std::string> tri_func_replace = { {"sin", "s"}, {"cos", "c" }, {"tan", "t" },
														{"arcsin", "S"}, {"arccos", "C"}, {"arctan", "T"},
														{"ln", "l"}, {"pi", "p"}, {"sqrt", "q"}
};

// 字符和要调用的函数名映射
std::map<std::string, std::function<double(double)>> c_func = {
		{"s", static_cast<double(*)(double)>(sin)},
		{"c", static_cast<double(*)(double)>(cos)},
		{"t", static_cast<double(*)(double)>(tan)},
		{"S", static_cast<double(*)(double)>(asin)},
		{"C", static_cast<double(*)(double)>(acos)},
		{"T", static_cast<double(*)(double)>(atan)},
		{"l", static_cast<double(*)(double)>(log)},
		{"q", static_cast<double(*)(double)>(sqrt)},
};
//std::map<std::string, std::function<double(double)>> c_func = { { "s", sin }, { "c", cos }, { "t", tan },
//																{ "S", asin }, { "C", acos }, { "T", atan }
//};

void replaceAll(std::string& str, const std::string& from, const std::string& to);


Calculator::Calculator() {				// 构造函数,初始化成员变量

	operatorSym = "支持运算符:+, -, *, /, %(取余), ^(幂次方), | |(绝对值), !(阶乘), sqrt(平方根), ln(自然对数), 括号 ( ) [ ] { }, 三角函数 sin cos tan, 反三角函数 arcsin arccos acrtan, 圆周率 pi, 自然常数 e";
	result = 0.0;
}

// 表达式判断合法性及自定义标准格式化
bool Calculator::getFormat() {

	stdInfix = infix;

	// 替换三角函数等长标识
	for (auto i = tri_func_replace.begin(); i != tri_func_replace.end(); i++) {
		replaceAll(stdInfix, i->first, i->second);
	}

	// for (int i = 0; i < stdInfix.length(); i++) {				// string 下标调用运算符时可能会导致类型溢出
	for (size_t i = 0; i < stdInfix.size(); i++) {					// string.size() 返回 size_type 类型,避免下标运算时的类型溢出
		if (legalCharacter.find(stdInfix[i]) == std::string::npos) {  // 判断字符合法性
			std::cout << "输入的表达式含非法字符 " << stdInfix[i] << ",返回默认结果 0。" << "\n";
			return false;
		}
		else if (stdInfix[i] == ' ') {  // 删除空格
			stdInfix.erase(i, 1);
		}
		else 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[i - 1] == '[' || stdInfix[i - 1] == '{')
				stdInfix.insert(i, 1, '0');
			else if (stdInfix[i - 1] == '|' && count(stdInfix.begin(), stdInfix.begin() + i, '|') % 2)  // 根据之前的 | 符号个数的奇偶性判断是否添加 0
				stdInfix.insert(i, 1, '0');
		}
	}
	return true;
}

// 获取算术符号优先级
// 单目预算符优先级应高于双目运算符(大概)
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 == 's' || c == 'c' || c == 't' || c == 'S' || c == 'C' || c == 'T' || c == 'l' || c == 'q') {
		return PRIO_LV4;
	}
	else if (c == '!') {
		return PRIO_LV5;
	}
	else if (c == 'p' || c == 'e') {  // pi 和 e 也当作运算符处理,优先级最高
		return PRIO_LV6;
	}
	else {
		return PRIO_LV0;
	}
	// else { cout << c << " 非法符号!" << endl; }
}

// 后缀表达式转换
void Calculator::getPostfix() {

	int absNumeber = ABS_ODD;  // 绝对值符号个数的奇偶性
	std::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 's':
		case 'c':
		case 't':
		case 'S':
		case 'C':
		case 'T':
		case 'l':
		case 'p':
		case 'e':
		case 'q':
		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() {

	std::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) {
				// 阶乘数应大于 0;阶乘数为小数时,求其向下取整的数的阶
				double factorial = 1;
				for (int i = 1; i <= op1; ++i)
				{
					factorial *= i;
				}
				op1 = factorial;
			}
			figStack.push(op1);
		}
		else if (postfix[i] == "s" || postfix[i] == "c" ||
			postfix[i] == "t" || postfix[i] == "S" ||
			postfix[i] == "C" || postfix[i] == "T" ||
			postfix[i] == "l" || postfix[i] == "q") {
			if (!figStack.empty()) {
				op1 = figStack.top();
				figStack.pop();
			}
			figStack.push(c_func[postfix[i]](op1));
		}
		else if (postfix[i] == "p") {
			figStack.push(pi);
		}
		else if (postfix[i] == "e") {
			figStack.push(e);
		}
		else
			std::cout << "后缀表达式中该操作符" << postfix[i] << "未编写处理情况" << "\n";
	}

	if (!figStack.empty()) {
		result = figStack.top();
	}
	else
		std::cout << "结果未正确计算" << "\n";

}

// 单个计算结束,清空用到的容器
void Calculator::clearContainer() {
	std::stack<double>().swap(figStack);  // 和空栈交换,实现清空栈效果
	std::stack<char>().swap(symStack);
	postfix.clear();
}

// 计算并返回结果
double Calculator::calculate() {

	if (getFormat()) {				// 表达式判断合法性及自定义标准格式化
		getPostfix();				// 后缀表达式转换
		calResult();				// 获取算术结果
		clearContainer();           // 清空每次计算用到的容器
		return result;
	}
	return 0;
}


void replaceAll(std::string& str, const std::string& from, const std::string& to) {
	// 把 string 中所有的 from 替换为 to
	size_t pos = 0;
	while ((pos = str.find(from, pos)) != std::string::npos) {
		str.replace(pos, from.length(), to);
		pos += to.length();  // 更新起始位置,避免重复替换  
	}
}

Calculator_gui.h

#pragma once

#include <QtWidgets/QMainWindow>
#include "ui_Calculator_gui.h"
#include "calculator.h"

class Calculator_gui : public QMainWindow
{
    Q_OBJECT

    public:
        Calculator_gui(QWidget *parent = nullptr);
        ~Calculator_gui();

    private slots:
        void value_clicked();  // 数字和操作符的槽函数
        void equal_clicked();  // 等号的槽函数
        void ac_clicked();  // ac 的槽函数
        void del_clicked();  // del 的槽函数
        void ans_clicked();  // ans 的槽函数
        void shift_clicked();  // shift 的槽函数

    private:
        Ui::Calculator_guiClass ui;
        Calculator cal;  // Calculator 子对象
        QString currentExpression;
        double result = 0;
        bool on_shift = false;  // shift 是否按下
};

Calculator_gui.cpp

#include "Calculator_gui.h"

Calculator_gui::Calculator_gui(QWidget* parent): QMainWindow(parent){
    ui.setupUi(this);

    connect(ui.pushButton_0, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_1, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_2, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_3, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_4, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_5, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_6, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_7, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_8, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_9, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_abs, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_ac, SIGNAL(clicked(bool)), this, SLOT(ac_clicked()));
    connect(ui.pushButton_add, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_ans, SIGNAL(clicked(bool)), this, SLOT(ans_clicked()));
    connect(ui.pushButton_c, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_del, SIGNAL(clicked(bool)), this, SLOT(del_clicked()));
    connect(ui.pushButton_div, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_e, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_equ, SIGNAL(clicked(bool)), this, SLOT(equal_clicked()));
    connect(ui.pushButton_fac, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));  // 连接阶乘键
    connect(ui.pushButton_l, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));  
    connect(ui.pushButton_lpar, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));  // 连接左小括号键
    connect(ui.pushButton_lsqb, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));  // 连接左方括号键
    connect(ui.pushButton_shift, SIGNAL(clicked(bool)), this, SLOT(shift_clicked()));
    connect(ui.pushButton_mod, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_mul, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_pi, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_point, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_power, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_rpar, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_rsqb, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_s, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_sqr, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_sub, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));
    connect(ui.pushButton_t, SIGNAL(clicked(bool)), this, SLOT(value_clicked()));   
}

Calculator_gui::~Calculator_gui()
{}

void Calculator_gui::value_clicked() {
        QPushButton * button = qobject_cast<QPushButton*>(sender());
    if (button) {
        QString text = button->text();  // 获取按钮上的文本(数字)  
        currentExpression.append(text);  // 将数字添加到表达式末尾  
        ui.text_input->setText(currentExpression);  // 更新显示  
    }
}

void Calculator_gui::equal_clicked() {
    cal.infix = currentExpression.toStdString();
    result = cal.calculate();
    ui.text_output->setText(QString::number(result));  // 显示结果
    currentExpression.clear();
}

void Calculator_gui::ac_clicked() { 
    currentExpression.clear();
    ui.text_input->setText(currentExpression);  // 更新显示
}

void Calculator_gui::del_clicked() {
    currentExpression.chop(1);
    ui.text_input->setText(currentExpression);  // 更新显示
}

void Calculator_gui::ans_clicked() {
    currentExpression.append(QString("%1").arg(result, 0, 'f', 4));
    ui.text_input->setText(currentExpression);  // 更新显示
}

void Calculator_gui::shift_clicked() {
    on_shift = !on_shift;  // 切换shift状态
    if (on_shift) {
        ui.pushButton_s->setText("arcsin");
        ui.pushButton_c->setText("arccos");
        ui.pushButton_t->setText("arctan");
    }
    else {
        ui.pushButton_s->setText("sin");
        ui.pushButton_c->setText("cos");
        ui.pushButton_t->setText("tan");
    }
}

main.cpp

#include "Calculator_gui.h"
#include <QtWidgets/QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Calculator_gui w;
    w.show();
    return a.exec();
}

 Calculator_gui.ui

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Calculator_guiClass</class>
 <widget class="QMainWindow" name="Calculator_guiClass">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>478</width>
    <height>464</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Calculator_gui</string>
  </property>
  <widget class="QWidget" name="centralWidget">
   <widget class="QWidget" name="layoutWidget">
    <property name="geometry">
     <rect>
      <x>40</x>
      <y>20</y>
      <width>403</width>
      <height>416</height>
     </rect>
    </property>
    <layout class="QVBoxLayout" name="verticalLayout">
     <item>
      <widget class="QTextEdit" name="text_output">
       <property name="font">
        <font>
         <pointsize>18</pointsize>
         <bold>true</bold>
        </font>
       </property>
       <property name="layoutDirection">
        <enum>Qt::LayoutDirection::LeftToRight</enum>
       </property>
       <property name="readOnly">
        <bool>true</bool>
       </property>
       <property name="cursorWidth">
        <number>1</number>
       </property>
      </widget>
     </item>
     <item>
      <widget class="QLineEdit" name="text_input">
       <property name="minimumSize">
        <size>
         <width>0</width>
         <height>30</height>
        </size>
       </property>
       <property name="font">
        <font>
         <pointsize>12</pointsize>
        </font>
       </property>
       <property name="text">
        <string/>
       </property>
      </widget>
     </item>
     <item>
      <layout class="QGridLayout" name="gridLayout">
       <item row="0" column="3">
        <widget class="QPushButton" name="pushButton_3">
         <property name="text">
          <string>3</string>
         </property>
        </widget>
       </item>
       <item row="3" column="1">
        <widget class="QPushButton" name="pushButton_fac">
         <property name="text">
          <string>!</string>
         </property>
        </widget>
       </item>
       <item row="1" column="1">
        <widget class="QPushButton" name="pushButton_4">
         <property name="text">
          <string>4</string>
         </property>
        </widget>
       </item>
       <item row="1" column="4">
        <widget class="QPushButton" name="pushButton_del">
         <property name="text">
          <string>DEL</string>
         </property>
        </widget>
       </item>
       <item row="5" column="4">
        <widget class="QPushButton" name="pushButton_div">
         <property name="text">
          <string>/</string>
         </property>
        </widget>
       </item>
       <item row="0" column="0">
        <widget class="QPushButton" name="pushButton_shift">
         <property name="text">
          <string>SHIFT</string>
         </property>
        </widget>
       </item>
       <item row="3" column="0">
        <widget class="QPushButton" name="pushButton_t">
         <property name="text">
          <string>tan</string>
         </property>
        </widget>
       </item>
       <item row="0" column="4">
        <widget class="QPushButton" name="pushButton_ac">
         <property name="text">
          <string>AC</string>
         </property>
        </widget>
       </item>
       <item row="5" column="1">
        <widget class="QPushButton" name="pushButton_mod">
         <property name="text">
          <string>%</string>
         </property>
        </widget>
       </item>
       <item row="1" column="2">
        <widget class="QPushButton" name="pushButton_5">
         <property name="text">
          <string>5</string>
         </property>
        </widget>
       </item>
       <item row="5" column="0">
        <widget class="QPushButton" name="pushButton_rpar">
         <property name="text">
          <string>)</string>
         </property>
        </widget>
       </item>
       <item row="4" column="3">
        <widget class="QPushButton" name="pushButton_power">
         <property name="text">
          <string>^</string>
         </property>
        </widget>
       </item>
       <item row="1" column="0">
        <widget class="QPushButton" name="pushButton_s">
         <property name="text">
          <string>sin</string>
         </property>
        </widget>
       </item>
       <item row="3" column="2">
        <widget class="QPushButton" name="pushButton_0">
         <property name="text">
          <string>0</string>
         </property>
        </widget>
       </item>
       <item row="3" column="4">
        <widget class="QPushButton" name="pushButton_sub">
         <property name="text">
          <string>-</string>
         </property>
        </widget>
       </item>
       <item row="2" column="2">
        <widget class="QPushButton" name="pushButton_8">
         <property name="text">
          <string>8</string>
         </property>
        </widget>
       </item>
       <item row="4" column="1">
        <widget class="QPushButton" name="pushButton_pi">
         <property name="text">
          <string>pi</string>
         </property>
        </widget>
       </item>
       <item row="0" column="1">
        <widget class="QPushButton" name="pushButton_1">
         <property name="text">
          <string>1</string>
         </property>
        </widget>
       </item>
       <item row="5" column="2">
        <widget class="QPushButton" name="pushButton_sqr">
         <property name="text">
          <string>sqrt</string>
         </property>
        </widget>
       </item>
       <item row="1" column="3">
        <widget class="QPushButton" name="pushButton_6">
         <property name="text">
          <string>6</string>
         </property>
        </widget>
       </item>
       <item row="4" column="4">
        <widget class="QPushButton" name="pushButton_mul">
         <property name="text">
          <string>*</string>
         </property>
        </widget>
       </item>
       <item row="2" column="4">
        <widget class="QPushButton" name="pushButton_add">
         <property name="text">
          <string>+</string>
         </property>
        </widget>
       </item>
       <item row="4" column="2">
        <widget class="QPushButton" name="pushButton_e">
         <property name="text">
          <string>e</string>
         </property>
        </widget>
       </item>
       <item row="3" column="3">
        <widget class="QPushButton" name="pushButton_point">
         <property name="text">
          <string>.</string>
         </property>
        </widget>
       </item>
       <item row="4" column="0">
        <widget class="QPushButton" name="pushButton_lpar">
         <property name="text">
          <string>(</string>
         </property>
        </widget>
       </item>
       <item row="0" column="2">
        <widget class="QPushButton" name="pushButton_2">
         <property name="text">
          <string>2</string>
         </property>
        </widget>
       </item>
       <item row="2" column="1">
        <widget class="QPushButton" name="pushButton_7">
         <property name="text">
          <string>7</string>
         </property>
        </widget>
       </item>
       <item row="5" column="3">
        <widget class="QPushButton" name="pushButton_l">
         <property name="text">
          <string>ln</string>
         </property>
        </widget>
       </item>
       <item row="2" column="3">
        <widget class="QPushButton" name="pushButton_9">
         <property name="text">
          <string>9</string>
         </property>
        </widget>
       </item>
       <item row="2" column="0">
        <widget class="QPushButton" name="pushButton_c">
         <property name="text">
          <string>cos</string>
         </property>
        </widget>
       </item>
       <item row="6" column="0">
        <widget class="QPushButton" name="pushButton_lsqb">
         <property name="text">
          <string>[</string>
         </property>
        </widget>
       </item>
       <item row="6" column="1">
        <widget class="QPushButton" name="pushButton_rsqb">
         <property name="text">
          <string>]</string>
         </property>
        </widget>
       </item>
       <item row="6" column="2">
        <widget class="QPushButton" name="pushButton_abs">
         <property name="text">
          <string>|</string>
         </property>
        </widget>
       </item>
       <item row="6" column="3">
        <widget class="QPushButton" name="pushButton_ans">
         <property name="text">
          <string>Ans</string>
         </property>
        </widget>
       </item>
       <item row="6" column="4">
        <widget class="QPushButton" name="pushButton_equ">
         <property name="text">
          <string>=</string>
         </property>
        </widget>
       </item>
      </layout>
     </item>
    </layout>
   </widget>
  </widget>
  <widget class="QStatusBar" name="statusBar"/>
 </widget>
 <layoutdefault spacing="6" margin="11"/>
 <resources>
  <include location="Calculator_gui.qrc"/>
 </resources>
 <connections/>
</ui>

要实现一个计算器,可以使用Qt Creator创建一个新的Qt Widgets应用程序。然后,在Qt Designer中创建一个用户界面,包括数字和操作符按钮以及一个显示结果的文本框。 接下来,需要编写C++代码来实现计算器的逻辑。可以使用Qt的信号槽机制来连接按钮的点击事件和计算器逻辑的函数。例如,当数字按钮被点击时,将数字添加到正在处理的数字中。当操作符按钮被点击时,将正在处理的数字和之前的数字一起计算,并更新结果文本框。 以下是一个简单的示例代码,仅实现了加法和减法操作: ``` #include <QtCore> #include <QtGui> class Calculator : public QWidget { Q_OBJECT public: Calculator(QWidget *parent = 0); private slots: void digitClicked(); void operatorClicked(); private: QPushButton *createButton(const QString &text, const char *member); void calculate(); double sum; double currentNumber; QString currentOperator; QLineEdit *display; }; Calculator::Calculator(QWidget *parent) : QWidget(parent), sum(0), currentNumber(0) { display = new QLineEdit("0"); display->setReadOnly(true); display->setAlignment(Qt::AlignRight); display->setMaxLength(15); QGridLayout *layout = new QGridLayout; layout->addWidget(display, 0, 0, 1, 4); layout->addWidget(createButton("7", SLOT(digitClicked())), 1, 0); layout->addWidget(createButton("8", SLOT(digitClicked())), 1, 1); layout->addWidget(createButton("9", SLOT(digitClicked())), 1, 2); layout->addWidget(createButton("+", SLOT(operatorClicked())), 1, 3); layout->addWidget(createButton("4", SLOT(digitClicked())), 2, 0); layout->addWidget(createButton("5", SLOT(digitClicked())), 2, 1); layout->addWidget(createButton("6", SLOT(digitClicked())), 2, 2); layout->addWidget(createButton("-", SLOT(operatorClicked())), 2, 3); layout->addWidget(createButton("1", SLOT(digitClicked())), 3, 0); layout->addWidget(createButton("2", SLOT(digitClicked())), 3, 1); layout->addWidget(createButton("3", SLOT(digitClicked())), 3, 2); layout->addWidget(createButton("=", SLOT(operatorClicked())), 3, 3); layout->addWidget(createButton("0", SLOT(digitClicked())), 4, 0, 1, 2); layout->addWidget(createButton(".", SLOT(digitClicked())), 4, 2); layout->addWidget(createButton("C", SLOT(operatorClicked())), 4, 3); setLayout(layout); } QPushButton *Calculator::createButton(const QString &text, const char *member) { QPushButton *button = new QPushButton(text); connect(button, SIGNAL(clicked()), this, member); return button; } void Calculator::digitClicked() { QPushButton *button = qobject_cast<QPushButton*>(sender()); Q_ASSERT(button != 0); int digitValue = button->text().toInt(); currentNumber = currentNumber * 10 + digitValue; display->setText(QString::number(currentNumber)); } void Calculator::operatorClicked() { QPushButton *button = qobject_cast<QPushButton*>(sender()); Q_ASSERT(button != 0); QString clickedOperator = button->text(); if (clickedOperator == "C") { sum = 0; currentNumber = 0; currentOperator = ""; display->setText("0"); return; } if (!currentOperator.isEmpty()) { calculate(); } currentOperator = clickedOperator; sum = currentNumber; currentNumber = 0; } void Calculator::calculate() { if (currentOperator == "+") { sum += currentNumber; } else if (currentOperator == "-") { sum -= currentNumber; } currentNumber = 0; display->setText(QString::number(sum)); } int main(int argc, char *argv[]) { QApplication app(argc, argv); Calculator calc; calc.setWindowTitle("Calculator"); calc.show(); return app.exec(); } ``` 这是一个非常简单的计算器,可以通过添加更多的操作符和逻辑来扩展它。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值