使用Qt制作个人计算器

2023-05-16

       我们知道windows系统有自带的计算器,那么我们也可以用Qt制作一款类似的个人计算器,实现整数的加减乘除括号运算,界面设计使用Qt,计算使用逆波兰算法,下面我就来分享一下个人计算器的制作方法。

一、逆波兰表达式算法介绍

逆波兰表示法是波兰逻辑学家J・卢卡西维兹(J・ Lukasiewicz)于1929年首先提出的一种表达式的表示方法 。后来,人们就把用这种表示法写出的表达式称作“逆波兰表达式”。逆波兰表达式把运算量写在前面,把算符写在后面。

逆波兰表达式又叫做后缀表达式,是一种没有括号,并严格遵循“从左到右”运算的后缀式表达方法,如下表所示:

正常表达式  逆波兰表达式
a+ba b +
a+(b-c)*d a d b c - * +
a+(b-c)a b c - +
a=1+3 a = 1 3
a*(b+c)+d a b c + * d +

 

算法步骤

  1. 首先构造一个运算符栈,此运算符在栈内遵循越往栈顶优先级越高的原则。
  2. 读入一个用中缀表示的简单算术表达式,为方便起见,设该简单算术表达式的右端多加上了优先级最低的特殊符号“#”。
  3. 从左至右扫描该算术表达式,从第一个字符开始判断,如果该字符是数字,则分析到该数字串的结束并将该数字串直接输出。
  4. 如果不是数字,该字符则是运算符,此时需比较优先关系。

           具体做法是:将该字符与运算符栈顶的运算符的优先关系相比较。如果该字符优先关             系高于此运算符栈顶的运算符,则将该运算符入栈。若不是的话,则将栈顶的运算符             从栈中弹出,直到栈项运算符的优先级低于当前运算符,将该字符入栈。

     5.重复步骤1~2,直至扫描完整个简单算术表达式,确定所有字符都得到正确处理,便可          以将中缀式表示的简单算术表达式转化为逆波兰表示的简单算术表达式。

二、个人计算器实现

1.头文件

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QGridLayout>
#include <QPushButton>
#include <QLineEdit>
#include <QDebug>
#include <QFont>

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

private slots:
    void show_lineedit();

private:
    QPushButton *pb[10], *pb1, *pb2, *pb3, *pb4, *pb5, *pb6, *pb7, *pb8;
    QLineEdit *le;
};

#endif // WIDGET_H

2.源文件

#include "widget.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <QApplication>

#define MAX_LEN 30
#define  MAX 100

//栈的数组实现
typedef struct
{
    int data[MAX_LEN];
    int top;
}Stack;

//为栈分配空间
Stack *Createstack()
{
    Stack *p;
    p = (Stack *)malloc(sizeof(Stack));
    p->top = -1;
    return p;
}
//压栈
int Push(Stack *p,int x)
{
    if (p->top == MAX_LEN - 1)
    {
    return -1;
    }
    p->top++;
    p->data[p->top] = x;
    return 0;
}
//出栈
int Pop(Stack *L,int *x)
{
    if (L->top == -1)
    {
    return -1;
    }
    //利用传出参数传出栈顶元素
    *x = L->data[L->top];
    L->top--;
    return 0;
}
//栈顶
int TOP(Stack *L,int *x)
{
    if (L->top == -1)
    {
    return -1;
    }
    *x = L->data[L->top];
    return 0;
}
//判断栈是否为空
int Empty(Stack *L)
{
    return (L->top == -1);
}
//定义符号的优先级
int Priority(int ope)
{
    switch(ope)
    {
    case '(':   return 0;  //左括号已经在栈内时,如果比较,其优先级最低
    case '+':
    case '-':   return 1;
    case '*':
    case '%':
    case '/':   return 2;
    case '^':  return 3;
    default :   return -1;
    }
}
// 将两个数出栈、根据ope符号计算,然后再次入栈
void Calculation(Stack *snum,int ope)
{
    int n,n1,n2;
    Pop(snum,&n1);
    Pop(snum,&n2);
    switch(ope)
    {
        case '+':   n = n1 + n2; break;
        case '-':   n = n2 - n1; break;
        case '*':   n = n1 * n2; break;
        case '/':   n = n2 / n1; break;
        //case '%':   n = n2 % n1; break;
        //case '^':   n = pow(n2,n1);break;
    }
    Push(snum,n);
}
// 先处理除右括号外的符号
void Deal_ope(Stack *snum,Stack *sope,int ope)
{
    int old_ope;
    if (Empty(sope) || ope == '(')
    {
        Push(sope,ope);
        return ;
    }
    TOP(sope,&old_ope);
    if (Priority(ope) > Priority(old_ope))
    {
        //传入符号大于当前栈顶,则将传入符号入栈
        Push(sope,ope);
        return ;
    }
    //如果传入的符号优先级小于当前栈顶符号
    while (Priority(ope) <= Priority(old_ope))
    {
        //将当前栈顶的符号取出与数字栈中顶端的两个数字进行计算
        Pop(sope,&old_ope);
        printf("%c",old_ope);
        Calculation(snum,old_ope);
        if (Empty(sope))
        {
            break;
        }
        //再次取出一个当前栈符号与传入符号比较,循环
        TOP(sope,&old_ope);
    }
    Push(sope,ope);
}
//单独处理右括号
void Right(Stack *snum,Stack *sope)
{
    int old_ope;
    TOP(sope,&old_ope);
    while (old_ope != '(')
    {
        //当前符号出栈然后将数字出栈两个进行计算,在括号内优先级最高
        Pop(sope,&old_ope);
        printf("%c",old_ope);
        Calculation(snum,old_ope);
        //循环
        TOP(sope,&old_ope);
    }
    Pop(sope,&old_ope);//出现左括号时将它丢弃
}
// 打印数字栈
void Display(Stack *L)
{
    int i;
    if (L->top == -1)
    {
    return ;
    }
    for (i = 0 ; i <= L->top; i++)
    {
    printf("%d",L->data[i]);
    }
    printf("\n");
}
//打印符号栈
void Displayope(Stack *L)
{
    int i;
    if (L->top == -1)
    {
    return ;
    }
    for (i = 0 ; i <= L->top; i++)
    {
    printf("%c",L->data[i]);
    }
    printf("\n");
}



Widget::Widget(QWidget *parent)
    : QWidget(parent)
{

     le = new QLineEdit;
    QFont font("Times", 20, QFont::Bold);
    this->setFont(font);

    le->setAlignment(Qt::AlignRight);

    int i = 0, row = 1, col = 0;
    for(i = 0; i < 10; i++)
    {
        pb[i] = new QPushButton(QString::number(i));
    }

    pb1 = new QPushButton("+");
    pb2 = new QPushButton("-");
    pb3 = new QPushButton("*");
    pb4 = new QPushButton("/");
    pb5 = new QPushButton(")");
    pb6 = new QPushButton("c");
    pb7 = new QPushButton("=");
    pb8 = new QPushButton("(");


    QGridLayout *gbox = new QGridLayout;

    for(i = 1; i < 10; i++)
    {
         gbox->addWidget(pb[i], row, col, 1, 1);
          col++;
         if(col == 3)
         {
             row++;
             col = 0;
         }
    }
    gbox->addWidget(pb[0], 4, 1, 1, 1);
    gbox->addWidget(pb1, 3, 3, 1, 1);
    gbox->addWidget(pb2, 2, 3, 1, 1);
    gbox->addWidget(pb3, 1, 3, 1, 1);
    gbox->addWidget(pb4, 0, 3, 1, 1);
    gbox->addWidget(pb5, 4, 2, 1, 1);
    gbox->addWidget(pb6, 0, 0, 1, 1);
    gbox->addWidget(pb7, 4, 3, 1, 1);
    gbox->addWidget(pb8, 4, 0, 1, 1);

    gbox->addWidget(le, 0, 1, 1, 2);

    setLayout(gbox);

    for(i = 0; i < 10; i++)
    {
        connect(pb[i], SIGNAL(clicked(bool)), this, SLOT(show_lineedit()));
    }
    connect(pb1, SIGNAL(clicked(bool)), this, SLOT(show_lineedit()));
    connect(pb2, SIGNAL(clicked(bool)), this, SLOT(show_lineedit()));
    connect(pb3, SIGNAL(clicked(bool)), this, SLOT(show_lineedit()));
    connect(pb4, SIGNAL(clicked(bool)), this, SLOT(show_lineedit()));
    connect(pb5, SIGNAL(clicked(bool)), this, SLOT(show_lineedit()));
    connect(pb6, SIGNAL(clicked(bool)), this, SLOT(show_lineedit()));
    connect(pb7, SIGNAL(clicked(bool)), this, SLOT(show_lineedit()));
    connect(pb8, SIGNAL(clicked(bool)), this, SLOT(show_lineedit()));



}

Widget::~Widget()
{

}

void Widget::show_lineedit()
{
    QPushButton *pb = static_cast<QPushButton *>(sender());

    static QString count_str;

    if(pb == pb6)
    {
       count_str.clear();
       le->clear();
       return;
    }

    QString buf = pb->text();
    count_str += buf;

    le->setText(count_str);

    if(pb == pb7)
    {
       char str[MAX];
       char* ch;
       QByteArray ba = le->text().toLatin1(); // must
       ch=ba.data();

       strcpy_s(str, ch);
       str[strlen(str)-1] = '\0';

       printf("str = %s\n", str);

       int i = 0,value = 0,flag = 0;
       int old_ope;
       Stack *numstack,*opestack;
       numstack = Createstack();  // 创建存放数字的栈
       opestack = Createstack();  // 创建存放运算符的栈

       while (str[i] != '\0')
       {
           if (str[i] >= '0' && str[i] <= '9')
           {
               value *= 10;        //数字的获取,注意可能不止一位
               value +=str[i]-'0';
               flag = 1;
           }
           else
           {
               if (flag)   //flag = 1说明value里面存储了数字,将其入栈
               {
                   printf("%d",value);
                   Push (numstack, value);
                   //flag标志清零,value存放数字的变量清零
                   flag = 0;
                   value = 0;

               }
               if(str[i] == ')')
               {
                   Right(numstack,opestack);

               }
               else
               {
                   Deal_ope(numstack,opestack,str[i]);

               }
           }
           i++;
       }
       if (flag)   //如果flag = 1.说明value里面还有数值,将其入栈
       {
           printf("%d",value);
           Push(numstack,value);
       }
       while (!Empty(opestack))  //如果符号栈不为空,继续计算
       {
           Pop(opestack,&old_ope);
           printf("%c",old_ope);
           Calculation(numstack,old_ope);

       }
       Pop(numstack,&value); //最终答案
       printf("\n%d\n",value);

       count_str.clear();
       le->clear();

       le->setText(QString::number(value));   //数值数据显示在行编辑器上

       return;

    }
}


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    w.show();

    return a.exec();
}

3.结果展示

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Qt制作个人计算器 的相关文章

  • 如何防止网站被爬虫爬取的几种办法

    相较于爬虫技术 xff0c 反爬虫实际上更复杂 目前许多互联网企业都会花大力气进行 反爬虫 xff0c 网络爬虫不但会占据过多的网站流量 xff0c 导致有真正需求的用户没法进入网站 xff0c 另外也有可能会导致网站关键数据的外泄等现象
  • 指定位置插入字符串(c++insert函数、find函数使用)

    一 insert函数 xff08 插入函数 xff09 str1 61 str1 xff08 被插入字符串 xff09 insert 插入位置 str2 xff08 被插入字符串 xff09 xff0c n xff0c m ps xff1a
  • vector容器(C++黑马程序员笔记)

    3 2 vector容器 3 2 1 vector基本概念 功能 vector数据结构和数组非常相似 xff0c 也称为单端数组 vector与普通数组区别 不同之处在于数组是静态空间 xff0c 而vector可以动态扩展 动态扩展 并不
  • set容器(c++黑马程序员笔记)

    3 8 set multiset容器 3 8 1 set基本概念 简介 所有元素都会在插入时自动被排序 本质 set multiset属于关联式容器 xff0c 底层结构是用二叉树实现 set和multiset区别 set不允许容器中有重复
  • map函数

    3 9 map multimap容器 3 9 1 map基本概念 简介 map中所有元素都是pair pair中第一 个元素为key 键值 xff0c 起到索引作用 xff0c 第二个元素为value 实值 所有元素都会根据元素的键值自动排
  • 解决Maven配置本地仓库路径不生效问题多个方法详解。(已成功解决自己遇到的问题)

    首先我尝试了很多种方法 xff0c 就是这个方法让我成功 xff0c 和大家分享一下 xff01 xff08 我用方法二成功的 xff01 xff09 maven本地仓库默认值 xff1a 用户家目录 m2 repository 由于本地仓
  • Servlet快速学习和Tomcat快速部署(web)

    Servlet快速学习和Tomcat快速部署 xff08 web xff09 一 快速入门二 执行流程三 生命周期四 Servlet体系结构五 Servlet urlPattern配置六 XML配置方式编写Servlet七 Tomcat快速
  • 蓝桥杯必备模板(python)

    蓝桥杯必备算法模板 xff08 python xff09 xff1a 前缀和模板差分模板二分双指针位运算最大公约数和最小公倍数模板判断质数和埃氏筛法模板唯一分解定理和质因数分解关系和模板快速幂并查集区间合并回溯算法模板 xff1a DFS
  • 蓝桥杯必备模块及常用操作(python)

    蓝桥杯必会模块 xff08 python xff09 xff1a 字符类型模块日期函数模块 常用 优先级队列itertools模块collections模块Bisect模块List 集合set 集合Math模块 字符类型模块 先看点常用但比
  • string的几个常见库函数

    文章目录 前言一 strlen直接求字符串长度二 strcpy用来赋值三 strcat追加字符串四 strcmp用于比较两个字符串五 strstr子串查找六 strtok应用七 加长度限制八 strerror 九 其他操作1 iscntrl
  • vector详解

    在开始学习C 43 43 的STL之后 xff0c 相信大家都学会通过查文档来了解一些库函数 xff0c 今天我来给大家介绍vector xff0c 从基本的使用到vector背后的源码实现 xff0c 迭代器等展开讲 xff0c 仔细阅读
  • 如何利用开源思想开发一个SEO友好型网站

    当你对一个网站进行 SEO 优化的时候 xff0c 不要期望你的努力能立即得到回报 耐心等待并更正内容营销策略 xff0c 最终会发现你的网站很受用户欢迎 下面就教你如何利用开源思维开发一个SEO友好型网站 xff01 首先 xff0c 你
  • 【STM32】串口通讯USART串口中断配置

    目录 STM32 USART 简介 程序编写 硬件接线 实际波形 STM32 USART 简介 STM32的USART通用同步异步收发器是一个串行通信设备 xff0c 可以灵活的与外部设备进行全双工数据交换 有别于USART xff0c 还
  • openmv第三天之标记跟踪

    AprilTag是一个视觉基准系统 感觉就是一个可以定位 校准帮助openmv来找到 定位的东西 官方解释的用处 xff1a 简单来说 xff0c 只要把这个tag贴到目标上 xff0c 就可以在OpenMV上识别出这个标签的3D位置 xf
  • 【A_star三维路径规划】A_star算法无人机三维路径规划【含Matlab源码 1387期】

    一 A star算法简介 0 引言 随着现代技术的发展 飞行器种类不断变多 应用也日趋专一化 完善化 如专门用作植保的大疆PS X625无人机 用作街景拍摄与监控巡察的宝鸡行翼航空科技的X8无人机 以及用作水下救援的白鲨MIX水下无人机等
  • 【路径规划】A_star算法机器人动态避障路径规划【含Matlab源码 1033期】

    一 A star算法简介 1 A Star算法及其应用现状 进行搜索任务时提取的有助于简化搜索过程的信息被称为启发信息 启发信息经过文字提炼和公式化后转变为启发函数 启发函数可以表示自起始顶点至目标顶点间的估算距离 也可以表示自起始顶点至目
  • C语言打印输出字符串的几种方法

    思路分析 知识点补充 1 xff0c 在C语言中 xff0c 一维数组的数组名实际上就是指向数组首项元素的指针 2 xff0c 如果指针p已经指向一个字符串 xff0c 判断字符串是否结束 xff0c 一般采用while p 61 39 0
  • 对‘fmt::v9::detail::throw_format_error(char const*)’未定义的引用

    在学习视觉SLAM十四讲第十二章的过程中 xff0c 尝试跑了一下单目稠密地图构建的代码 xff0c 在编译源代码的过程中遇到该问题 xff0c 编译结果中显示长篇的 CMakeFiles dense mapping dir dense m
  • [STM32F103C8T6] 串口

    1 非中断串口发送数据 串口发送 接收函数 xff1a HAL UART Transmit 串口发送数据 xff0c 使用超时管理机制 HAL UART Receive 串口接收数据 xff0c 使用超时管理机制 HAL UART Tran
  • 【C语言】strcat函数_字符串追加/连接

    前言 xff1a 在C C 43 43 的学习过程当中一定一定要多刷题 xff0c 牛客网作为国内内容超级丰富的IT题库 xff0c 尤其是它的C C 43 43 xff0c 有从入门到大厂真题 xff0c 而且大部分的考试题目也是从中抽取

随机推荐

  • SWUST OJ448: 字符串查找

    题目描述 在一段句子中找出给定字符串出现在句子中第一个字母出现的位置 句子中字符个数小于4500 字符串字符个数小于120 输入 两行 第一行是给定字符串 第二行是句子 输出 整数 xff0c 字符串出现的位置 样例输入 abcde thi
  • C语言十进制转十六进制

    输入 xff1a 123 输出 xff1a 7B include lt stdio h gt int main int n scanf 34 d 34 amp n int a 100 int count int i 61 0 while 1
  • CentOS软件那么老为什么大家还要用它?

    作为一个专业的服务器系统 xff0c RHEL 系统理论上每一个软件包都有 RedHat 内部的人员负责维护 xff0c 这个维护包括长期 xff08 和系统生命周期一样长 xff09 的开发 更新 测试 运维等 也就是说你能从 RHEL
  • vscode配置C/C++调试环境

    转自作者知乎的原创文章 vscode配置C 43 43 调试环境 在环境变量path中添加mingw中bin后 在vscode界面侧边栏点击调试界面 xff0c 创建launch json文件 添加配置后保存就行 下为我的添加配置后自动生成
  • ROS通信机制~话题通信(Publisher&Subscriber)·笔记2

    系列文章目录 xff1a ROS开发 xff08 ubuntu xff09 笔记 1 嘻 嘻的博客 CSDN博客 ROS通信机制 服务通信 server amp client 笔记3 嘻 嘻的博客 CSDN博客 话题通信 理论模型 xff1
  • postman Windows的详细安装过程

    1 首先去postman官网下载postman 官网地址 xff1a Download Postman Get Started for Free https www postman com downloads 2 根据你浏览器下载的所在位置
  • 数据结构链表的结构体定义的理解(C语言)

    此理解有参考数据结构的教材和一些博主的文章 xff1b 1 先补充一下typedef在此处的基本用法 xff1a typedef可用来建立已经定义好的数据类型的别名 形式为 xff1a typedef 已有变量名 别名 通俗的来说就是给已有
  • ROS安装与Rviz的摄像头视频采集与标定

    文章目录 一 ROS的安装与配置1 添加 ROS 软件源 xff0c 将下列命令输入到 Ubuntu 的终端执行2 添加密钥 xff0c 将下列命令输入到 Ubuntu 的终端执行3 安装desktop full4 初始化rostep5 设
  • HTTP协议的基本格式

    目录 一 HTTP请求 1 1 首行 1 1 1 URL 1 1 2 方法 1 2 请求报头 xff08 header xff09 1 2 1 host 编辑 1 2 2 Content Length和Content Type 1 2 3
  • 思岚雷达win与ubuntu18.04连接并测试详细过程

    雷达简介 包含套件 雷达模组 xff08 内置pwm电机驱动 xff09 usb适配器 Micro USB线缆 电源线 接线方式 ps 雷达不需额外的电源供电 xff0c 直接使用电脑USB接口 xff0c 5V供电 驱动安装 USB 适配
  • c/c++常见字符串函数(strlen,strcmp,strcat,strcpy,strstr,strncpy,strncat,strncmp)的详解和自己编辑实现

    下面介绍c语言中指针与数组的面试题 再看下列题之前首先要知识储备 下面用c语言介绍常用字符串函数和进行编译 一 介绍strlen函数 unsigned int strlen char s 或size t strlen const char
  • 【C语言】学数据结构前必学的结构体struct详细

    佛祖说 xff0c 他可以满足程序猿一个愿望 程序猿许愿有生之年写出一个没有bug的程序 xff0c 然后他得到了永生 目录 1 结构体的声明与定义 1 1结构体是什么 xff1f 1 2为什么要有结构 xff1f 1 3结构体的声明 1
  • 数据结构哈希查找的C语言实现

    大家好 xff0c 我是练习编程时长两年半的昆工第一ikun xff0c 今天我们来分享查找算法中的一个 哈希查找 xff0c 哈希查找适用于有庞大的数据量时的查找 xff0c 是一种很好用的查找算法 xff0c 话不多说 xff0c 开团
  • 为什么很多程序员喜欢linux系统?

    a gt Linux哪些行业在运用 xff1f Linux系统运用极其广泛 xff0c 不少用户只知道windows xff0c 是因为 xff0c Linux的运用主要是在企业端 现在科技极其发达 xff0c 我们手机在手 xff0c 就
  • Linux Ubuntu下的标准IO相关库函数的介绍与使用

    大家好 xff0c 我是练习编程时长两年半的个人练习生昆工第一ikun xff0c 今天我们来分享一下标准IO相关函数库的介绍与使用 xff0c 话不多话 xff0c 开团 xff01 xff01 xff01 xff01 xff01 目录
  • Linux Ubuntu下的文件IO介绍及实例应用(C语言)

    大家好 xff0c 我是练习编程时长两年半的个人练习生昆工第一ikun xff0c 昨天咋们说了标准IO xff0c 今天咋们来分享文件IO xff0c 以及一个很有趣的实例 xff0c 给图片加密 xff0c 使其无法打开 话不多说 xf
  • 输入年月日得出该天是星期几(C语言)

    大家好 xff0c 我是练习编程时长两年半的个人练习生昆工第一ikun xff0c 昨天因为在写Thoughtworkers的2018年笔试题 xff0c 所以没有更新 xff0c 今天就先把笔试题中的一个函数分享出来 xff0c 该函数可
  • Linux下的UDP服务器客户端的搭建(C语言实现)

    大家好 xff0c 我是练习编程时长两年半的个人练习生昆工第一ikun xff0c 昨天我们说了搭建TCP的服务器和客户端 xff0c 今天我们就来分享一下UDP的服务器和客户端搭建 UDP的特点是无连接 xff0c 多个客户端可以发送消息
  • 使用STL库list类实现单双向约瑟夫环问题(C++)

    目录 一 单向约瑟夫环 1 问题描述 2 list类函数用法 xff08 1 xff09 list构造 xff08 2 xff09 list iterator迭代器 xff08 3 xff09 list容量 xff08 4 xff09 li
  • 使用Qt制作个人计算器

    我们知道windows系统有自带的计算器 xff0c 那么我们也可以用Qt制作一款类似的个人计算器 xff0c 实现整数的加减乘除括号运算 xff0c 界面设计使用Qt xff0c 计算使用逆波兰算法 xff0c 下面我就来分享一下个人计算