Can I tell if a std::string represents a number us

2019-04-06 14:54发布

Apparently this is suposed to work in showing if a string is numerical, for example "12.5" == yes, "abc" == no. However I get a no reguardless of the input.

std::stringstream ss("2");
double d; ss >> d;
if(ss.good()) {std::cout<<"number"<<std::endl;}
else {std::cout<<"other"<<std::endl;}

4条回答
2楼-- · 2019-04-06 15:31
int str2int (const string &str) {
  stringstream ss(str);
  int num;
  if((ss >> num).fail())
  { 
      //ERROR: not a number
  }
  return num;
}
查看更多
小情绪 Triste *
3楼-- · 2019-04-06 15:44

You should use an istringstream so that it knows it's trying to parse input. Also, just check the result of the extraction directly rather than using good later.

#include <sstream>
#include <iostream>

int main()
{
    std::istringstream ss("2");
    double d = 0.0;
    if(ss >> d) {std::cout<<"number"<<std::endl;}
    else {std::cout<<"other"<<std::endl;}
}
查看更多
太酷不给撩
4楼-- · 2019-04-06 15:44

Don't use good()! Test if the stream is failed or not:

if (ss)

Good tells you if any of eofbit, badbit, or failbit are set, while fail() tells you about badbit and failbit. You almost never care about eofbit unless you already know the stream is failed, so you almost never want to use good.

Note that testing the stream directly, as above, is exactly equivalent to:

if (!ss.fail())

Conversely, !ss is equivalent to ss.fail().


Combining the extraction into the conditional expression:

if (ss >> d) {/*...*/}

Is exactly equivalent to:

ss >> d;
if (ss) {/*...*/}

However, you probably want to test if the complete string can be converted to a double, which is a bit more involved. Use boost::lexical_cast which already handles all of the cases.

查看更多
一夜七次
5楼-- · 2019-04-06 15:47

If you want to check whether a string contains only a number and nothing else (except whitespace), use this:

#include <sstream>

bool is_numeric (const std::string& str) {
    std::istringstream ss(str);
    double dbl;
    ss >> dbl;      // try to read the number
    ss >> std::ws;  // eat whitespace after number

    if (!ss.fail() && ss.eof()) {
        return true;  // is-a-number
    } else {
        return false; // not-a-number
    }
}

The ss >> std::ws is important for accepting numbers with trailing whitespace such as "24 ".

The ss.eof() check is important for rejecting strings like "24 abc". It ensures that we reached the end of the string after reading the number (and whitespace).

Test harness:

#include <iostream>
#include <iomanip>

int main()
{
    std::string tests[8] = {
            "", "XYZ", "a26", "3.3a", "42 a", "764", " 132.0", "930 "
    };
    std::string is_a[2] = { "not a number", "is a number" };
    for (size_t i = 0; i < sizeof(tests)/sizeof(std::string); ++i) {
        std::cout << std::setw(8) << "'" + tests[i] + "'" << ": ";
        std::cout << is_a [is_numeric (tests[i])] << std::endl;
    }
}

Output:

      '': not a number
   'XYZ': not a number
   'a26': not a number
  '3.3a': not a number
  '42 a': not a number
   '764': is a number
' 132.0': is a number
  '930 ': is a number
查看更多
登录 后发表回答