安全的 C++ 方式
您可以使用以下方法为此定义一个函数std::istringstream
:
#include <sstream>
bool is_double(std::string const& str) {
std::istringstream ss(str);
// always keep the scope of variables as close as possible. we see
// 'd' only within the following block.
{
double d;
ss >> d;
}
/* eat up trailing whitespace if there was a double read, and ensure
* there is no character left. the eof bit is set in the case that
* `std::ws` tried to read beyond the stream. */
return (ss && (ss >> std::ws).eof());
}
为了帮助您弄清楚它的作用(简化了一些要点):
- 创建使用给定字符串初始化的输入字符串流
- 使用
operator>>
. 这意味着跳过空格并尝试读取双精度。
- 如果无法读取双精度,则在
abc
流中设置失败位。请注意,类似的情况3abc
会成功并且不会设置失败位。
- 如果设置了失败位,则
ss
计算为零值,这意味着false。
- 如果读取了双精度数,我们会跳过尾随空格。如果我们然后在流的末尾(请注意,如果我们尝试读取结束,将
eof()
返回truestd::ws
。确实如此),eof
将返回 true。请注意,此检查确保3abc
不会通过我们的检查。
- 如果两种情况,左右两边的
&&
求值都为true,我们将 true 返回给调用者,表明给定的字符串是一个双精度字符串。
类似地,您检查int
和其他类型。如果您知道如何使用模板,那么您也知道如何将其推广到其他类型。顺便说一句,这正是boost::lexical_cast
为您提供的。看看: http: //www.boost.org/doc/libs/1_37_0/libs/conversion/lexical_cast.htm。
C方式一
这种方式有优点(速度快)但也有主要缺点(不能使用模板概括,需要使用原始指针):
#include <cstdlib>
#include <cctype>
bool is_double(std::string const& s) {
char * endptr;
std::strtod(s.c_str(), &endptr);
if(endptr != s.c_str()) // skip trailing whitespace
while(std::isspace(*endptr)) endptr++;
return (endptr != s.c_str() && *endptr == '\0');
}
strtod
将设置endptr
为处理的最后一个字符。在我们的例子中是终止空字符。如果未执行转换,则 endptr 设置为给定的字符串的值strtod
。
C方式二
一件可能的事情可以std::sscanf
解决问题。但是很容易监督一些事情。这是正确的方法:
#include <cstdio>
bool is_double(std::string const& s) {
int n;
double d;
return (std::sscanf(s.c_str(), "%lf %n", &d, &n) >= 1 &&
n == static_cast<int>(s.size()));
}
std::sscanf
将返回转换的项目。尽管标准规定%n
不包括在该计数中,但几个来源相互矛盾。最好进行比较>=
以使其正确(请参阅 的联机帮助页sscanf
)。n
将设置为已处理字符的数量。它与字符串的大小进行比较。两个格式说明符之间的空格是可选的尾随空格。
结论
如果您是初学者,请阅读std::stringstream
并以 C++ 的方式进行操作。在您对 C++ 的一般概念感到满意之前,最好不要乱用指针。