-3

I am getting input as a float. For example if the user is entering in 3.5 then it works fine. If user enters in 3.X or any other characters it is causing an infinite loop. is there any way in which i can validate the variable so that user can enter only numbers? I am using gcc compiler.

mmmmmm
  • 30,723
  • 26
  • 85
  • 109

5 Answers5

2

The usual way is to read the data as a string, then convert it to a float, and see of the entire input string was consumed in that conversion. Boost lexical_cast (for one example) can automate most of that for you.

Jerry Coffin
  • 437,173
  • 71
  • 570
  • 1,035
  • which header file i need to add to use this code? will it work in gcc? – srinathmkce Mar 01 '12 at 19:34
  • `boost/lexical_cast.hpp`. Yes it works with gcc. If you don't have Boost you can download from boost.org. You can also get pre-built libraries for Windows from [boostpro Computing](http://www.boostpro.com/download/). – Jerry Coffin Mar 01 '12 at 19:39
1

You don't give any sample code, so we can see what you're doing, but I suspect from the symptoms that you're doing something like:

while ( ! input.eof() ) {
    double d;
    input >> d;
    //  do someting with d...
}

There are two problems with this: the first is that once an error occurs (because 'X' cannot be part of a double), the stream memorizes the error until it is explicitly cleared, so all following input also fails (and no further characters are extracted from the string). When you have a format error in a stream, it is necessary to reset the error state before continuing.

The second problem with the above is that input.eof() doesn't mean much until after input has failed; it's not a very useful function. What you probably want to do is:

double d;
while ( input >> d ) {
    //  do something with d
}

This will stop reading on the first error. If you want to recover from errors and continue, then you need something more elaborate:

double d;
while ( input >> d || !input.eof() ) {
    if ( input ) {
        //  do something with d...
    } else {
        //  format error...
        input.clear();      //  reset the error state...
        //  advance the stream beyond the error:
        //  read to next white space (or EOF), or at least
        //  advance one character.
    }
}

Alternatively, it's often more robust to do as others have suggested, read the input line by line, then scan the line:

std::string line;
while ( std::getline( input, line ) ) {
    std::istringstream l( line );
    double d;
    if ( l >> d >> std::ws && d.get() == EOF ) {
        //  do something with d...
    } else {
        //  format error...
        //  we don't have to clear or skip ahead, because we're
        //  going to throw out the istringstream anyway, and the
        //  error didn't occur in the input stream.
    }
}

This imposes a much more rigorous format: one value per line, but if you count the lines, you can output the line number in the error message; the person who has to correct the bad input will appreciate that.

James Kanze
  • 142,482
  • 15
  • 169
  • 310
0
try 
{
  double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }

from: How to determine if a string is a number with C++?

Community
  • 1
  • 1
neciu
  • 3,979
  • 1
  • 21
  • 31
  • which header file i need to add to use this code? will it work in gcc? – srinathmkce Mar 01 '12 at 19:34
  • @srinathmkce, it will work with gcc. You need to use [Boost](http://www.boost.org/doc/libs/1_48_0/libs/math/doc/sf_and_dist/html/math_toolkit/utils/fp_facets/examples.html). – neciu Mar 01 '12 at 20:11
0

The best way for reading a double value from input and assuring it's well formed is reading the input as a string, and then parsing it using the standard strtod function included in the stdlib library.

For a more detailed explanation on some different possibilities when parsing that string you can check this other post.

Community
  • 1
  • 1
Win32
  • 1,059
  • 10
  • 12
0

Your post i somewhat unclear, but from what I understand, i think you should use strtof. Get your data from the user as String, than use the function to convert to float and check if succeeded by comparing the pointers.

for more info check the man pages for strtof.

SnapDragon
  • 1,246
  • 2
  • 16
  • 31
  • will this function work in gcc complier? – srinathmkce Mar 01 '12 at 19:35
  • Yes it will, here's the man page [link](http://linux.die.net/man/3/strtof) – SnapDragon Mar 01 '12 at 19:52
  • #include #include using namespace std; int main() { string a; cin>>a; float v=strtof(a.c_str(),NULL); cout< – srinathmkce Mar 01 '12 at 20:09
  • What does the error says? You really should be more verbose. – SnapDragon Mar 01 '12 at 20:25
  • /tmp/cc3vq32Q.o: In function `main': test1.cpp:(.text+0x12): undefined reference to `std::basic_string, std::allocator >::basic_string()' – srinathmkce Mar 01 '12 at 20:28
  • test1.cpp:(.text+0x21): undefined reference to `std::cin' test1.cpp:(.text+0x26): undefined reference to `std::basic_istream >& std::operator>>, std::allocator >(std::basic_istream >&, std::basic_string, std::allocator >&)' test1.cpp:(.text+0x32): undefined reference to `std::basic_string, std::allocator >::c_str() const' – srinathmkce Mar 01 '12 at 20:30
  • sorry, its too big.. i couldnt understand the error . – srinathmkce Mar 01 '12 at 20:31