web-dev-qa-db-ja.com

C ++文字列がintかどうかを確認するにはどうすればよいですか?

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;
    }
}
37
user342231

別のバージョン...

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が最良の答えである場合があります:

  • 例外の使用は、失敗することを許可されたテストにとってはやり過ぎです
  • 字句キャストによる一時的なストリームオブジェクトの作成は、C標準ライブラリにジョブを実行するためのあまり知られていない専用関数がある場合、過剰で効率が悪いです。

どのように機能しますか?

strtolは一見非常に生々しいように見えるので、説明を読むとコードが読みやすくなります。

strtolは文字列を解析し、整数の一部と見なすことができない最初の文字で停止します。 (上記で行ったように)pを指定すると、pがこの最初の非整数文字に設定されます。

私の推論は、pが文字列の最後(0文字)に設定されていない場合、sを意味する文字列sに非整数文字があるということです。 _は正しい整数ではありません。

最初のテストは、コーナーケース(先頭のスペース、空の文字列など)を排除するためにあります。

もちろん、この関数は必要に応じてカスタマイズする必要があります(先頭のスペースはエラーですか?など)。

ソース:

strtolの説明を参照してください: http://en.cppreference.com/w/cpp/string/byte/strtol

strtolの姉妹関数(strtodstrtoulなど)の説明も参照してください。

66
paercebal

「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;
}
56

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;
}
16
Karl von Moor

Wordが数値であるかどうかを確認するだけであれば、それほど難しくありません。

#include <ctype.h>

...

string Word;
bool isNumber = true;
for(string::const_iterator k = Word.begin(); k != Word.end(); ++k)
    isNumber &&= isdigit(*k);

必要に応じて最適化します。

8
Mike DeSimone

強力な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
4
cmo

boost::lexical_castを使用することもできますが、文字列に関する事前知識がある場合(つまり、文字列に整数リテラルが含まれている場合、先頭にスペースがないか、整数が決して指数で書き込まれない) 、独自の関数をローリングすることはより効率的であり、特に難しくはありません。

4
James

わかりました、3つのオプションがあります。

1:数値が整数であるかどうかを単純に確認し、変換を気にせず、文字列として保持し、潜在的なオーバーフローを気にしない場合、それが正規表現に一致するかどうかを確認するここでは整数が理想的です。

2:boost :: lexical_castを使用し、潜在的なboost :: bad_lexical_cast例外をキャッチして、変換が失敗したかどうかを確認できます。ブーストを使用でき、変換の失敗が例外的な条件である場合、これはうまく機能します。

3:lexical_castに似た独自の関数をロールし、変換をチェックし、成功したかどうかに応じてtrue/falseを返します。これは、1と2が要件に合わない場合に機能します。

3
Jacob

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. さまざまなベース(2進数、8進数、16進数など)を確認できます。
  2. ベースとして1、負の値または値>36を渡さないことをsureにしてください。
  3. 0をベースとして渡すと、ベースを自動的に検出します。つまり、0xで始まる文字列は16進数として処理され、0で始まる文字列はoctとして処理されます。文字は大文字と小文字を区別しません。
  4. 文字列に空白があると、falseが返されます。
1
Jahid

別のソリューションがあります。

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
}
1
Benjamin
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");
1
Nicolas Viennot