0

I'm completely new to coding, so please keep this in mind before commenting.

So I've been trying to get into coding for a while, and today I went to the library and picked up a book called "programming in c++". I've written some basic programs, but I have gotten stuck at one point, I have no idea how to create a function that makes sure that when the user is prompted for a double, what they enter is valid. (If the user enters a character like 'k', the program just breaks). I searched here and on the net, and there are some answers, but they are more along the line of "here's a line of code that works, insert x, y, z, into it". And I don't have enough experience to know what to do. So here is a sample that is a mix of code from another question, and me failing to try to make it work in my program:

#include <iostream>
#include <stdio.h>


using namespace std;

double GetDouble () {
    double x;
    cin >> x;
    int valid = 0;
    while (valid == 0) {
        if (x == double) {
      return x;
      break;
  } else if (x != double) {
      cout << "Invalid Input! Please input a numerical value." << endl;
      cin.clear();
      while (cin.get() != '\n') ; // empty loop
    }
}
return x;
}

Now what I want it to do is to use "cin << x" to get a user input for x, and then make sure that x is a double, and I'm failing quite hard at this. If someone could explain this to in a manner that clarifies each operation, I would be truly grateful. For example, I don't know what the break function does, and what the cin.clear(), and cin.get() do. (I know this is a duplicate, but the answers on the other question does not at all address what I'm confused about, thank you for taking time to read & answer this! :)

Paw
  • 3
  • 1
  • 2
  • 3
    Out of curiosity, where did you get this code from? (I'm implying you should learn C++ using a book) – Luchian Grigore Jul 19 '13 at 16:22
  • Check `cin.good()` after `cin >> x;`. Then you can `cin.clear()` and `cin.ignore(1000, '\n')` to clear flags and empty buffer respectively if you like. –  Jul 19 '13 at 16:25
  • Hi Luchian Grigore! The original code was from http://stackoverflow.com/questions/3273993/how-do-i-validate-user-input-as-a-double-in-c?rq=1 cassablancas answer I do believe. (I did indeed search around first, but as I said, it was to little help), and the messed up version of it is what you see on top of this thread after I tried to make sense of it :) – Paw Jul 19 '13 at 17:36

4 Answers4

2

This seems a close analog to your code that (mostly) works:

double GetDouble () {
    double x;
    cin >> x;
    // ver1: while( cin.fail() ) // or !cin.good()   no trailing char check.
    while( cin.fail() || (cin.peek() != '\r' && cin.peek() != '\n'))
    {
        cout << "Invalid Input! Please input a numerical value." << endl;
        cin.clear();
        while( cin.get() != '\n' ); // or cin.ignore(1000, '\n');
        cin >> x;
    }
    return x;
}
  • 1
    I cant post long answers here, but I wrote a piece of code that does the same thing as yours, (I also tried your code to make sure), and both have the flaw that if the user enters something valid with something that is not valid tucked on at the end i.e. "123.45k" it still goes through and it just chops off the end part (k in this case), how can I still make it give and error message and re prompt for input? Thanks for all the help guys, it helps a ton! – Paw Jul 19 '13 at 17:33
  • @Paw good question, I've now updated the answer with (hopefully) an improvement. –  Jul 19 '13 at 19:14
  • This works (found no flaws in it so far at least), thank you so much! – Paw Jul 20 '13 at 09:47
1

First of all, double is a keyword so you don't need to use it in a conditional statement. Secondly, you can use the cin>>x in a while loop and then process x , a sample code is given below:

    while(cin>>x)
     {
       //process
     }

whenever you use anything in a while statement, it first checks it's validity. if for example user enters a character the condition will evaluate to false and you can then tell this to the user. In this way you can run the loop till the time user enters correct input. As for the function of break keyword, it gets you out of a loop, for ex

    for(int i=10; i>0; i++)
    {
       // do something
    }

will keep on running forever, but suppose you rewrite the code as:

    for(int i=10; i>0; i++)
    {
      if(i==15)
      break ;
    }

the loop will end as soon as the value of i reaches 15

  • Note: `if( cin )` is just shorthand for `if( !cin.fail() )`. Similarly, `cin >> x; if( cin )` is the long form of `if( cin >> x)` since operator >> returns the left-hand stream object to allow chaining. –  Jul 19 '13 at 16:34
  • 1
    Also, `for(int i=10; i>0; i++)` will only run 32 thousand, or 2 billion or 9 Quintillion iterations or so depending on architecture. Typically it'll be 2 billion which might take 5 seconds on a modern CPU. –  Jul 19 '13 at 16:54
0

Something like so:

double getDouble(const string& askMessage = "Please Enter a number: ",const string& errorMessage = "Please enter a valid number: ", const int numberOfTrials = 10){
 double userInput = 0.0;
 bool isValidInput = false;
 int trials = 0;
 do{
    cout << endl << askMessage;
    if(cin >> input) break;
    else{ 
      cin.clear(); //EDIT thanks ebyrob, forgot about this.
      std::cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
      std::cout << errorMessage;
    }

 }while(!isValidInput || trials < numberOfTrials);

 return userInput;
}

use it like so

const double d1 = getDouble();
const double d2 = getDouble("Please Enter a number: ", "Error! Enter a valid number: ", 1000);
dchhetri
  • 6,926
  • 4
  • 43
  • 56
  • No `cin.clear()`? This just loops wildly on the first invalid input. Also, the `do...while()` is effectively `while(true)`. –  Jul 19 '13 at 19:54
  • Needs to come before `cin.ignore()`. –  Jul 19 '13 at 21:53
  • This does not compile for me, gives me an error stating that 'input' was not declared in this scope in the "if(cin >> input) break;" part. What I think you meant was to write "userInput" instead, but it still does not compile, there is an error at the "std::cin.igrone(std::numeric_limits::max(),'\n');" Here it tells me that numeric_limits is not a member of 'std'. I'm including the libraries "iostream", and "stdio.h", do I need another? Thank you very much for helping. :) Also: can you tell me what :: does? – Paw Jul 20 '13 at 09:25
-1

Break breaks out of a loop (in this case, a while) cin.clear() clears the cin buffer of all chars. cin.get() gets a single character from cin (probably standard in).

Jiminion
  • 5,080
  • 1
  • 31
  • 54
  • 1
    Last I checked `cin.clear()` only cleared flags. Perhaps you're thinking of `cin.ignore()`? –  Jul 19 '13 at 16:25