2016-06-22 14 views
1

atoiの代わりにstrtolを使用するべきであると聞いたことがあります。私は、文字列が整数であるかどうかを確認するために、このコードを使用することができるかどうかを確認したかった。C++:文字列が "strtol"を使用する有効な整数かどうか確認してください

#include <iostream> 
#include <stdlib.h> 

using namespace std; 

int main() 
{ 
    string testString = "ANYTHING"; 
    cout << "testString = " << testString << endl; 
    int testInt = strtol(testString.c_str(),NULL,0); 
    cout << "errno = " << errno << endl; 
    if (errno > 0) 
    { 
     cout << "There was an error." << endl; 
     cout << "testInt = " << testInt << endl; 
    } 
    else 
    { 
     cout << "Success." << endl; 
     cout << "testInt = " << testInt << endl; 
    } 
    return 0; 
} 

私は5ANYTHINGを交換し、それが完全に働いた:

testString = 5 
errno = 0 
Success. 
testInt = 5 

をそして私は2147483648でそれを行うとき、可能な最大のint + 1、これを返します:

testString = 2147483648 
errno = 34 
There was an error. 
testInt = 2147483647 

十分に適切です。私はHello world!でそれをしようとする。しかし、これはアップします:

testString = Hello world! 
errno = 0 
Success. 
testInt = 0 

私はここで行うことを意図していますか?そして、文字列がintであることを確認するだけで、何かのために複雑なものを私に与えないでください。使用

:GNU GCCコンパイラ、コード::ブロック、Windowsの
は "G ++続くC++ 11 ISO C++言語の標準[-std = C++ 11]があり、" "コンパイラフラグ" にチェックされています。

+1

[NULL]の代わりに適切な引数を[strtol](http://www.cplusplus)に渡してください。com/reference/cstdlib/strtol /)を使用して有効な範囲を知ることができます。 – Jarod42

+0

あなたの2番目のテストケースのために[No repro](http://coliru.stacked-crooked.com/a/021660de72cf66f4) –

+0

@πάνταῥεῖ、それは 'long'がその番号を保持できるかどうかによって異なります。 32ビットの「long」はできません。 – chris

答えて

2

を見ることができますhttp://man7.org/linux/man-pages/man3/strtol.3.html manページを読んでいる場合。 std::strtolを呼び出しますが、あなたはstd::stringと直接連携

bool isNumeric(const std::string& str) { 
    try { 
     size_t sz; 
     std::stol(str, &sz); 
     return sz == str.size(); 
    } catch (const std::invalid_argument&) { 
     // if no conversion could be performed. 
     return false; 
    } catch (const std::out_of_range&) { 
     // if the converted value would fall out of the range of the result type. 
     return false; 
    } 
} 

std::stol:私のような、std::stol代わりのstd::strtolを使用することを好む、

C++ 11では
bool isNumeric(const std::string& str) { 
    char *end; 
    long val = std::strtol(str.c_str(), &end, 10); 
    if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN)) || (errno != 0 && val == 0)) { 
     // if the converted value would fall out of the range of the result type. 
     return false; 
    } 
    if (end == str) { 
     // No digits were found. 
     return false; 
    } 
    // check if the string was fully processed. 
    return *end == '\0'; 
} 

:あなたのようなあなたの関数を定義する必要がありますコードは単純化されています。

+0

聞いたことがあります可能であれば '試してください'を避けるべきです。 – FluorescentGreen5

+1

@ FluorescentGreen5、現在のベストプラクティスはtry/catchですが、とりわけtry/catchがオプションになります。また、新しいC++ 11ライブラリの機能の中には、上記の例のように 'std :: stol'を使用してtry/catchに必要な機能が必要なものがあります。 – keith

+0

あなたの最初のコードスニペットは仕事をしましたが、関数 "isInt"を呼び出すことをお勧めします。数値として小数点をカウントしません。 – FluorescentGreen5

3

strtolはは、最初の非数字

に停止しますが、あなたはthe man page of strtolによると

If endptr is not NULL, strtol() stores the address of the first invalid character in *endptr. If there were no digits at all, strtol() stores the original value of nptr in *endptr (and returns 0). In particular, if *nptr is not '\0' but **endptr is '\0' on return, the entire string is valid.

すなわち

string testString = "ANYTHING"; 
cout << "testString = " << testString << endl; 
char *endptr; 
int testInt = strtol(testString.c_str(),&endptr,0); 
if(**endptr) 
    cout << "bad input"; 
+0

'エラー:unary '*'(型 'char')の型引数が無効です。このパッチ(3つのファイルすべて)を必ず使用しました:http://tehsausage.com/mingw-to-string – FluorescentGreen5

0

C++の11ウェイソリューションは例外的に使用しないでください。遅いためです。 !

あなたは、文字列はほとんど空でないことが確実な場合
#include <algorithm> 
bool is_decimal(const std::string& s) 
{ 
    return !s.empty() && std::find_if(s.begin(), s.end(), [](char c){ return !std::isdigit(c); }) == s.end(); 
} 

、その後、あなたはs.emptyを削除することができます():ここでは、高速C++ 11のバージョンがあります。あなたがいない場合は、!s.empty()!(s.length()== 0))ので、それを維持あなたは空の文字列と(reference) find_if を呼び出す場合よりも安価です。

編集: オーバーフローを処理する必要がある場合は、上記の例外バージョンを使用してください。例外を使用できない場合にのみ、次のようにしてください:

#include <string> 
#include <sstream> 
#include <limits> 

template <class T> 
bool is_decimal_and_fit(const std::string& s) 
{ 
    long double decimal = 0; 
    return (!(std::istringstream(s) >> decimal).fail() && (decimal >= std::numeric_limits<T>::lowest()) && (decimal <= std::numeric_limits<T>::max())); 
} 
+0

それは数字だけを持っているかどうかをチェックするだけです。番号が符号付き/符号なしでオーバーフローしているかどうかを確認する必要があります。私は提供されている他の方法に固執する必要がありますか? – FluorescentGreen5

+0

ただ、この使用:[](char型のC、 ブールis_decimal(のconstのstd ::文字列&S) { リターンs.empty()&&のstd :: find_if(s.begin()、s.end()を! ){return!std :: isdigit(c);})== s.end(); } – tobias88

+0

申し訳ありませんが、shift + enterはこのクイックコメントでは機能しません。削除できません:) – tobias88

関連する問題