(C++)简单计算器

文章目录

  • 一、实验目的、内容
  • 二、实验程序设计及结构
    • 1.需求分析
      • 变量
      • 函数
    • 2.设计结构或流程图
  • 三、设计过程
  • 四、测试分析
    • 第一组
    • 第二组
    • 实验中出现的bug及解决方案
  • 五、设计的特点和结果

一、实验目的、内容

输入是一个带有括号的四则运算表达式,输出是计算得出的正确计算结果。

二、实验程序设计及结构

1.需求分析

由于待求值表达式长度不限,故采用标准库类型string存储字符串;又因为运算符个数不确定,故采用标准库类型vector存储运算符的位置。要能检查错误,故包含math.h头文件利用宏定义NAN返回错误值。要能计算小数,故采用double作运算。

变量

字符串a(string)用于存储待求值表达式;数result(double)用于存储结果。

函数

计算函数double cal(string s),主函数int main()string的成员函数,vector的成员函数以及库函数stodisnanto_string

2.设计结构或流程图

  1. 输入表达式存入a中。
  2. 调用计算函数求值,并存入b中。
    1. 输入表达式存入a中。
    2. 调用计算函数求值,并存入b中。
      1. 首先遍历字符串,若存在' ''\t'则删除之以免影响后面的计算;若存在'(',将此时的位置保存于string类下的迭代器a中,n表示嵌套'('的个数递增;若存在')'n递减,如果n减至0,递归调用计算函数以消除括号;若出现数字、运算符字符、小数点'.'以及指数'e'以外的字符或分母为0的情况,返回NAN
      2. 在递归完成后(没有'('),如果n(左括号个数减右括号个数)非零,返回NAN
      3. 处理乘除:定义向量u(vector<string::size_type>)保存'*''/'运算符的位置。从第一个运算符开始把相邻两个数用stod转换为double作运算,用to_string把运算结果转换为字符串用成员函数replace替换回原来的字符串,删除u的首元素并移动u中各元素的位置。重复上述过程直到u为空集。
      4. 处理加减:利用上面的u保存'+''-'运算符的位置,并将相邻的加减号合并。其余过程与乘除类似。
      5. 将结果转换为double并返回。
  3. 判断b的值并输出。

三、设计过程

#include <iostream>
#include <string>
#include <vector>
#include <math.h> //利用宏定义NAN
using namespace std;
double cal(string s)
{
    string s1;
    string::iterator a, b, i; // a记录'(',b记录')'
    string::size_type n = 0;
    int l;
    if (false)
    F:
        s.replace(a, i + 1, to_string(cal(string(a + 1, i))).c_str()); // 递归计算括号
R:
    i = s.begin();
    while (i < s.end())
    {
        if (*i == ' ' || *i == '\t')
        {
            s.erase(i);
            goto R;
        }
        if (*i == '(')
        { // 防止悬垂else问题
            if (!n++)
                a = i;
        }
        else if (*i == ')')
        { // 防止悬垂else问题
            if (!--n)
                goto F;
        }
        else if (*i != '\0' && *i != '.' && *i != 'e' && *i != '*' && *i != '-' && *i != '+' && *i != '/' && (*i < '0' || *i > '9') || (*i == '/' && *(i + 1) == '0' && *(i + 2) != '.'))
            return NAN; // 不是数学表达式
        ++i;
    }
    if (n)
        return NAN; // 左括号个数不等于右括号个数
    vector<string::size_type> u;
    // k用作bool数组
    // 第一位表示第一个数字的正负性
    // 第二位表示第二个数字的正负性
    // 第三位表示第一个数字是否为字符串首个数字
    unsigned char k = 0;
    // 计算乘除
    for (b = a = s.begin(); a < s.end(); ++a)
        if (*a == '*' || *a == '/')
            u.push_back(a - b);
    while (u.size())
    {
        i = a = b = s.begin() + u[0];
        while ((*--b >= '0' && *b <= '9') || *b == '.' || *b == 'e')
            if (b == s.begin())
            {
                k = 4;
                goto G;
            }
        // n记录第一个数字的首位的位置
        k += *b == '-';
        if (*b == '-')
            n = b - s.begin();
        else
            n = ++b - s.begin();
    G:
        double t = stod(string(b, a++));
        do
            if (++a == s.end())
                break;
        while ((*a >= '0' && *a <= '9') || *a == '.' || *a == 'e');
        double w = stod(string(i + 1, a));
        k += (w < 0) * 2;
        if (*i == '*')
        {
            l = (s1 = to_string(t * w)).size() - (a - b);
            s.replace(b, a, s1.c_str());
        }
        else if (w)
        {
            l = (s1 = to_string(t / w)).size() - (a - b);
            s.replace(b, a, s1.c_str());
        }
        else
            return NAN; // 除数为0
        switch (k)
        {
        case 2:
            s.erase(s.begin() + n - 1);
            break; // 删除-号前的+
        case 3:
            s.insert(s.begin() + n, '+'); // 在计算结果之前加一个+
        }
        u.erase(u.begin());
        for (auto &q : u)
            q += l;
    }
    // 计算加减
H:
    for (a = (b = s.begin()) + 1; a < s.end(); ++a)
        if (*a == '+')
        {
            if (*(a + 1) == '-' || *(a + 1) == '+')
            {
                s.erase(a);
                goto H;
            }
            u.push_back(a - b);
        }
        else if (*a == '-')
        {
            if (*(a + 1) == '-')
            {
                s.replace(a, a + 2, "+");
                goto H;
            }
            else if (*(a + 1) == '+')
            {
                s.erase(a + 1);
                goto H;
            }
            u.push_back(a - b);
        }
    while (u.size())
    {
        i = a = (b = s.begin()) + u[0];
        double t = stod(string(b, a++));
        do
            if (++a == s.end())
                break;
        while ((*a >= '0' && *a <= '9') || *a == '.' || *a == 'e');
        if (*i++ == '+')
            l = (s1 = to_string(t + stod(string(i, a)))).size() - (a - b);
        else
            l = (s1 = to_string(t - stod(string(i, a)))).size() - (a - b);
        s.replace(b, a, s1.c_str());
        u.erase(u.begin());
        for (auto &q : u)
            q += l;
    }
    return stod(s);
}
int main()
{
    string a;
    cout << "请输入数学算术表达式:\n";
    cin >> a;
    double result = cal(a);
    if (isnan(result))
        cout << "表达式不正确!\n";
    else
        cout << result << endl;
    system("pause");
    return 0;
}

四、测试分析

第一组

第二组

实验中出现的bug及解决方案

bug解决方案
u如果使用vector<string::iterator>在替换后可能导致u中的迭代器失效使用数字而非迭代器保存
29行需要加上*i!='\0',否则无论输入任何表达式都会报错加上条件判断
容易出现超级大数检查乘除时负负得正的情况,并在结果前加一个'+'用以区分;在每次替换完成后移动u中的元素

五、设计的特点和结果

采用递归的思想解决括号,并根据优先级和结合方向逐个处理运算符。

结果:求出表达式的值。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/343722.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

canvas绘制美国国旗(USA Flag)

查看专栏目录 canvas实例应用100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

kubeadm部署k8s1.27.2版本高可用集群(外部etcd集群带TLS认证)

文章目录 环境软件版本服务器系统初始化etcd 证书生成etcd集群部署负载均衡器部署部署k8s集群部署网络组件FAQ 环境 控制平面节点主机的配置最少是2C2G,否则kubeadm init的时候会报错 主机名IP组件系统os128192.168.177.128etcd、kube-apiserver、kube-controller-manager、k…

Kubernetes/k8s之HPA,命名空间资源限制

Horizontal Pod Autoscaling:po的水平自动伸缩 这是k8s自带的模块 pod占用cpu比例达到一定的阀值&#xff0c;会触发伸缩机制。 根据cpu的阀值触发伸缩机制 replication controller 副本控制器 控制pod的副本数 deployment controller 节点控制器 部署pod hpa控制副本的数…

玩客云Armbian 23.8.1 Bullseye安装PrometheusGrafana

Welcome to Armbian 23.8.1 Bullseye with bleeding edge Linux 6.4.13-edge-meson prometheus 参考Monitoring – How to install Prometheus/Grafana on arm – Raspberry PI/Rock64 | Blogs (mytinydc.com) cd /usr/local/srcwget https://github.com/prometheus/prometh…

Studio One 6 mac 6.5.2 激活版 数字音乐编曲创作

PreSonus Studio One是PreSonus出品的一款功能强大的音乐创作软件。主要为用户提供音乐创作、录音、编辑、制作等功能。它可以让你创造音乐&#xff0c;无限的轨道&#xff0c;无限的MIDI和乐器轨道&#xff0c;虚拟乐器和效果通道&#xff0c;这些都是强大和完美的。 软件下载…

不合格机器人工程讲师再读《悉达多》-2024-

一次又一次失败的经历&#xff0c;让我对经典书籍的认同感越来越多&#xff0c;越来越觉得原来的自己是多么多么的无知和愚昧。 ----zhangrelay 唯物也好&#xff0c;唯心也罢&#xff0c;我们都要先热爱这个世界&#xff0c;然后才能在其中找到自己所热爱的事业。 ----zh…

神经网络的学习(Neural Networks: Learning)

1.代价函数 案例&#xff1a;假设神经网络的训练样本有&#x1d45a;个&#xff0c;每个包含一组输入&#x1d465;和一组输出信号&#x1d466;&#xff0c;&#x1d43f;表示神经网络层数&#xff0c;&#x1d446;&#x1d43c;表示每层的 neuron 个数(&#x1d446;&#…

web安全思维导图(白帽子)

web安全思维导图(白帽子) 客户端脚本安全 服务端应用安全 白帽子讲web安全 安全运营体系建设

‘cnpm‘ 不是内部或外部命令,也不是可运行的程序

一、问题 昨天用npm 安装环境&#xff0c;实在太慢了&#xff0c;就想用cnpm&#xff0c;然后发现提示‘cnpm 不是内部或外部命令,也不是可运行的程序。 看了很多方法&#xff0c;选择了下面这个&#xff0c;运气好到爆棚&#xff0c;就直接可以用了。其他的方法暂未去了解。先…

C++模板与STL【STL概述】

&#x1f308;个人主页&#xff1a;godspeed_lucip &#x1f525; 系列专栏&#xff1a;C从基础到进阶 &#x1f30f;1 STL概述&#x1f349;1.1 STL的诞生&#x1f349;1.2 STL基本概念&#x1f349;1.3 STL六大组件&#x1f349;1.4 STL中容器、算法、迭代器&#x1f349;1.5…

Typecho后台无法登录显示503 service unavailable问题及处理

一、Typecho 我的博客地址&#xff1a;https://www.aomanhao.top 使用老薛主机动态Typecho博客框架handsome主题的搭配&#xff0c;文章内容可以异地网页更新&#xff0c;可以听后台背景音乐&#xff0c;很好的满足我的痛点需求&#xff0c;博客部署在云端服务器访问响应较快…

微信小程序(十二)在线图标与字体的获取与引入

注释很详细&#xff0c;直接上代码 上一篇 新增内容&#xff1a; 1.从IconFont获取图标与文字的样式链接 2.将在线图标配置进页面中&#xff08;源码&#xff09; 3.将字体配置进页面文字中&#xff08;源码&#xff09; 4.css样式的多文件导入 获取链接 1.获取图标链接 登入…

百度大脑 使用

百度大脑&#xff1a; 官方网址&#xff1a;https://ai.baidu.com/ 文档中心&#xff1a;https://ai.baidu.com/ai-doc 体验中心&#xff1a;https://ai.baidu.com/experience 百度大脑则是百度AI核心技术引擎&#xff0c;它包括基础层、感知层、认知层和安全&#xff0c;是百…

理想架构的非对称高回退Doherty功率放大器理论与仿真

Doherty理论—理想架构的非对称高回退Doherty功率放大器理论与仿真 参考&#xff1a; 三路Doherty设计 01 射频基础知识–基础概念 Switchmode RF and Microwave Power Amplifiers、 理想架构的Doherty功率放大器&#xff08;等分经典款&#xff09;的理论与ADS电流源仿真参考…

python爬虫之JS逆向基础小案例:网抑云数据获取

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 所用软件 解释器: python 3.8 编辑器: pycharm 2022.3 使用的模块 第三方模块&#xff1a; requests >>> 数据请求 execjs >>> pip insta…

Structure-from-Motion Revisited(COLMAP) 流程介绍

Structure-from-Motion Revisited&#xff08;COLMAP&#xff09;流程介绍 主要贡献1 场景图增强2 下一最佳视图选择3 稳健高效的三角化4 BA5 冗余视图挖掘 Reference&#xff1a; Structure-from-Motion Revisited 原文COLMAP 使用教程Colmap论文——《Structure-from-Motion …

HarmonyOS鸿蒙应用开发( 四、重磅组件List列表组件使用详解)

List列表组件&#xff0c;是一个非常常用的组件。可以说在一个应用中&#xff0c;它的身影无处不在。它包含一系列相同宽度的列表项&#xff0c;适合连续、多行呈现同类数据&#xff0c;如商品列表、图片列表和和文本列表等。ArkUI 框架采用 List 容器组件创建列表&#xff08;…

红队打靶练习:W34KN3SS: 1

目录 信息收集 1、arp 2、nmap 3、nikto 4、gobuster 5、dirsearch WEB web信息收集 目录探测 漏洞利用 openssl密钥碰撞 SSH登录 提权 get user.txt get passwd 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface: eth0, type: EN10MB…

【深度学习】初识深度学习

初识深度学习 什么是深度学习 关系&#xff1a; #mermaid-svg-7QyNQ1BBaD6vmMVi {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-7QyNQ1BBaD6vmMVi .error-icon{fill:#552222;}#mermaid-svg-7QyNQ1BBaD6vmMVi .err…

HEGERLS智能物流机器人|场景为王 以存取为技术核心布局的仓储集群

随着物流需求的多样化、复杂化&#xff0c;四向穿梭车技术经过几年的蓬勃发展&#xff0c;正在各领域迎来愈加广泛的应用。河北沃克作为该领域的代表&#xff0c;凭借庞大的产品群、功能强大的软件系统以及资源丰富的生态合作伙伴体系实现了快速的发展。其中&#xff0c;海格里…
最新文章