C++ 确定字符串是否为双精度

C++ 确定字符串是否为双精度,c++,string,double,C++,String,Double,我想看看字符串是否包含一个double作为其唯一内容。换句话说,如果它可能是以下函数的输出: string doubleToString(double num) { stringstream s; s << num; return s.str(); } string doubleToString(双数值) { 细绳; 你想要这个函数 bool isOnlyDouble(const char* str) { char* endptr = 0;

我想看看字符串是否包含一个double作为其唯一内容。换句话说,如果它可能是以下函数的输出:

string doubleToString(double num)
{
    stringstream s;
    s << num;
    return s.str();
}
string doubleToString(双数值)
{
细绳;
你想要这个函数

bool isOnlyDouble(const char* str)
{
    char* endptr = 0;
    strtod(str, &endptr);

    if(*endptr != '\0' || endptr == str)
        return false;
    return true;
}
您可以使用Boost检查字符串是否包含double

#include <boost/lexical_cast.hpp> 
....
using boost::lexical_cast; 
using boost::bad_lexical_cast; 
....
template<typename T> bool isValid(const string& num) { 
   bool flag = true; 
   try { 
      T tmp = lexical_cast<T>(num); 
   } 
   catch (bad_lexical_cast &e) { 
      flag = false; 
   } 
   return flag; 
} 

int main(){
  // ....
 if (isValid<double>(str))
     cout << "valid double." << endl; 
 else 
     cout << "NOT a valid double." << endl;
  //....
}
#包括
....
使用boost::词法转换;
使用boost::bad_词法_cast;
....
模板布尔值有效(常量字符串和数值){
布尔标志=真;
试试{
T tmp=词汇投射(num);
} 
捕捉(错误的词汇投射和e){
flag=false;
} 
返回标志;
} 
int main(){
// ....
if(isValid(str))

您可以选择C风格和boost风格,但在您的
doubleToString
实现中:

bool is_double(const std::string& s)
{
    std::istringstream iss(s);
    double d;
    return iss >> d >> std::ws && iss.eof();
}
这里,您正在检查
iss>>d
返回
iss
,如果流式处理成功,它将仅在布尔上下文中计算为
true
。在
eof()
之前只检查空格,以确保没有后续垃圾

如果您想考虑引导和尾随空白空间的垃圾:

    return iss >> std::nowkipws >> d && iss.eof();
这可以概括为一个布尔返回测试,类似于boost的
lexical\u cast

template <typename T>
bool is_ws(const std::string& s)
{
    std::istringstream iss(s);
    T x;
    return iss >> x >> std::ws && iss.eof();
}

template <typename T>
bool is(const std::string& s)
{
    std::istringstream iss(s);
    T x;
    return iss >> std::noskipws >> x && iss.eof();
}

...
if (is<double>("3.14E0")) ...
if (is<std::string>("hello world")) ...; // note: NOT a single string
                                         // as streaming tokenises at
                                         // whitespace by default...
模板
bool is_ws(const std::string&s)
{
标准:istringstream iss;
tx;
返回iss>>x>>std::ws&&iss.eof();
}
模板
bool is(const std::string&s)
{
标准:istringstream iss;
tx;
返回iss>>std::noskipws>>x&&iss.eof();
}
...
如果(是(“3.14E0”)。。。
if(is(“hello world”)…;//注意:没有一个字符串
//在
//默认为空白。。。
您可以将模板专门用于您想要的任何特定类型的行为,例如:

template <>
bool is<std::string>(const std::string& s)
{
    return true;
}
模板
bool is(const std::string&s)
{
返回true;
}

或直接使用流:

#include <string>
#include <sstream>
#include <iostream>

template<typename T>
bool isValid(std::string const& num)
{
    T  value;
    std::stringstream stream(num);
    stream >> value;

    // If the stream is already in the error state peak will not change it.
    // Otherwise stream should be good and there should be no more data
    // thus resulting in a peek returning an EOF
    return (stream) &&
           stream.peek() == std::char_traits<typename std::stringstream::char_type>::eof();
}

int main()
{
    isValid<double>("55");
}
#包括
#包括
#包括
模板
bool是有效的(std::string const&num)
{
T值;
std::stringstream(num);
流>>值;
//如果流已经处于错误状态,peak将不会更改它。
//否则,流应该是好的,不应该有更多的数据
//从而导致偷看返回EOF
返回(流)&&
stream.peek()==std::char_traits::eof();
}
int main()
{
有效(“55”);
}

因为没有人提到它:显而易见的解决方案是,您想知道字符串是否具有给定的语法,就使用正则表达式。我不确定这是否是这种情况下的最佳解决方案,因为合法双精度的正则表达式相当复杂(因此很容易出错)。并且您的规范有点模糊:是否接受任何可以解析的字符串(例如通过
>
)作为合法的双精度,或者只有字符串可以由
doubleToString
函数返回?如果是前者,最简单的解决方案可能是将字符串转换为双精度,确保没有错误并且您已使用了所有字符(Martin的解决方案,只是在需要之前将其作为模板是愚蠢的)。如果是后者,最简单的解决方案是使用函数将找到的双精度值重新转换为字符串,并比较两个字符串。(只是为了明确区别:对于
“1.0”
“1E2”
,.0000000000 1”
“3.141592653589793238462643383279520288419716939937”
,您的函数将永远不会生成它。)

如果不执行转换,则返回零,并且nptr的值存储在endptr引用的位置。如果(x)返回false,则我似乎无法使用这种检测双精度的方法;[else]return true;
更好地表达为'return!(x);Chris:它可以更好地考虑代码:删除冗余的“return”",关键字
true
false
显然是任何逻辑测试的结果,以及
if
语句也隐含在这种情况下。因此,这证明它更简洁。我无法证明它本身更简单或更好-这取决于程序员维护它。尽管如此,经过28年的编程我可以向你保证,业界的期望和最佳实践是,程序员应该尽一点努力,让他们的头脑了解布尔运算的本质,并相应地简化代码。根据strdot的文档,小数点依赖于本地。因此,这意味着此函数旨在从m用户输入,但不适合解析某些定义良好的格式,例如文件。假设您使用点作为小数点,但在捷克Windows上是逗号默认小数点而不是点。因此,strdot将查找逗号,它是美国格式的千位分隔符。您将解析非小数点和完全不同的数字d、 @BoundaryImposition:
return endptr!=str&&&*endptr=='\0';
不是以牺牲复杂性为代价进行压缩的-它是简化的。如果你在Chris的回答中比
If
语句更纠结于这一点,那么你就不应该专业地编程。-1用于滥用异常。异常不应该用于控制流,克里斯:我有,但不足以采用Python风格。即使如此,一种语言中的正常语言在另一种语言中是很差的。另一个例子是在使用列表理解时,在OCAML中编写C++代码。@ Ben Voigt:我认为代码比代码片段更完美和更干净。Chris发布。
lexical_cast(num);
在失败时抛出异常。我想不出更好的替代方法。@Chris:但实际上,它捕获异常以将其转换为返回值,这是