安全な 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());
}
それが何をするかを理解するのを助けるために(いくつかの点は単純化されています):
- 指定された文字列で初期化された入力文字列ストリームの作成
- を使用して double 値を読み取ります
operator>>
。これは、空白をスキップして double を読み取ろうとすることを意味します。
- double を読み取ることができなかった場合は
abc
、ストリームでfailビットが設定されます。3abc
のような場合は成功し、fail-bit は設定されないことに注意してください。
- fail-bit が設定
ss
されている場合、ゼロ値に評価されます。これはfalseを意味します。
- double が読み取られた場合は、末尾の空白をスキップします。その後、ストリームの最後にいる場合 (最後を超えて読み取ろうとするとtrue
eof()
が返されることに注意してください。まさにそれを行います)、は true を返します。このチェックは、私たちのチェックに合格しないことを確認することに注意してください。std::ws
eof
3abc
- 右と左の両方のケースがtrue
&&
に評価された場合、呼び出し元に true を返し、指定された文字列が double であることを通知します。
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 ウェイ 2
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
処理された文字の量に設定されます。文字列のサイズと比較されます。2 つの書式指定子の間のスペースは、オプションの末尾の空白を考慮します。
結論
初心者の場合はstd::stringstream
、C++ の方法を読んで実行してください。C++ の一般的な概念に慣れるまでは、ポインターをいじらないでください。