Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何使用boost词法转换库仅用于检查输入_C++_Boost_Lexical Cast - Fatal编程技术网

C++ 如何使用boost词法转换库仅用于检查输入

C++ 如何使用boost词法转换库仅用于检查输入,c++,boost,lexical-cast,C++,Boost,Lexical Cast,我经常使用boost词法转换库将文本数据解析为数值。然而,在一些情况下,我只需要检查值是否是数字;我实际上不需要或使用转换 因此,我考虑编写一个简单的函数来测试字符串是否为双精度: template<typename T> bool is_double(const T& s) { try { boost::lexical_cast<double>(s); return true; } catch (...) {

我经常使用boost词法转换库将文本数据解析为数值。然而,在一些情况下,我只需要检查值是否是数字;我实际上不需要或使用转换

因此,我考虑编写一个简单的函数来测试字符串是否为双精度:

template<typename T> 
bool is_double(const T& s)
{
  try 
  {
    boost::lexical_cast<double>(s); 
    return true;
  }
  catch (...) 
  {
    return false;
  }
}
模板
布尔值为双(常数T&s)
{
尝试
{
boost::词法转换;
返回true;
}
捕获(…)
{
返回false;
}
}
我的问题是,有没有优化编译器会放弃这里的词法转换,因为我从来没有实际使用过这个值


有没有更好的技术可以使用词法转换库来执行输入检查?

因为转换可能会引发异常,因此直接删除该转换的编译器将严重损坏。您可以假设所有主要的编译器都能正确地处理这个问题


从性能的角度来看,尝试执行词法转换可能不是最佳选择,但除非您以这种方式检查数百万个值,否则就不必担心了。

我认为您需要稍微重新编写该函数:

template<typename T>  
bool tryConvert(std::string const& s) 
{ 
    try         { boost::lexical_cast<T>(s);} 
    catch (...) { return false; }

    return true; 
} 
模板
bool-tryConvert(标准::字符串常量&s)
{ 
试试{boost::lexical_cast;}
catch(…){return false;}
返回true;
} 

无论发生什么情况,编译器都不太可能成功地抛出转换。例外只是锦上添花。如果您想对此进行优化,您必须编写自己的解析器来识别浮点的格式。使用regexps或手动解析,因为模式很简单:

if ( s.empty() ) return false;
string::const_iterator si = s.begin();
if ( *si == '+' || * si == '-' ) ++ si;
if ( si == s.end() ) return false;
while ( '0' <= *si && *si <= '9' && si != s.end() ) ++ si;
if ( si == s.end() ) return true;
if ( * si == '.' ) ++ si;
if ( ( * si == 'e' || * si == 'E' )
 && si - s.begin() <= 1 + (s[0] == '+') + (s[0] == '-') ) return false;
if ( si == s.end() ) return si - s.begin() > 1 + (s[0] == '+') + (s[0] == '-');
while ( '0' <= *si && *si <= '9' && si != s.end() ) ++ si;
if ( si == s.end() ) return true;
if ( * si == 'e' || * si == 'E' ) {
    ++ si;
    if ( si == s.end() ) return false;
    if ( * si == '-' || * si == '+' ) ++ si;
    if ( si == s.end() ) return false;
    while ( '0' <= *si && *si <= '9' && si != s.end() ) ++ si;
}
return si == s.end();

另一方面,该代码已经过测试;v) 你可以试试这样的东西

#include <sstream>

//Try to convert arg to result in a similar way to boost::lexical_cast
//but return true/false rather than throwing an exception.
template<typename T1, typename T2>
bool convert( const T1 & arg, T2 & result )
{
    std::stringstream interpreter;
    return interpreter<<arg && 
           interpreter>>result && 
           interpreter.get() == std::stringstream::traits_type::eof();
}

template<typename T>
double to_double( const T & t )
{
   double retval=0;
   if( ! convert(t,retval) ) { /* Do something about failure */ }
   return retval;
}

template<typename T>
double is_double( const T & t )
{
   double retval=0;
   return convert(t,retval) );
} 
#包括
//尝试将arg转换为类似于boost::lexical_cast的结果
//但是返回true/false,而不是抛出异常。
模板
布尔转换(常数T1和arg、T2和结果)
{
stringstream解释器;
返回解释器结果(&R)
解释器.get()==std::stringstream::traits_type::eof();
}
模板
双对双(常数T&T)
{
双回程=0;
如果(!convert(t,retval)){/*对失败*/}
返回返回;
}
模板
双倍即双倍(常数T&T)
{
双回程=0;
返回转换(t,retval));
} 
convert函数的作用与boost::lexical_cast基本相同,只是lexical cast更小心地避免使用固定缓冲区等来分配动态存储

将boost::lexical_cast代码重构为这种形式是可能的,但这种代码非常密集且难以处理-很遗憾,lexical_cast没有在后台使用类似的东西实现。。。然后它可能看起来像这样:

template<typename T1, typename T2>
T1 lexical_cast( const T2 & t )
{
  T1 retval;
  if( ! try_cast<T1,T2>(t,retval) ) throw bad_lexical_cast();
  return retval;
}
模板
T1词汇转换(常数T2&t)
{
T1检索;
如果(!try_cast(t,retval))抛出bad_lexical_cast();
返回返回;
}

最好先使用正则表达式,然后使用词法强制转换来转换为实际类型。

因为类型T是一个模板化的类型名,我相信您的答案是正确的,因为它将能够处理boost::词法强制转换已经处理的所有情况

不过,不要忘记为已知类型专门化函数,如
char*
wchar\u t*
std::string
wstring
,等等

例如,您可以添加以下代码:

template<>
bool is_double<int>(const int & s)
{
   return true ;
}

template<>
bool is_double<double>(const double & s)
{
   return true ;
}

template<>
bool is_double<std::string>(const std::string & s)
{
   char * p ;
   strtod(s.c_str(), &p) ; // include <cstdlib> for strtod
   return (*p == 0) ;
}
模板
布尔值为双精度(常数整数和整数)
{
返回true;
}
模板
布尔是双精度的(常数双精度和s)
{
返回true;
}
模板
布尔是双精度的(常数标准::字符串和s)
{
char*p;
strtod(s.c_str(),&p);//包含strtod
返回(*p==0);
}
通过这种方式,您可以“优化”已知类型的处理,并将剩余的案例委托给boost::lexical_cast。

您现在可以使用标题
boost/lexical_cast/try_lexical_convert.hpp
(如果您只想
try_lexical_convert
)。像这样:

double temp;
std::string convert{"abcdef"};
assert(boost::conversion::try_lexical_convert<double>(convert, temp) != false);
双温;
字符串转换{“abcdef”};
断言(boost::conversion::try_lexical_conversion(convert,temp)!=false);

编译器不会删除强制转换。强制转换中有一个if语句,它可能引发异常。如果它跳过了,我会理解它是在改变你的逻辑。你可能想抓住它(boost::bad_lexical_cast),否则像操作符
bool
double
这样奇怪的转换会很流行。这只是一种风格的改变吗?是否还有其他理由不使用try返回?@Inverse:查看原始函数名和返回类型。也就是说,就我所知,将返回值移出是一个表面上的改变。@GMan:slaps-header你是对的,我输入了错误的函数名/返回类型@格曼:不清楚这是否会成功。如果他一次从输入字符串中提取一个字符串,那么无论如何都不会发生。这就是投否决票的原因吗?编辑-我已经意识到了这一点,希望得到一个更具建设性的更正:vP,除了
哨兵
之外,我不记得如何丢弃空格了,顺便说一句,我没有投你反对票。丢弃方式:
ss>>std::ws
。请参见如何模拟
词法转换
。请注意,流代码不会检查数字后面是否有空格分隔的其他内容<代码>123.4诸如此类
转换很好。事实确实如此。boost在其自定义流实现中隐藏了部分匹配的预防。我已经将他们的方法explorer.get()==std::stringstream::traits_type::eof()集成到我的代码中,这样就不会再出现部分匹配。您如何维护所有有效转换的正则表达式,并确保它们完全匹配
词法转换所使用的格式,直至与区域性相关的格式?祝你好运。
double temp;
std::string convert{"abcdef"};
assert(boost::conversion::try_lexical_convert<double>(convert, temp) != false);