///////
//
// Student: Russell Lowke
//     T.F: Francis Crick
// Unit Three, Hard Supplementary - question 15 [worth 7pts],  7/9/2002
//
//  (extra-credit problem)
//
//  thousand.txt has 1000 most frequently occuring words
//
//  user to choose one of the following options
//
//  1) How many words contain the letter: [c]
//  2) How many words contain exactly n letters: [n]
//  3) How many words contain at least one double letter?
//  4) How many words have the property that all their letters are in alphabetical order


#include <iostream>
#include <iomanip>
#include <fstream>
#include <cstring>


// constants
const int MAXSTR  = 80;							// max char string size

//
//  Get a string [str] of length maxLength
//  
void getString(char * query, char * str, int maxLength)
{
	cout << query;								// ask query
	
	cin >> ws;									// remove all the white spaces
	cin.getline(str, maxLength);				// read characters until \n MAXSTR
}


//
//  reads an integer from the keyboard,
//  uses error checking to ensure value is between minValue and maxValue
//
int getInt(char askStr[], int minValue, int maxValue)
{
	int mVar;
	bool inputOK = false;
	
	while (! inputOK) { 
	
		cout << askStr;						// ask query
		cin >> mVar;						// get input
		
		if ( (mVar >= minValue && mVar <= maxValue) )
			inputOK = true;					// input OK, exit loop
		else {
			cout << "Bad input: please enter a value between "
			     << minValue << " and " << maxValue << endl;
			cin.clear();					// clear error   cin.fail(); ??
			cin.ignore(80, '\n');			// empty buffer
		}
	}
	
	return mVar;
}


//
//   Analyzer class
//   analyzes files, counting number of small, large, and medium words
//
class WordCounter
{
	private :
	
		char *  pFileName;						// name of file being read
	   ifstream pInStream;						// in tream for file
		
      public:
       
		        WordCounter(char *filename); 	// constructor
		        ~WordCounter();					// destructor
       	int     openFile();						// open pFileName
       	int     readFile(char letter);			// read pFileName
       	int     readFileNLetters(int n);		// read for n letters
       	int 	readFileDblLetters();			// read for doubles
       	int 	readFileAlpha();				// read alpha order
       	int     closeFile();					// close pFileName
};


//
//  constructor for WordCounter class
//  
WordCounter :: WordCounter (char * fileName)
{
	pFileName    = fileName;
}


//
//  destructor for WordCounter class
//  
WordCounter :: ~WordCounter()
{
}


int WordCounter :: openFile()
{
	// open file		
	pInStream.open(pFileName);
	
	// ensure file exists
	if (pInStream == NULL) {					// file not found
	
		cout << pFileName << " -- Input file not found!\n";
		return -1;								// readFile failed
		
	} else {									// file OK
	
		pInStream.unsetf(ios::skipws);			// unset skip whitespace	
		
		return 0;								// readFile worked
	}
}


int WordCounter :: readFile(char letter)
{
	char c;
	bool hasLetter = false;
	int  wordCount = 0;
	
	do {
	
		pInStream >> c;							// read file
		
		if (c == letter) {						// letter matched
			hasLetter = true;
		}
		
		if ( c == '\n') {
		
			if ( hasLetter ) {					// count word
				wordCount++;
			}

			hasLetter = false;
		}
		
		cout << c;
		
	} while (! pInStream.eof() );
	
	cout << "words which contain the letter " << letter << " = " << wordCount << endl;
	
	return 0;
}


int WordCounter :: readFileNLetters(int n)
{
	char c;
	int letterCount = 0;
	int wordCount   = 0;
	
	do {
	
		pInStream >> c;							// read file
		letterCount++;
		
		switch(c)
		{
			case '\n':
				if (letterCount == n+1) {		// +1 for '/n'
					wordCount++;
				}
				letterCount = 0;
		}
		
		cout << c;
		
	} while (! pInStream.eof() );
	
	cout << "words with " << n << " letters = " << wordCount << endl;
	
	return 0;
}


int WordCounter :: readFileDblLetters()
{
	char c, prev = '\0';
	int wordCount = 0;
	
	do {
		prev = c;								// save previous ltter
		pInStream >> c;							// read c
		
		if (c == prev && c != '\n') {			// test if c == last char
			wordCount++;
		}
		
		cout << c;
		
	} while (! pInStream.eof() );
	
	cout << "Words with double letter = " << wordCount << endl;
	
	return 0;
}


int WordCounter :: readFileAlpha()
{
	char c, prev  = '\0';
	int letterCount = 0, wordsInAlpha = 0;
	bool inOrder  = true;
	
	do {
		prev = c;								// save previous letter
		pInStream >> c;							// read c
		letterCount++;
		
		// cout << "   prev:" << (int) prev << " c:" << (int) c << " ";
		if ( ((int) prev > (int) c) && c != '\n') {
			inOrder = false;
		}
		
		if (c == '\n') {
			
			if (inOrder && letterCount != 1) {
				wordsInAlpha++;
				cout << " !! ";
			}
				
			inOrder = true;
			prev    = '\0';
			letterCount = 0;
		}
		
		cout << c;
		
	} while (! pInStream.eof() );
	
	cout << "Words with all letters in alphabetical order = " << wordsInAlpha << endl;
	
	return 0;
}


int WordCounter :: closeFile()
{
	pInStream.close();
	return 0;									// closeFile worked
}


//
//  ask for name of file to analyze
//  construct WordCounter object
//  read file and print data
//
void main()
{	
	int selection, n;
	WordCounter robot( "thousand.txt" );	    // construct WordCounter object
	char letter;
	
	cout << "Choose from the following:\n";
	cout << "   1) How many words contain a letter\n";
	cout << "   2) How many words contain exactly n letters\n";
	cout << "   3) How many words contain at least one double letter\n";
	cout << "   4) How many words have the property that \n";
	cout << "      all their letters are in alphabetical order\n";

	selection = getInt("Moke a selection: ", 1, 4);
	
	if ( robot.openFile() == 0 ) {		// read worked OK
		
		switch (selection)
		{
			case 1:						// How many words contain a letter
				cout << "How many words contain the character: ";
				cin >> letter;
				robot.readFile(letter);
				break;
			case 2:						// How many words contain exactly n letters
				n = getInt("How many words contain [n] letters: n = ", 1, 1000);
				robot.readFileNLetters(n);
				break;
			case 3:						// How many words contain at least one double letter
				robot.readFileDblLetters();
				break;
			case 4:						// How many letters are in alphabetical order
				robot.readFileAlpha();
				break;
		}
		
		robot.closeFile();
	}
	
	exit(0);
}
