Want more features on Pastebin? Sign Up, it's FREE!
Guest

Untitled

By: a guest on Sep 7th, 2013  |  syntax: C++  |  size: 5.24 KB  |  views: 35  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /*
  2. * Safe input example:
  3. * If your compiler is not up to date for C++ 11, some of this stuff might not work for you.
  4. * If that's the case, try just the topmost example - this should work.
  5. */
  6.  
  7. #include <iostream>
  8.  
  9. template <class StreamIn> void SafeInput(StreamIn & Object,
  10.         std:: istream & InputStream = std:: cin) {
  11.         for ( ;; ) {
  12.                 if (InputStream >> Object) return;
  13.                 else {
  14.                         InputStream.clear();
  15.                         InputStream.ignore(std:: numeric_limits<std:: streamsize>:: max(), '\n');
  16.  
  17.                         std:: cerr << "Invalid input: try again.\n";
  18.                 }
  19.         }
  20. }
  21.  
  22. /*
  23. * As complicated as it looks, it isn't that bad to use.
  24. * You simply call the function as you would any other, but you specify the type of the first
  25. * parameter in angle brackets - look, here's an example:
  26. */
  27.  
  28. int main(int, char **) {
  29.         int A = 0;
  30.         std:: cout << "The current value of 'A' is: " << A;
  31.         std:: cout << "\nInput the new value of 'A': ";
  32.  
  33.         SafeInput<int> (A);
  34.  
  35.         std:: cout << "The new value of 'A' is " << A;
  36.        
  37.         return 0L;
  38. }
  39.  
  40. /*
  41. * Likewise, if 'A' was a 'char' instead, you would call 'SafeInput<char>(A);',
  42. * and the same for any type that you can get input for with std:: cin.
  43. */
  44.  
  45. /*
  46. * That's not too bad-  copy all the above and compile to try it out yourself.
  47. * You should not be able to crash your program with input, and it should rather reset and prompt
  48. * the user again.
  49. *
  50. * What happens is this:
  51. * 1: Prompt the user for input.
  52. * 2: If the fail bit of std:: cin was not set, (called InputStream in this function),
  53. *        break and return.
  54. * 3: Else, reset the stream of all errors, and ignore.
  55. * 4: Print an error message, and repeat.
  56. *
  57. * But we can make it better.
  58. * This works great for some basic stuff, but what if you have some sort of restriction
  59. * on your input, as is commonly the case?
  60. * We can use a neat function of the new C++11 standard, called lambdas to supply a predicate
  61. * to test whether the input is okay, inline.
  62. * See:
  63.  
  64.   http://en.cppreference.com/w/cpp/language/lambda
  65.  
  66. *
  67. * Note: Syntax might get ugly here, don't worry. Even when we're done, it's still shorter
  68. * than the alternative, which is typing out the entire function SafeInput inline with the
  69. * predicate enclosed.
  70. */
  71.  
  72. /*
  73. * We need to add another include this time - this will offer us a bit more flexibility in how we
  74. * use this feature.
  75. */
  76.  
  77. #include <functional>
  78. #include <iostream>
  79.  
  80. template <class StreamIn> void SafeInput(StreamIn & Object, std:: function<bool(const StreamIn &)>
  81.         Predicate = nullptr, std:: istream & InputStream = std:: cin) {
  82.         for ( ;; ) {
  83.                 if (InputStream >> Object) {
  84.                         if (Predicate == nullptr) {
  85.                                 return;
  86.                         } else if(Predicate(Object) ) {
  87.                                 return;
  88.                 } else {
  89.                         InputStream.clear();
  90.                         InputStream.ignore(std:: numeric_limits<std:: streamsize>:: max(), '\n');
  91.  
  92.                         std:: cerr << "Invalid input: try again.\n";
  93.                 }
  94.         }
  95. }
  96.  
  97. int main(int, char **) {
  98.         int A = 0;
  99.         std:: cout << "The current value of 'A' is: " << A;
  100.         std:: cout << "\nInput the new value of 'A': ";
  101.  
  102.         SafeInput<int> (A, [](const int A){
  103.                 return (A <= 100 && A >= 0)? true: false;
  104.                                                                           } );
  105.  
  106.         std:: cout << "The new value of 'A' is " << A;
  107.        
  108.         return 0L;
  109. }
  110.  
  111. /*
  112. * In this case, we demonstrate the power of such a construct by letting us constrain input to the
  113. * values in the interval [0, 100].
  114. * You can alter the predicate function to evaluate anything, as long as the value returned
  115. * is boolean. If you need to read external state, you can do that. mention the name in the lambda
  116. * and capture by value:
  117. * int y = 25;
  118. * SafeInput <int> (a, [=](const int a) {
  119. *       return A <= y? true: false;
  120. *                                                                          } );
  121. */
  122.  
  123. /*
  124. * Don't be intimidated by the syntax, especially if you've never seen these features before.
  125. * The function accomplishes something rather trivial: get input and make sure that it meets some
  126. * restriction.
  127. * It works like this:
  128. *
  129. * 1: Get the type of the data we want to input:
  130. *       SafeInput<int>
  131. * 2: Get the datum that we actually want to change
  132. *       SafeInput<int>(Value,
  133. * 3: Get a pointer to a function, functor or a "lambda function", since std:: function lets us
  134. *       use any, that returns a boolean and takes the type of the data we want to change as an argument.
  135. *       SafeInput<int>(Value, [](const int SomeName){ return true } );
  136. * 4: And close the function. The predicate (in this case always true) will be evaluated on each
  137. *       input, if it's provided. Since this one is constantly true, we could have just left it out.
  138. *       SafeInput<int>(Value);
  139. * 5: Test if input is okay - the stream is okay. Assuming it is, if and only if the predicate
  140. *       was supplied, evaluate that predicate and filer input based on that. If the predicate returns
  141. *       false,  than prompt the user again.
  142. * 6: If the stream isn't okay, prompt the user again.
  143. */
  144.  
  145. /*
  146. * You should be able to copy- paste this entire file into your compiler in two parts.
  147. * As ugly as this is, it's frankly more concise, readable, and safer than trying to validate
  148. * input inline. If you can't compile the second one, than trust me, it's your compiler!
  149. * Tested on GNU GCC 4.8.1, and the test version of the "Microsoft Visual C++ Compiler Nov 2012 CTP"
  150. * Feel free to use this subject to the terms of the Do What The Fuck You Want to Public License.
  151.  
  152.         http://www.wtfpl.net/
  153.        
  154. * Cheers.
  155. */
clone this paste RAW Paste Data