Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Safe input example:
- * If your compiler is not up to date for C++ 11, some of this stuff might not work for you.
- * If that's the case, try just the topmost example - this should work.
- */
- #include <iostream>
- template <class StreamIn> void SafeInput(StreamIn & Object,
- std:: istream & InputStream = std:: cin) {
- for ( ;; ) {
- if (InputStream >> Object) return;
- else {
- InputStream.clear();
- InputStream.ignore(std:: numeric_limits<std:: streamsize>:: max(), '\n');
- std:: cerr << "Invalid input: try again.\n";
- }
- }
- }
- /*
- * As complicated as it looks, it isn't that bad to use.
- * You simply call the function as you would any other, but you specify the type of the first
- * parameter in angle brackets - look, here's an example:
- */
- int main(int, char **) {
- int A = 0;
- std:: cout << "The current value of 'A' is: " << A;
- std:: cout << "\nInput the new value of 'A': ";
- SafeInput<int> (A);
- std:: cout << "The new value of 'A' is " << A;
- return 0L;
- }
- /*
- * Likewise, if 'A' was a 'char' instead, you would call 'SafeInput<char>(A);',
- * and the same for any type that you can get input for with std:: cin.
- */
- /*
- * That's not too bad- copy all the above and compile to try it out yourself.
- * You should not be able to crash your program with input, and it should rather reset and prompt
- * the user again.
- *
- * What happens is this:
- * 1: Prompt the user for input.
- * 2: If the fail bit of std:: cin was not set, (called InputStream in this function),
- * break and return.
- * 3: Else, reset the stream of all errors, and ignore.
- * 4: Print an error message, and repeat.
- *
- * But we can make it better.
- * This works great for some basic stuff, but what if you have some sort of restriction
- * on your input, as is commonly the case?
- * We can use a neat function of the new C++11 standard, called lambdas to supply a predicate
- * to test whether the input is okay, inline.
- * See:
- http://en.cppreference.com/w/cpp/language/lambda
- *
- * Note: Syntax might get ugly here, don't worry. Even when we're done, it's still shorter
- * than the alternative, which is typing out the entire function SafeInput inline with the
- * predicate enclosed.
- */
- /*
- * We need to add another include this time - this will offer us a bit more flexibility in how we
- * use this feature.
- */
- #include <functional>
- #include <iostream>
- template <class StreamIn> void SafeInput(StreamIn & Object, std:: function<bool(const StreamIn &)>
- Predicate = nullptr, std:: istream & InputStream = std:: cin) {
- for ( ;; ) {
- if (InputStream >> Object) {
- if (Predicate == nullptr) {
- return;
- } else if(Predicate(Object) ) {
- return;
- } else {
- InputStream.clear();
- InputStream.ignore(std:: numeric_limits<std:: streamsize>:: max(), '\n');
- std:: cerr << "Invalid input: try again.\n";
- }
- }
- }
- int main(int, char **) {
- int A = 0;
- std:: cout << "The current value of 'A' is: " << A;
- std:: cout << "\nInput the new value of 'A': ";
- SafeInput<int> (A, [](const int A){
- return (A <= 100 && A >= 0)? true: false;
- } );
- std:: cout << "The new value of 'A' is " << A;
- return 0L;
- }
- /*
- * In this case, we demonstrate the power of such a construct by letting us constrain input to the
- * values in the interval [0, 100].
- * You can alter the predicate function to evaluate anything, as long as the value returned
- * is boolean. If you need to read external state, you can do that. mention the name in the lambda
- * and capture by value:
- * int y = 25;
- * SafeInput <int> (a, [=](const int a) {
- * return A <= y? true: false;
- * } );
- */
- /*
- * Don't be intimidated by the syntax, especially if you've never seen these features before.
- * The function accomplishes something rather trivial: get input and make sure that it meets some
- * restriction.
- * It works like this:
- *
- * 1: Get the type of the data we want to input:
- * SafeInput<int>
- * 2: Get the datum that we actually want to change
- * SafeInput<int>(Value,
- * 3: Get a pointer to a function, functor or a "lambda function", since std:: function lets us
- * use any, that returns a boolean and takes the type of the data we want to change as an argument.
- * SafeInput<int>(Value, [](const int SomeName){ return true } );
- * 4: And close the function. The predicate (in this case always true) will be evaluated on each
- * input, if it's provided. Since this one is constantly true, we could have just left it out.
- * SafeInput<int>(Value);
- * 5: Test if input is okay - the stream is okay. Assuming it is, if and only if the predicate
- * was supplied, evaluate that predicate and filer input based on that. If the predicate returns
- * false, than prompt the user again.
- * 6: If the stream isn't okay, prompt the user again.
- */
- /*
- * You should be able to copy- paste this entire file into your compiler in two parts.
- * As ugly as this is, it's frankly more concise, readable, and safer than trying to validate
- * input inline. If you can't compile the second one, than trust me, it's your compiler!
- * Tested on GNU GCC 4.8.1, and the test version of the "Microsoft Visual C++ Compiler Nov 2012 CTP"
- * Feel free to use this subject to the terms of the Do What The Fuck You Want to Public License.
- http://www.wtfpl.net/
- * Cheers.
- */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement