getline
を使用する場合、文字列または数字の束を入力しますが、数字でない場合はwhileループに「Word」のみを出力させます。 「Word」が数字かどうかを確認する方法はありますか?私はC文字列にatoi()
を使用できることを知っていますが、文字列クラスの文字列にはどうですか?
int main () {
stringstream ss (stringstream::in | stringstream::out);
string Word;
string str;
getline(cin,str);
ss<<str;
while(ss>>Word)
{
//if( )
cout<<Word<<endl;
}
}
別のバージョン...
strtol
を使用し、単純な関数でラップして複雑さを隠します。
inline bool isInteger(const std::string & s)
{
if(s.empty() || ((!isdigit(s[0])) && (s[0] != '-') && (s[0] != '+'))) return false;
char * p;
strtol(s.c_str(), &p, 10);
return (*p == 0);
}
strtol
なのか?私がC++を愛している限りでは、C APIが最良の答えである場合があります:
strtol
は一見非常に生々しいように見えるので、説明を読むとコードが読みやすくなります。
strtol
は文字列を解析し、整数の一部と見なすことができない最初の文字で停止します。 (上記で行ったように)p
を指定すると、p
がこの最初の非整数文字に設定されます。
私の推論は、p
が文字列の最後(0文字)に設定されていない場合、s
を意味する文字列s
に非整数文字があるということです。 _は正しい整数ではありません。
最初のテストは、コーナーケース(先頭のスペース、空の文字列など)を排除するためにあります。
もちろん、この関数は必要に応じてカスタマイズする必要があります(先頭のスペースはエラーですか?など)。
strtol
の説明を参照してください: http://en.cppreference.com/w/cpp/string/byte/strtol 。
strtol
の姉妹関数(strtod
、strtoul
など)の説明も参照してください。
「stol」は最初の桁を変換し、残りを無視するため、入力が数字とテキストの場合、受け入れられた答えは偽陽性となります。
次のバージョンが最も気に入っています。これは、関数を定義する必要のない素敵なワンライナーであり、必要な場所にコピーして貼り付けることができるからです。
#include <string>
...
std::string s;
bool has_only_digits = (s.find_first_not_of( "0123456789" ) == std::string::npos);
編集:この実装が好きなのに、関数として使用したい場合は、次のようにする必要があります。
bool has_only_digits(const string s){
return s.find_first_not_of( "0123456789" ) == string::npos;
}
boost::lexical_cast
を試すことができます。失敗すると、bad_lexical_cast
例外をスローします。
あなたの場合:
int number;
try
{
number = boost::lexical_cast<int>(Word);
}
catch(boost::bad_lexical_cast& e)
{
std::cout << Word << "isn't a number" << std::endl;
}
Word
が数値であるかどうかを確認するだけであれば、それほど難しくありません。
#include <ctype.h>
...
string Word;
bool isNumber = true;
for(string::const_iterator k = Word.begin(); k != Word.end(); ++k)
isNumber &&= isdigit(*k);
必要に応じて最適化します。
強力なC stdio/string関数を使用します。
int dummy_int;
int scan_value = std::sscanf( some_string.c_str(), "%d", &dummy_int);
if (scan_value == 0)
// does not start with integer
else
// starts with integer
boost::lexical_cast
を使用することもできますが、文字列に関する事前知識がある場合(つまり、文字列に整数リテラルが含まれている場合、先頭にスペースがないか、整数が決して指数で書き込まれない) 、独自の関数をローリングすることはより効率的であり、特に難しくはありません。
わかりました、3つのオプションがあります。
1:数値が整数であるかどうかを単純に確認し、変換を気にせず、文字列として保持し、潜在的なオーバーフローを気にしない場合、それが正規表現に一致するかどうかを確認するここでは整数が理想的です。
2:boost :: lexical_castを使用し、潜在的なboost :: bad_lexical_cast例外をキャッチして、変換が失敗したかどうかを確認できます。ブーストを使用でき、変換の失敗が例外的な条件である場合、これはうまく機能します。
3:lexical_castに似た独自の関数をロールし、変換をチェックし、成功したかどうかに応じてtrue/falseを返します。これは、1と2が要件に合わない場合に機能します。
paercebalの方法 を変更して、ニーズに合わせました:
typedef std::string String;
bool isInt(const String& s, int base){
if(s.empty() || std::isspace(s[0])) return false ;
char * p ;
strtol(s.c_str(), &p, base) ;
return (*p == 0) ;
}
bool isPositiveInt(const String& s, int base){
if(s.empty() || std::isspace(s[0]) || s[0]=='-') return false ;
char * p ;
strtol(s.c_str(), &p, base) ;
return (*p == 0) ;
}
bool isNegativeInt(const String& s, int base){
if(s.empty() || std::isspace(s[0]) || s[0]!='-') return false ;
char * p ;
strtol(s.c_str(), &p, base) ;
return (*p == 0) ;
}
注:
1
、負の値または値>36
を渡さないことをsureにしてください。0
をベースとして渡すと、ベースを自動的に検出します。つまり、0x
で始まる文字列は16進数として処理され、0
で始まる文字列はoctとして処理されます。文字は大文字と小文字を区別しません。別のソリューションがあります。
try
{
(void) std::stoi(myString); //cast to void to ignore the return value
//Success! myString contained an integer
}
catch (const std::logic_error &e)
{
//Failure! myString did not contain an integer
}
template <typename T>
const T to(const string& sval)
{
T val;
stringstream ss;
ss << sval;
ss >> val;
if(ss.fail())
throw runtime_error((string)typeid(T).name() + " type wanted: " + sval);
return val;
}
そして、あなたはそれをそのように使うことができます:
double d = to<double>("4.3");
または
int i = to<int>("4123");