/* Lecture code 16.3
 *
 * Code to compute the number of elements in a file less than a specified value
 * by using adaptable functions and a binder.
 */

#include <iostream>
#include <fstream>
#include <algorithm>
#include <iterator>
#include <string>
#include <sstream>
#include <functional> // For bind2nd, ptr_fun
using namespace std;

/* Reads a line from the console and returns it. */
string GetLine()
{
	string result;
	getline(cin, result);
	return result;
}

/* Read an integer, prompting until the user enters valid data. */
int GetInteger()
{
	while(true)
	{
		stringstream converter;
		converter << GetLine(); // Read data and load into the stream.
		
		/* Try to read an int. */
		int result;
		converter >> result;
		
		/* If we read an int successfully, see if anything's left over. */
		if(!converter.fail())
		{
			/* Try to read a single char.  In class we used a string, but
			 * this approach works as well.
			 */
			char remaining;
			converter >> remaining;
			
			/* If the stream broke, we ran out of characters and are done. */
			if(converter.fail())
				return result;
			else
				cout << "Unexpected character: " << remaining << endl;
		}
		else
			cout << "Please enter an integer." << endl;
		
		cout << "Retry: ";
	}
}

bool LessThan(int x, int y)
{
	return x < y;
}

int main()
{
	cout << "Enter upper bound: ";
	const int maxValue = GetInteger();

	ifstream input("numbers.txt");
	cout << count_if(istream_iterator<int>(input), istream_iterator<int>(),
	                 bind2nd(ptr_fun(LessThan), maxValue)) << endl;
	
	/* NOTE: While we did not cover it in class, we could have also used the less<int>
	 * adaptable function that's part of the <functional> header.  The resulting code
	 * would look like this:
	 * cout << count_if(istream_iterator<int>(input), istream_iterator<int>(),
	 *                 bind2nd(less<int>(), maxValue)) << endl;
	 */

	return 0;
}