C++ 用正则regex和容器vector计算字符串算式的值

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: C++ 用正则regex和容器vector计算字符串算式的值

要求:科学记数法必须是(d e± i,e后不能省略+或-)运算符必须是(+、-、*、/、^,5种)

  暂未处理有括号的运算式;字符串也不能有运算符和数字(包括 . 和e)之外的字符


步骤:先用正则表达式regex把字符串算式拆分成数和运算符,依次存放进容器vector,

  然后按运算符优先级别先后计算出中间结果,最后计算代数和。


代码如下:

#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
#include <regex>
#include <cfloat>
using namespace std;
#define isSgn(s) (s=="+"?1:(s=="-"?2:(s=="*"?3:(s=="/"?4:(s=="^"?5:(s==""?1:0))))))
int Error=0;
int regexSplit(string&, const string, vector<string>&, int=0);
long double str2ld(string);
string ld2str(long double);
long double expSum(string);
void outError(void);
template<typename Type>
void v_erase(vector<Type> &v, size_t pos)
{ //删除容器中指定第pos和pos+1个元素 
  if (pos+1>v.size()) return;
  vector<Type> tmp(v.begin()+pos+1,v.end());
  while (v.size()>pos-1) v.pop_back();
  for (auto t:tmp) v.push_back(t);
  vector<Type>().swap(tmp); //清空临时容器tmp
}
int main(void)
{
  long double sum;
  string str = "-1+2*3+4/5-5.8e+1+1.9999999999999999984279*2^16383";
  sum=expSum(str);
  if (Error==0)
    cout<<str<<"="<<endl<<setprecision(18)<<sum<<endl;
  else
    outError();
  cout<<"long doube最大值DBL_MAX:"<<endl<<setprecision(18)<<LDBL_MAX;
  return 0;
 }
long double expSum(string str)
{
  long double sum=0; 
  string reg("\\d+|\\d+\\.\\d+|(\\d+|\\d+\\.\\d+)e[+-]\\d+");
  vector <string> v,vt; 
  regexSplit(str,reg,v);
  regexSplit(str,reg,vt,-1);
  if (!(isdigit(str[0])||str[0]=='+'||str[0]=='-')) Error=1; //表达式错 
  for(auto t:vt) if (t.size()>1||!isSgn(t)) Error=2; //表达式错
  for (int i=0;i<vt.size();i++) //vt间隔插入v
    v.insert(v.begin()+i*2,1,vt.at(i));
  for (int i=1;i<v.size();i++)
    if(v.at(i)=="^"){ //幂指运算 
        v.at(i-1)=ld2str(pow(str2ld(v.at(i-1)),str2ld(v.at(i+1))));
        if (v.at(i-1)=="inf") Error=3; //溢出,结果超出long double范围 
        if (v.at(i-1)=="nan") Error=4; //无意义,如负数的小数次方
        if (v.at(i-1)=="inf"||v.at(i-1)=="nan") break;
        v_erase(v,i+1);
        i--; //位置前移1,解决如2^2^3这样的连续幂指运算 
      }
  for (int i=1;i<v.size();i++) //把所有x/n转换成x*(1/n) 
    if(v.at(i)=="/")
      if (v.at(i+1)!="0"){
        v.at(i+1)=ld2str(1/str2ld(v.at(i+1)));
        v.at(i)="*";
      }
      else{
        Error=5; //除0错 
        break;
      }
  for (int i=1;i<v.size();i++)
    if(v.at(i)=="*"){
        v.at(i-1)=ld2str(str2ld(v.at(i-1))*str2ld(v.at(i+1)));
        v_erase(v,i+1);
        i--; //位置前移1,解决连乘运算 
      }
  for (int i=0;i<v.size();i++){
    if(v.at(i)=="-"){  // 把所有x-n转换成x+(-n) 
      v.at(i)="+";
      v.at(i+1)="-"+v.at(i+1);
    }
  }
  for (int i=1;i<v.size();i=i+2) //求出算式的代数和 
    sum+=str2ld(v.at(i));
  vector<string>().swap(v); //清空容器 
  vector<string>().swap(vt);
  return sum;
}
int regexSplit(string &str,const string str_reg,vector<string>&vect,int pos)
{
  if (pos!=-1) pos=0;  //pos=0 匹配到的位置,pos=-1匹配位置的前一字串 
  regex myPattern(str_reg); 
    sregex_token_iterator it(str.begin(),str.end(),myPattern,pos); 
    sregex_token_iterator end;
    for(;it!=end;++it) vect.push_back(*it); 
    return vect.size();  //if 0 没有匹配到,else 匹配到的个数
 } 
string ld2str(long double d)
{
  string s;
  stringstream ss;
  ss<<setprecision(18)<<d;
  s=ss.str();
  ss.clear();
  return s;
}
long double str2ld(string s)
{
  long double d;
  stringstream ss;
  ss<<s;
  ss>>setprecision(18)>>d;
  ss.clear();
  return d;
}
void outError(void)
{
  switch(Error){
    case 1:
    case 2:
      cout<<"表达式错!"; 
      break;
    case 3:
      cout<<"#INF错误!"; 
      break;
    case 4:
      cout<<"#NAN错误!"; 
      break;
    case 5:
      cout<<"#DIV/0错!";       
      break;
  }
  Error=0;
}


运行结果:

-1+2*3+4/5-5.8e+1+1.9999999999999999984279*2^16383=
1.18973149535723177e+4932
long doube最大值DBL_MAX:
1.18973149535723177e+4932
--------------------------------
Process exited after 0.5967 seconds with return value 0
请按任意键继续. . .



顺带找到一个比较接近long double最大值的数:1.9999999999999999984279*2^16383


看来我的系统上long double型是12字节的,最大值应该是2^16384 -1


通常double型数字到 2^1024 就溢出了

目录
相关文章
|
10天前
|
C语言 C++
【实战指南】 C/C++ 枚举转字符串实现
本文介绍了在C/C++中实现枚举转字符串的实用技巧,通过宏定义与统一管理枚举名,提升代码调试效率并减少维护错误。
43 10
|
5月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
5月前
|
算法 编译器 C++
模拟实现c++中的vector模版
模拟实现c++中的vector模版
|
5月前
|
消息中间件 Linux C++
c++ linux通过实现独立进程之间的通信和传递字符串 demo
的进程间通信机制,适用于父子进程之间的数据传输。希望本文能帮助您更好地理解和应用Linux管道,提升开发效率。 在实际开发中,除了管道,还可以根据具体需求选择消息队列、共享内存、套接字等其他进程间通信方
120 16
|
6月前
|
Serverless 编译器 C++
【C++面向对象——类的多态性与虚函数】计算图像面积(头歌实践教学平台习题)【合集】
本任务要求设计一个矩形类、圆形类和图形基类,计算并输出相应图形面积。相关知识点包括纯虚函数和抽象类的使用。 **目录:** - 任务描述 - 相关知识 - 纯虚函数 - 特点 - 使用场景 - 作用 - 注意事项 - 相关概念对比 - 抽象类的使用 - 定义与概念 - 使用场景 - 编程要求 - 测试说明 - 通关代码 - 测试结果 **任务概述:** 1. **图形基类(Shape)**:包含纯虚函数 `void PrintArea()`。 2. **矩形类(Rectangle)**:继承 Shape 类,重写 `Print
113 4
|
6月前
|
存储 人工智能 Python
[oeasy]python061_如何接收输入_input函数_字符串_str_容器_ 输入输出
本文介绍了Python中如何使用`input()`函数接收用户输入。`input()`函数可以从标准输入流获取字符串,并将其赋值给变量。通过键盘输入的值可以实时赋予变量,实现动态输入。为了更好地理解其用法,文中通过实例演示了如何接收用户输入并存储在变量中,还介绍了`input()`函数的参数`prompt`,用于提供输入提示信息。最后总结了`input()`函数的核心功能及其应用场景。更多内容可参考蓝桥、GitHub和Gitee上的相关教程。
93 0
|
8月前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
412 4
|
7月前
|
存储 对象存储 C++
C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
本文深入对比了 C++ 标准库中的 `std::array` 和 `std::vector`,从内存管理、性能、功能特性、使用场景等方面详细分析了两者的差异。`std::array` 适合固定大小的数据和高性能需求,而 `std::vector` 则提供了动态调整大小的灵活性,适用于数据量不确定或需要频繁操作的场景。选择合适的容器可以提高代码的效率和可靠性。
251 0
|
7月前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
178 0
|
9月前
|
存储 C++ 索引
【C++打怪之路Lv9】-- vector
【C++打怪之路Lv9】-- vector
102 1