////////////////////////////////////////////////////////////////////////
// DEVELOPER	Patrick Riley Connor	[c1005205]					  //
// ASSIGNMENT	olab2												  //
// INSTRUCTOR	Dr. Al Cripps										  //
// COURSE		CSCI-2170-003										  //
// DUE DATE		Thursday, 2/4/2010									  //
////////////////////////////////////////////////////////////////////////

#include <iostream>			// General I/O libraries
#include <iomanip>			// Nice alignment of search results.
#include <fstream>			// File manipulation.

using namespace std;

/***** DEBUGGING PURPOSES, COMMENT OUT/REMOVE FOR FINAL PRODUCT *****/
/*
 const string DATA_FILE = "olab2.dat";				// Local file.
 const string SEARCH_FILE = "olab2_search.dat";		// Local file.
*/

// First two constants (string) define where to find our data and search
// files. Last constant (int) defines the upper bound of our data array.
const string DATA_FILE = "/nfshome/csal/public_html/spring.10/cs2170/public/olab2.dat";
const string SEARCH_FILE = "/nfshome/csal/public_html/spring.10/cs2170/public/olab2_search.dat";
const int MAX_NAMES = 100;

// Function prototypes for all functions. Documentation for functions
// located in function definitions.
void ReadNames (string dataArray[], ifstream& readFile, int& numRead);
void PrintNames (string dataArray[], int arraySize);
int SearchNames (string toFind, int startLocation, string dataArray[], 
				 int arraySize);

int main()
{
	ifstream 	dataRead,				// File to read name data.
				searchRead;				// File to read search data.
	int 		dataSize,				// Number of strings in data.
				location;				// Last location result at.
	string 		dataArray[MAX_NAMES],	// Array holding data from file.
				currentSearch;			// String being searched for.
	
	// Open our data file, and error/quit if the file open was not
	// successful.
	dataRead.open(DATA_FILE.c_str());
	if (!dataRead)
	{
		cerr << "Problem opening data file. Please check the file, "
			 << "and try again." << endl
			 << "File: " << DATA_FILE << endl;
		return -1;
	}
	
	// Read our names in from dataRead and place them in dataArray.
	ReadNames(dataArray, dataRead, dataSize);
	
	// Properly close our input data, as we have no further use for the
	// file now that its contents are stored in memory.
	dataRead.close();
	
	// Print out the data that was found.
	PrintNames(dataArray, dataSize);

	// Open our search file, and error/quit if the file open was not
	// successful.	
	searchRead.open(SEARCH_FILE.c_str());
	if (!searchRead)
	{
		cerr << "Problem opening search file. Please check the file, "
			 << "and try again." << endl
			 << "File: " << SEARCH_FILE << endl;
		return -1;
	}
	
	// Prepare a print heading for our search results.
	cout << endl << "Search results:" << endl;
	
	// Priming read, before we start scanning through our search file.
	searchRead >> currentSearch;
	
	while (searchRead)	// While there is another name to look for...
	{
		// Print out the string being searched for.
		cout << setw(15) << left << currentSearch;
		
		// Look for that string for the first time.
		location = SearchNames(currentSearch, 0, dataArray, dataSize);
		
		if (location == -1)			// If the string was not found,
			cout << "Not found";	// inform the user.
		else  						// If the string was found, print
			cout << "Position: ";	// out the header for the row.
			while (location != -1)	// Look until no other locations.
			{
				cout << location;	// Print most recent location found.
				
				// Look after previous location found for another
				// occurance of the same string.
				location = SearchNames(currentSearch, location + 1,
									   dataArray, dataSize);
				
				// If we found yet another one, append a comma to the
				// end of the most previous location printed.
				if (location != -1)
					cout << ", ";
			}
		cout << endl;		// New line in preparation for more data.
		
		// Read in another possibility to search for. If we come to the
		// end of this file, then our while loop will shut down.
		searchRead >> currentSearch;
	}		
	
	// Properly close our search file.
	searchRead.close();
	
	// Successful exit.
	return 0;
}

void ReadNames (string dataArray[], ifstream& readFile, int& numRead)
{
	/*******************************************************************
	 * FUNCTION		ReadNames		void		Lines: 4
	 * PURPOSE		To read in name data from readFile and store into
	 *				dataArray[], while also counting the number of
	 *				entries found from readFile.
	 * PARAMETERS	dataArray[]		string
	 *					An array where our data is to be read into.
	 * 				readFile		ifstream, reference
	 * 					File where our data is to be read from.
	 * 				numRead			int, reference
	 * 					Number of entries read from our data file.
	 * EXECUTION	dataArray[] will fill up with data from readFile.
	 * 				numRead shows how many entries were read from our
	 * 				file.
	 ******************************************************************/
		
	// Priming read in first position, since we know that the file was
	// already successfully opened.
	readFile >> dataArray[0];
	
	// According to project specifications, we are not allowed to go
	// over MAX_NAMES entries in our array, so this loop will either
	// read up to MAX_NAMES entries from readFile.
	while (readFile && numRead < MAX_NAMES)
	{
		// Increment our counter of entries read. If, for whatever
		// reason, our priming read failed, there will be no number of
		// entries read. Likewise, this also allows for a simple way to
		// tell where to store our next array entry.
		numRead++;
		readFile >> dataArray[numRead];
	}
}

void PrintNames (string dataArray[], int arraySize)
{
	/*******************************************************************
	 * FUNCTION		PrintNames		void		Lines: 3
	 * PURPOSE		To display all data located in dataArray[], of size
	 * 				arraySize.
	 * PARAMETERS	dataArray[]		string
	 *					An array where our data is to be read from.
	 * 				arraySize		int
	 * 					Number of entries in dataArray[].
	 * EXECUTION	Each entry of dataArray[] will be printed on a new
	 * 				line.
	 ******************************************************************/

	// Print out a heading for our information.
	cout << "Names read: " << endl;
	
	// Print each entry from dataArray[], each on its own line.
	for (int i = 0; i < arraySize; i++)
		cout << dataArray[i] << endl;
}

int SearchNames (string toFind, int startLocation, string dataArray[], 
				 int arraySize)
{
	/*******************************************************************
	 * FUNCTION		SearchNames		int		Lines: 4
	 * PURPOSE		To scan through an array of strings, looking for the
	 * 				occurrence of a given string, starting any position
	 * 				in the array
	 * PARAMETERS	toFind			string
	 *					String to be searching for.
	 * 				startLocation	int
	 * 					Location to start looking from in the array.
	 * 				dataArray[]		string
	 * 					Array to be scanning, looking for toFind.
	 * 				arraySize		int
	 * 					Number of elements in dataArray[]
	 * EXECUTION	SearchNames will return the first occurrence of
	 * 				toFind in dataArray[], after the beginning location
	 * 				given by startLocation. If the string is not found,
	 * 				SearchNames will return -1.
	 ******************************************************************/
	
	// Look through all elements of our array, starting with the first
	// location given.
	for (int i = startLocation; i < arraySize; i++)
		if (toFind == dataArray[i])	// If we found an occurrence, return
			return i;				// it and exit the function.
	
	// If we were able to get out of the for loop without the function
	// prematurely quitting (meaning it found something), report that
	// nothing was found.
	return -1;
}
