45

を使用するgetlineと、一連の文字列または数値を入力しますが、数値でない場合は while ループで「単語」を出力するだけです。「単語」が数字かどうかを確認する方法はありますか?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;
    }
}
4

11 に答える 11

74

別のバージョン...

を使用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、 は正しい整数ではありません。

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

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

ソース:

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

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

于 2010-05-16T20:09:24.127 に答える
70

「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;
}
于 2016-06-16T16:42:20.383 に答える
17

試してみてくださいboost::lexical_castbad_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;
}
于 2010-05-16T18:03:56.683 に答える
9

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

#include <ctype.h>

...

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

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

于 2010-05-16T18:20:36.790 に答える
5

強力な 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
于 2013-01-23T20:52:15.980 に答える
4

わかりました、私が見る方法には、3 つのオプションがあります。

1: 数値が整数かどうかを確認したいだけで、変換は気にせず、文字列として保持したいだけでオーバーフローの可能性を気にしない場合は、ここでは整数が理想的です。

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

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

于 2010-05-16T18:06:08.757 に答える
4

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

于 2010-05-16T18:11:47.487 に答える
3

ここに別の解決策があります。

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
}
于 2017-07-10T11:09:45.683 に答える
2
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");
于 2010-05-16T18:14:37.827 に答える
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. さまざまな基数 (2 進数、8 進数、16 進数など) を確認できます。
  2. 、負の値、または値をベースとして渡さないようにしてください。1>36
  3. 基数として渡す0と、基数が自動検出されます。つまり、 で始まる0x文字列は 16 進数として扱われ、 で始まる文字列は 8 進数として0扱われます。文字は大文字と小文字を区別しません。
  4. 文字列に空白があると、false が返されます。
于 2015-11-24T12:22:38.137 に答える