我一直在寻找一种方法来确定我的字符串值是否是一个有效的双倍,我还没有找到一种方法也不会拒绝带有一个点的数字......
在我的搜索中,我发现了这个
How to determine if a string is a number with C++?
和Charles Salvia给出的答案是
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();
}
这适用于任何没有点的数字,但带点数的数字会被拒绝...
答案 0 :(得分:10)
你可能想要像这样使用std::stod
:
bool is_number(const std::string& s)
{
try
{
std::stod(s);
}
catch(...)
{
return false;
}
return true;
}
但这可能效率很低,例如, zero-cost exceptions
所以使用@ Robinson的解决方案或strtod
是一个更好的选择:
bool is_number(const std::string& s)
{
char* end = 0;
double val = strtod(s.c_str(), &end);
return end != s.c_str() && val != HUGE_VAL;
}
答案 1 :(得分:3)
为什么不使用istringstream?
#include <sstream>
bool is_numeric (std::string const & str)
{
auto result = double();
auto i = std::istringstream(str);
i >> result;
i >> std::ws;
return !i.fail() && i.eof();
}
答案 2 :(得分:2)
您还可以计算字符串包含的点数。如果此数字小于或等于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;
}
}
如果你知道如何处理这个问题,你也可以使用正则表达式...
答案 3 :(得分:1)
您可以使用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';
}
<强>输出:强>
true
false
true
模板化版本用于测试特定类型
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';
}
<强>输出:强>
true
false
true
false
true
答案 4 :(得分:0)
添加另一项支票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;
}
答案 5 :(得分:0)
确保数字中最多有一个点。
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;
}
答案 6 :(得分:0)
对于这种低级别的操作,我非常反对使用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。
答案 7 :(得分:0)
对此已经发布了一些答案,所以我认为我会添加自己的答案。如果您可以访问C ++ 17,则使用charconv可能是一种更有效的方法。我没有对此进行基准测试,但是对于大多数字符串转换应用程序,charconv效率很高。此解决方案还需要支持charconv到double或来自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 :: from_chars 返回 std :: errc()。从本质上讲,这只是包装 from_chars 并丢弃所得的double。根据您的用例,使用错误值并将其加倍(假设字符串稍后将转换为数字)可能会更有利,但是在那时,使用 from_chars 会更有意义。本身。
答案 8 :(得分:0)
这是我的解决方法:
bool isNumber(string s)
{
for (int i = 0; i < s.length(); i++)
if (isdigit(s[i]) == false && s[i] != '.')
return false;
return true;
}
它对我来说正常工作,您可以尝试一下!