input validation
What would be the best way to check if a number is between 1 and 3? Now I want to account for any situation such as the user could type a sentence, a large number, a character whatever and until it is a number between 1 and 3 it won't let it go through.
I'm assuming you're using C/C++.
Just make sure the string contains only digits and the period.
Then do an atof on the string and make sure the result is between 1 and 3.
Mike C.
http://www.coolgroups.com/zoomer/
Just make sure the string contains only digits and the period.
Then do an atof on the string and make sure the result is between 1 and 3.
Mike C.
http://www.coolgroups.com/zoomer/
Quote:Original post by Grahf750
What would be the best way to check if a number is between 1 and 3? Now I want to account for any situation such as the user could type a sentence, a large number, a character whatever and until it is a number between 1 and 3 it won't let it go through.
Quote:Original post by Grahf750
What would be the best way to check if a number is between 1 and 3? Now I want to account for any situation such as the user could type a sentence, a large number, a character whatever and until it is a number between 1 and 3 it won't let it go through.
Strongly recommend that you separate this into two steps: check it's a number, and then check that the number is in range. With the normal C++ formatted (text) IO (i.e. using operator>> on an input stream), reading in to an integer-typed value "fails" if the data is invalid; to continue reading, you must "reset" the stream, and then you generally want to skip past that data by "ignore"ing it.
More information here, but basically a general-purpose solution looks like (this is off the top of my head):
// Grab a value of type T from the input stream, which is between low and high// (inclusive). Skip to the next line of data upon failure.template <typename T>T getValue(const istream& is, const T& low, const T& high) { T result; // Until we can read in a T, and it's in range... while(!(is >> result && result >= low && result <= high)) { // Until that's true (i.e. while it's false), we have an error, so handle it // One pathological case is "end of input" with nothing valid // We'll throw an exception in that case. if (is.eof()) { throw exception("No valid value before end of input"); } is.clear(); // Skip past arbitrarily many characters (we ask the standard library for // a number that represents "the greatest possible size of a stream"), up // until a '\n' occurs. is.ignore(numeric_limits<streamsize>::max(), '\n'); } return result;}
Or, a variation:
// This time, the input will always be grabbed a line at a time, and we will// only accept a line which begins with a valid value and has no more data// after that (except possibly some trailing whitespace).template <typename T>T getValue(const istream& is, const T& low, const T& high) { string line; // will hold successive lines from the stream. // Read lines until we are successful or it is no longer possible to read. while(getline(is, line)) { T candidate; // possible result. char garbageHolder; // Parse the line into a temporary, then whitespace, then a character. // If we were able to read the character, then there is garbage after our // item, and we reject the line. Of course we must reject it right away // if we can't read the T :) // To do the parsing, we load the line into a stringstream :) stringstream ss(line); if ((ss >> candidate) && !(ss >> ws >> garbageHolder) && // line has right stuff (candidate >= low) && (candidate <= high)) { // item is in range return candidate; // breaking out of the loop too, of course } // If it failed, we'll try again from scratch with the next line. // Thus there is no need for any resetting or ignoring, because getline() // always works as long as there is more input. } // If we get here, there are no more lines to read. throw exception("No valid value before end of input");}
You will need to include <iostream> (of course), <limits> (for the std::numeric_limits class and its max() function), <exception> (for std::exception), <string> (for std::string) and <sstream> (for std::stringstream); and indicate things that are in the std namespace where appropriate (either qualify them with std:: in the code given, or use appropriate 'using' statements).
As an exercise, modify these:
i) so that they always use cin for input, and remove the istream parameter (since it will no longer be needed);
ii) so that they accept a 'const std::string& prompt' parameter, which is a prompt for input, and outputs this to cout before each attempt to grab input.
The same applies for console input as for files. std::cin behaves like a file in many respects, so it's no great hassle to remove the file openning code and just stream the data directly from cin as you would with normal console input :-)
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement