C++ 安全读取溢出双as';inf&x27;从字符串

C++ 安全读取溢出双as';inf&x27;从字符串,c++,double,ieee-754,C++,Double,Ieee 754,是否有一种很好的方法可以从字符串中读取溢出的double,即转换“1e500”->+inf 我知道的读取字符串的方法: ::std::stringstream-溢出时返回垃圾 ::boost::lexical\u cast-抛出错误的\u lixecal\u cast,没有关于正在转换的数字的有用信息 ::std::strtodfromcstdlib-afaik它是唯一一个报告溢出的软件(通过返回大数值并将错误号设置为Errange),但是使用它非常不方便 特别是我需要一种方法来可靠地将字符

是否有一种很好的方法可以从字符串中读取溢出的
double
,即转换
“1e500”->+inf

我知道的读取字符串的方法:

  • ::std::stringstream
    -溢出时返回垃圾
  • ::boost::lexical\u cast
    -抛出错误的\u lixecal\u cast,没有关于正在转换的数字的有用信息
  • ::std::strtod
    from
    cstdlib
    -afaik它是唯一一个报告溢出的软件(通过返回
    大数值
    并将
    错误号
    设置为
    Errange
    ),但是使用它非常不方便
特别是我需要一种方法来可靠地将字符串转换为数字(
double
),例如

编辑:

我实际上使用的是最后一种方法,下面是代码:

double stringToDouble(char const *str)
{
    double result = ::std::strtod(str, 0);

    if (ERANGE == errno)
    {
        if (HUGE_VAL == result)
        {
            result = INFINITY;
        }
        else if (-HUGE_VAL == result)
        {
            result = -INFINITY;
        }
    }

    return result;
}
我很惊讶
stringstream
不能很好地处理溢出。但它实际上返回了一些其他的
值(与正在读取的值无关),并且只按stream::fail()方式报告


<>但是我仍然在寻找一些C++的方式读取数字。

嗯,你当前的C方式比我所建议的要有效得多,但是既然你要C++,那么这里有一个定义机械手类对象来保护你不溢出:

#include "stdafx.h"
#include <iostream>
#include <string>
#include <limits>
#include <algorithm>

using namespace std;

struct OverflowProtect
{
} limitdouble;

struct DoubleOverflowException : public std::exception
{

};

double stringToDouble(char const *str)
{
  double result = ::std::strtod(str, 0);

  if (ERANGE == errno)
  {
    if (HUGE_VAL == result)
    {
      throw DoubleOverflowException(); // throw whatever exception you want here
    }
    else if (-HUGE_VAL == result)
    {
      throw DoubleOverflowException(); // throw whatever exception you want here
    }
  }

  return result;
}

istream & operator >> (istream & aIn, const OverflowProtect & aManip)
{
  string number;
  aIn >> number;

  stringToDouble(number.c_str());

  for_each(number.rbegin(), number.rend(), [&aIn](char c){aIn.putback(c);});

  return aIn;
}

int _tmain(int argc, _TCHAR* argv[])
{  
  double nr;
  try
  {
    cin >> limitdouble >> nr;
  }
  catch ( DoubleOverflowException & e )
  {
    // handle overflow exception thrown by limitdouble
    e;
  }

  return 0;
}
#包括“stdafx.h”
#包括
#包括
#包括
#包括
使用名称空间std;
结构溢出保护
{
}有限双倍;
结构DoubleOverflowException:public std::exception
{
};
双字符串双字符(字符常量*str)
{
双结果=::std::strtod(str,0);
if(ERANGE==errno)
{
如果(巨大值==结果)
{
抛出DoubleOverflowException();//在这里抛出您想要的任何异常
}
else if(-maging_VAL==结果)
{
抛出DoubleOverflowException();//在这里抛出您想要的任何异常
}
}
返回结果;
}
istream和operator>>(istream和aIn、常数溢出保护和aManip)
{
字符串编号;
aIn>>编号;
stringToDouble(number.c_str());
对于每个(number.rbegin(),number.rend(),[&aIn](字符c){aIn.putback(c);});
返回aIn;
}
int _tmain(int argc,_TCHAR*argv[]
{  
双nr;
尝试
{
cin>>limitdouble>>nr;
}
捕获(双重溢出例外和e)
{
//limitdouble引发的句柄溢出异常
E
}
返回0;
}
不是最有效的方法,尤其是
操作符>>
实现,但毫无疑问,它很喜欢C++,而且很有趣。
我确信可以进行改进,我只是说明一个想法。

好的,使用strtod,将不方便之处包装在函数中,这样就不会带来不便了,不是吗?你确定没有办法让istringstream以某种方式报告这些数字的错误吗?它返回的垃圾到底是什么?@John:是的,但是提供一个代码示例怎么样?这对你来说可能很明显,但对OP来说却不明显,否则他不会问的。@RobertHarvey我不确定你是否正确。但无论如何,我只是在评论,而不是提供答案。如果OP需要一些代码,我很乐意给它。@john我现在实际上正在使用这个解决方案,但我正在寻找一些C++,这确实很有趣。:)
#include "stdafx.h"
#include <iostream>
#include <string>
#include <limits>
#include <algorithm>

using namespace std;

struct OverflowProtect
{
} limitdouble;

struct DoubleOverflowException : public std::exception
{

};

double stringToDouble(char const *str)
{
  double result = ::std::strtod(str, 0);

  if (ERANGE == errno)
  {
    if (HUGE_VAL == result)
    {
      throw DoubleOverflowException(); // throw whatever exception you want here
    }
    else if (-HUGE_VAL == result)
    {
      throw DoubleOverflowException(); // throw whatever exception you want here
    }
  }

  return result;
}

istream & operator >> (istream & aIn, const OverflowProtect & aManip)
{
  string number;
  aIn >> number;

  stringToDouble(number.c_str());

  for_each(number.rbegin(), number.rend(), [&aIn](char c){aIn.putback(c);});

  return aIn;
}

int _tmain(int argc, _TCHAR* argv[])
{  
  double nr;
  try
  {
    cin >> limitdouble >> nr;
  }
  catch ( DoubleOverflowException & e )
  {
    // handle overflow exception thrown by limitdouble
    e;
  }

  return 0;
}