Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/133.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++ 如何验证字符串是否为有效的double(即使其中有一个点)?_C++_String_Double - Fatal编程技术网

C++ 如何验证字符串是否为有效的double(即使其中有一个点)?

C++ 如何验证字符串是否为有效的double(即使其中有一个点)?,c++,string,double,C++,String,Double,我整晚都在寻找一种方法来确定我的字符串值是否是一个有效的double,但我还没有找到一种方法可以不拒绝一个带点的数字 在我的搜索中我找到了这个 查尔斯·萨尔维亚给出的答案是 bool is_number(const std::string& s) { std::string::const_iterator it = s.begin(); while (it != s.end() && std::isdigit(*it)) ++it; return !s.empty()

我整晚都在寻找一种方法来确定我的字符串值是否是一个有效的double,但我还没有找到一种方法可以不拒绝一个带点的数字

在我的搜索中我找到了这个

查尔斯·萨尔维亚给出的答案是

bool is_number(const std::string& s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
return !s.empty() && it == s.end();
}

这适用于任何没有点但有点的数字被拒绝的数字…

您还可以计算字符串包含的点数。如果此数字小于或等于1,并且所有其他字符都是数字,则字符串是有效的双精度字符串

bool isnumber(const string& s)
{
    int nb_point=0;
    for (int i=0; i<s.length();i++)
    {
         if (s[i]=='.')
         {
              nb_point++;
         }
         else if (!isdigit(s[i])
         {
              return false;
         }
    }
    if (nb_point<=1)
    {
          return true;
    }
    else
    {
          return false;
    }
}
bool isnumber(常量字符串&s)
{
int nb_点=0;

对于(int i=0;i添加另一个检查
c='.

bool is_number(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(), 
    s.end(), [](char c) { return !(std::isdigit(c) || c == '.');  }) == s.end();
}
您可以使用以下方法使代码更易于阅读:

bool is_number(const std::string& s)
{
    int dotCount = 0;
    if (s.empty())
       return false;

    for (char c : s )
    {
       if ( !(std::isdigit(c) || c == '.' ) && dotCount > 1 )
       {
          return false;
       }
       dotCount += (c == '.');
    }

    return true;
}
您可以使用:


但这可能效率很低,请参见,例如,确保数字中最多有一个点

bool is_number(const std::string& s)
{
    if (s.empty())
       return false;

    bool sawDot = false;
    for (char c : s )
    {
       if ( !(std::isdigit(c) || (c == '.' && !sawDot) ) )
          return false;
       sawDot = sawDot || (c == '.');
    }

    return true;
}

为什么不直接使用istringstream呢

#include <sstream>

bool is_numeric (std::string const & str) 
{
    auto result = double();
    auto i = std::istringstream(str);

    i >> result;      

    return !i.fail() && i.eof();
}
#包括
布尔是数字的(std::string const&str)
{
自动结果=双();
自动i=std::istringstream(str);
i>>结果;
return!i.fail()和&i.eof();
}

您可以使用
std::istringstream()
。它通过不设置
eof()
标志来告诉您数字后面是否有任何非数字

bool is_number(const std::string& s)
{
    long double ld;
    return((std::istringstream(s) >> ld >> std::ws).eof());
}

int main()
{
    std::cout << std::boolalpha << is_number("   3.14") << '\n';
    std::cout << std::boolalpha << is_number("   3.14x") << '\n';
    std::cout << std::boolalpha << is_number("   3.14 ") << '\n';
}
模板化版本:用于测试特定类型

template<typename Numeric>
bool is_number(const std::string& s)
{
    Numeric n;
    return((std::istringstream(s) >> n >> std::ws).eof());
}

int main()
{
    std::cout << std::boolalpha << is_number<int>("314") << '\n';
    std::cout << std::boolalpha << is_number<int>("3.14") << '\n';
    std::cout << std::boolalpha << is_number<float>("   3.14") << '\n';
    std::cout << std::boolalpha << is_number<double>("   3.14x") << '\n';
    std::cout << std::boolalpha << is_number<long double>("   3.14 ") << '\n';
}

我强烈反对在这种低级别操作中使用try-catch方法。 相反,我用自己做了以下几件事:

bool const hasDoubleRepresentation( std::string const & str, double & d ) const {
std::stringstream sstr(str);
return !((sstr >> std::noskipws >> d).rdstate() ^ std::ios_base::eofbit);}
上述方法的优点是,如果返回true,它还将d设置为str中包含的数字。如果不需要此附加功能,则可以删除d作为输入参数。
还请注意,如果str类似于“3.14”,则noskipws(无跳过空格)的存在会导致返回false,即包含空格的数字。

对此有一些答案,所以我想我会添加我自己的答案。如果您可以访问C++17,使用charconv可能是一种更有效的方法。我尚未对此进行基准测试,但对于大多数字符串转换应用程序,charconv非常有效。此解决方案还需要编译器that支持charconv到/从double.VC++支持这一点;我不确定其他哪些编译器实现了标准库的这一方面

#include <string>
#include <charconv>

bool string_is_number(const std::string& str)
{
    if (str.empty()) return false;
    double result;
    auto[ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), result);
    return (ec == std::errc());
}
#包括
#包括
布尔字符串是字符串编号(常量std::string&str)
{
if(str.empty())返回false;
双重结果;
auto[ptr,ec]=std::from_chars(str.data(),str.data()+str.size(),result);
返回(ec==std::errc());
}
成功转换后,std::from_chars返回std::errc()。这本质上就是简单地从_chars包装并丢弃生成的双精度。根据您的使用情况,采用错误值和双精度(假设字符串稍后将转换为数字)可能更有利,但在这一点上,单独使用use from_chars会更有意义。

以下是我的解决方案:

bool isNumber(string s)
{
    for (int i = 0; i < s.length(); i++)
        if (isdigit(s[i]) == false && s[i] != '.')
            return false;

    return true;
}
bool isNumber(字符串s)
{
对于(int i=0;i

它对我来说工作正常,你可以试试看!

我喜欢这一个的可能副本。std::stod也可以抛出\u范围之外的\u,你不能这样做,所以你需要另一个捕获。没错,我实际上错过了OP寻找“有效双精度”行为而不是“有效数字”的部分这是固定的,谢谢!效率如何?错误的返回伴随着与catch处理程序相关的巨大运行时间效率低下。这应该是一个非常重要的问题,因为这个函数可能经常被击中。是的,用一个catch实现一个这样的函数并不是最有效的解决方案,因为大多数C++实现。ons似乎使用零成本异常。因此,使用strtod或@Robinson应该是首选。@Ð..修复了解决方案,使其对这些异常返回false。@CinCout,是的,它将返回false。捕捉得很好。当
dotCount>1
时,为什么不在循环中返回
?@CinCout,可以。它使代码变得比需要的更复杂,因为在循环中没有多少收益如果我们将要遇到它们的次数与我们没有遇到它们的次数相比是很小的,那么实际使用情况会如何呢?我怀疑这是否是过度优化。因此,问题就来了。负面效果如何?只要你去掉
I>>std::ws;
行,它就可以正常工作。否则,它会在基本输入上失败,如“67.12345”。谢谢。我已经修复了它。我想我们可以假设输入在任何情况下都已经事先去掉了空白。为什么
auto result=double();
而不是
double result;
double result={};
?我更喜欢AAA(几乎总是自动的).这包括负数吗?@Peyman不,这不适用于负数
true
false
true
false
true
bool const hasDoubleRepresentation( std::string const & str, double & d ) const {
std::stringstream sstr(str);
return !((sstr >> std::noskipws >> d).rdstate() ^ std::ios_base::eofbit);}
#include <string>
#include <charconv>

bool string_is_number(const std::string& str)
{
    if (str.empty()) return false;
    double result;
    auto[ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), result);
    return (ec == std::errc());
}
bool isNumber(string s)
{
    for (int i = 0; i < s.length(); i++)
        if (isdigit(s[i]) == false && s[i] != '.')
            return false;

    return true;
}