views:

91

answers:

3

I have a string of class string

string str;

how can I check if it is a number or not, str can only have 3 possible types described below like

abcd

or a number like

123.4

or a number with a parenthesis attach to the end it for example

456)

note the parenthesis at the end of "str" is the only possible combination of number and none number

where the bottom two are considered valid numbers, I know I could use lexical_cast if only the first 2 cases occur, but how about considering all 3 possible cases to occur? I don't need to do anything fancy with str, I just need to know whether it is a valid number as I described

A: 

You have to define "number". There isn't a generic "number" type (for example, your first number is a double while the second is an integer).

That said, as shown in this answer, lexical_cast simply checks that the destination and only the destination exists:

template <typename R, typename T>
R lexical_cast(const T& pX)
{
    std::stringstream ss;
    ss << pX;

    R result;               // take out any whitespace, make sure nothing is left
    if ((ss >> result).fail() || !(ss >> std::ws).eof())
    {
        throw std::bad_cast();
    }

    return result;
}

So just make a new function:

template <typename R, typename T>
R weak_lexical_cast(const T& pX)
{
    std::stringstream ss;
    ss << pX;

    R result;
    if ((ss >> result).fail())
    {
        throw std::bad_cast();
    }

    return result;
}

It's basically a lexical_cast but doesn't care about any remaining characters (allowing your second number to work.)

GMan
A: 

maybe a regular expression would do the trick for you.

Randy
Despite the negative vote this isn't such a bad idea. Could you given an example?
mdma
A: 

The C++ solution for parsing strings manually is string streams. Put your string into a std::istringstream and read from that.

What you could do to parse this is to try to read an (unsigned) int from the string.
If this fails, it is a string not starting with digits.
If it works, peek at the next character. If that's a . you have a floating point number, if it's a ), you have an integer number. (Otherwise you have a reading error.)

Something along the lines of

void read(const std::string& str)
{
  std::istringstream iss(str);
  int i;
  if( !(iss>>i) ) {
    // str contains "abcd"
  } else {
    switch( iss.peek() ) {
      case ')': 
        // i contains '456'
        break;
      case '.' {
        double d;
        if( !(iss>>d) ) throw "dammit!";
        d += i;
        // d contains floating point value
        break;
      default: throw "what?!";
  }
  // ...
}

Does this make sense?

sbi