views:

272

answers:

3

Hi

I'm using boost libs for c++ and the function lexical_cast behaves really weird. If I do lexical_cast("0.07513994") it works fine, but if I use my variable which I need to convert, it throws the bad_lexical_cast exception. Here is the code:

string word;
istringstream iss(line);
do
{
   string word;
   iss >> word;        
   double x;
   x = lexical_cast<double>(word);   
   cout << x << endl;
} while (iss);

What am I doing wrong here? I appreciate any help, thanks

+2  A: 

Your problem is probably that the loop is processed one more time than you expect. The last time through the loop, the read to word fails, setting the fail bit in iss, which is what while(iss) is checking. To fix it you need to do something like this.

string word;
istringstream iss(line);
do
{
   string word;
   iss >> word; 
   if(iss)
   {       
     double x;
     x = lexical_cast<double>(word);   
     cout << x << endl;
   }
} while (iss);
Michael Anderson
Thank you very much Michael
Student
Or get rid of the do-while loop, and use a simple while loop with `while(iss >> word) { ... }`. With this do-while loop, the condition is basically redundant.
Johannes Schaub - litb
Johannes solution is certainly neater. I just wanted to emphasise what was going wrong in the original post.
Michael Anderson
Why not do just `iss >> x`?
Billy ONeal
A: 

Unlike functions such as atof() which stop parsing as soon as they see an invalid character, lexical_cast requires that every character in the input string be valid. i.e. any leading or trailing spaces will cause it to throw an exception.

You want to see what kind of input it is getting and trim it accordingly. You should also catch bad_lexical_cast just in case it does get input which is completely garbage.

One possible solution is to use boos.regex or boost.xpressive to extract a valid sub-string and pass the result to lexical_cast.

Ferruccio
A: 

The problem is probably that you are sending an empty string when there is no data left.
You should change the loop you are using.

Use the while {} loop (not the 'do while' loop). This allows you to read from the stream and test it in a single easy to read statement. Note the result of iss >> word is the stream. When used in this boolean context it is tested to see if the state is good and its value converted into something that can be used by the while condition. Thus if the operator >> filed to work correctly then the loop is never entered.

istringstream iss(line);
string        word;
while(iss >> word)
{
    double x = lexical_cast<double>(word);   
    cout << x << endl;
}

But really you don't even need the lexical cast in this situation (unless you want to test for non numbers with an exception). The standard stream operator will convert the input into a double.

istringstream iss(line);
double        word;
while(iss >> word)
{
    cout << word << endl;
}
if (iss.fail())
{    /* Failure to convert input to a double */
}
Martin York