Multihunters Analysis tool v0.8

From Planetarion Wiki
Jump to navigationJump to search

This is the oldest existing code for the Multihunters Analysis tool. It was written in c++ and is somewhat primitive, It worked directly from files and as such was rather slow. It uses an array to store the planet data, and as such is susceptable to a buffer overflow. This was mitigated by making the array stupidly large - at the cost of memory usage.

This version of the analysis tool included an opinion function for the tool to determine guilt or innocence. Subsequent versions deliberately did not include this since guilt is subjective and is best determined by a human rather then a tool.

This version has not been in use since r11.


Multiscan.cpp

//
// Includes
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include "tokens.h"
#include <math.h>
#include "dataclass.h"
#include "tickcalcclass.h"
#include "statsclass.h"

//
using namespace std;

// Prototypes
void FileCompaire(char* file1,char* file2);
void LineCompaire(string line1,string line2,string P1,string P2);
void Report(string text);
void QuickScan(int array1,int array2,string file1, string file2);
void FileParse(char* file,int array);

//
// Globals
//
string type1 = "None";
string type2 = "None";
string temp;
string filename = "Report.txt";
string rating = "";
string lastline1 = "";
string lastline2 = "";

int count = 1;
int timeforcheck = 10;
int timeforcheck2 = 5;
int timeforcheck3 = 1;
int timeforlaunch = 3;
int rating1 = 50;
int rating2 = 100;
int rating3 = 150;
int rating4 = 200;
long unsigned int Dodgyrating = 0;
long unsigned int Linesanalysed = 0;
int magiccount = 0;

bool UseQuick = false;
bool UseSilent = false;

DataArray PlanetData;


//
// Main Procedure
int main(int argc, char* argv[])
{
	int start = 1;
	cout << "Multihunter Scan tool V0.8 Coded by Phil^\n";
	cout << "=========================================\n";
	// handle custom params
	// NO error checking for the param data
	// introduced a while loop to scan the params so they dont have to be in any order
// its - 2 since theres GOT to be at least 2 files to compaire
	while ( count <= ( argc - 2 ) ) {
	temp = Gettok(argv[count],1," ");
		if (( temp == "-?" ) || ( temp == "/?" )) {
		// Help File
		cout << "Command Line Switches : \n\n";
		cout << "Login Time Parameters : -l x y z\n";
		cout << "x = Time ( in mins ) to flag for 1 point\n" ;
		cout << "y = Time ( in mins ) to flag for 2 points\n" ;
		cout << "z = Time ( in mins ) to flag for 3 points\n\n";
		cout << "Fleet Launch Parameters : -f x\n";
		cout << "x = Ticks within fleet launches to flag for 1 point\n";
		cout << "Launches on the same tick will gain a further point\n";
		cout << "Launches on the same target will gain a further point\n\n";
		cout << "Output File Parameters : -o Filename\n";
		cout << "Filename must have no spaces or directories in it\n\n";
		cout << "Rating Parameters : -r a b c d\n";
		cout << "a = Average rating for Innocent\n";
		cout << "b = Average rating for Interesting\n";
		cout << "c = Average rating for Suspicious\n";
		cout << "d = Average rating for Guilty\n";
		system("PAUSE");
		return 0;
	}
	if ( temp == "-q" ) {
		UseQuick = true;
		start = start + 1;
		cout << "Quickscan option selected ( EXPERIMENTAL )\n";
	}
	if ( temp == "-s" ) {
		UseSilent = true;
		cout << "Silent option detected. Correlations will not be shown\n";
		start = start + 1;
	}
	if ( temp == "-l" ) {
		// Login Time Parameters 
		timeforcheck = atoi(argv[start + 1]);
		timeforcheck2 = atoi(argv[start + 2]);
		timeforcheck3 = atoi(argv[start + 3]);
		start = start + 4;
		cout << "Time for +1 points set to : " << timeforcheck << " Minutes\n" ;
		cout << "Time for +2 points set to : " << timeforcheck2 << " Minutes\n" ;
		cout << "Time for +3 points set to : " << timeforcheck3 << " Minutes\n";
	}

	if ( temp == "-f" ) {
		// Fleet Launch Parameters
		timeforlaunch = atoi(argv[start + 1]);
		start = start + 2;
		cout << "Tick difference for +1 points set to : " << timeforlaunch << " Ticks\n";
	}

	if ( temp == "-o" ) {
		// Output Filename Params
		filename = argv[count + 1];
		start = start + 2;
		cout << "Output filename selected to be " << filename << endl;
	}
	if ( temp == "-r" ) {
		// Rating Parameters
		rating1 = atoi(argv[count + 1]);
		rating2 = atoi(argv[count + 2]);
		rating3 = atoi(argv[count + 3]);
		rating4 = atoi(argv[count + 4]);
		start = start + 5;
		cout << "Rating Parameters selected to be :" << endl;
		cout << "Innocent : Less then " << rating1 << endl;
		cout << "Interesting : Between " << rating1 << " and " << rating2 << endl;
		cout << "Questionable : Between " << rating2 << " and " << rating3 << endl;
		cout << "Suspicious : Between " << rating3 << " and " << rating4 << endl;
		cout << "Guilty : Over " << rating4 << endl;
	}
	if ( temp == "-" ) {
		// Picks up dodgy params
		cout << "Invalid Parameters\n";
		system("Pause");
		return 0;
	}
	count++;
}
	if ( argc <= 2 ) { cout << "Insufficient Parameters\n"; return 1; }

	system("pause");
	cout << "Beginning Report...\n";
	Report("Multihunter Scan tool V0.8 Coded by Phil^\nBeginning Report\n");
	PlanetData.arrayitems = ( argc - start ) ;
	int k = 1;
	for (int i=start; i<argc; i++) {
		for (int j = i + 1; j<argc; j++) {
			// If Not using quick method
			if ( UseQuick == false ) {
				FileCompaire(argv[i],argv[j]);
				magiccount++;
			}
		}
		// If using quick method - parse files first and use dedicated combo checker later
		if ( UseQuick == true ) { 
			FileParse(argv[i],k); 
			k++;
		}
	}
	if ( UseQuick == true ) {
		int files = PlanetData.arrayitems;
		for (i = 1;i<=files;i++) {
			for (int j = i + 1;j<=files;j++) {
				QuickScan(i,j,PlanetData.Readdata(i,0),PlanetData.Readdata(j,0));
			}
		}
	}
	Report("Complete\n\n\n\n");
	// Calculate Rating
	if ((Dodgyrating / magiccount) <= rating1 ) { rating = "Innocent"; }
	if ( ( (Dodgyrating / magiccount) <= rating2 ) && ( (Dodgyrating / magiccount) > rating1 ) ) { rating = "Interesting"; }
	if ( ( (Dodgyrating / magiccount) <= rating3 ) && ( (Dodgyrating / magiccount) > rating2 ) ) { rating = "Questionable"; }
	if ( ( (Dodgyrating / magiccount) <= rating4 ) && ( (Dodgyrating / magiccount) > rating3 ) ) { rating = "Suspicious"; }
	if (( Dodgyrating / magiccount ) >= rating4 ) { rating = "Guilty"; }
	float Arating = ( Dodgyrating / magiccount );
	cout << "Operation Complete. " << filename << " Generated\n";
	cout << "Total Dodgy points : " << Dodgyrating << endl;
	cout << "Lines Analysed : " << Linesanalysed << endl;
	cout << "Combinations Analysed : " << magiccount << endl;
	cout << "Average Rating per Combination Analysed : " << Arating << endl;
	cout << "Program Opinion of Case : " << rating << endl;
	char* temp2 = "";
	// Write Report to the file
	Report("Total Dodgy Points : ");
	Report(itoa(Dodgyrating,temp2,10));
	Report("\n");
	Report("Lines Analysed : ");
	Report(itoa(Linesanalysed,temp2,10));
	Report("\n");
	Report("Combinations Analysed : ");
	Report(itoa(magiccount, temp2,10));
	Report("\n");
	Report("Average Rating per Combination Analysed : ");
	Report(itoa(Arating,temp2,10));
	Report("\n");
	Report("Total Dodgy Points : ");
	Report(itoa(Dodgyrating,temp2,10));
	Report("\n\n");
	Report("Program Opinion of Case : ");
	Report(rating);
	Report("\n");

	// Write Parameter info to the file
	Report("\n\n\nParameters Used for this investigation\n");
	Report("======================================\n");
	Report("Login Difference for +1 point: ");
	Report(itoa(timeforcheck,temp2,10));
	Report(" Minutes\n");
	Report("Login Difference for +2 points: ");
	Report(itoa(timeforcheck2,temp2,10));
	Report(" Minutes\n");
	Report("Login Difference for +3 points: ");
	Report(itoa(timeforcheck3,temp2,10));
	Report(" Minutes\n");
	Report("Tick difference between launches for +1 point: ");
	Report(itoa(timeforlaunch,temp2,10));
	Report(" Ticks\n");
	Report("Average dodgy rating per combination required for :\n");
	Report("Innocent : Less than ");
	Report(itoa(rating1,temp2,10));
	Report("\n");
	Report("Interesting : More than ");
	Report(itoa(rating1,temp2,10));
	Report(" and less than ");
	Report(itoa(rating2,temp2,10));
	Report("\n");
	Report("Questionable : More than ");
	Report(itoa(rating2,temp2,10));
	Report(" and less than ");
	Report(itoa(rating3,temp2,10));
	Report("\n");
	Report("Suspicious : More than ");
	Report(itoa(rating3,temp2,10));
	Report(" and less than ");
	Report(itoa(rating4,temp2,10));
	Report("\n");
	Report("Guilty : More than ");
	Report(itoa(rating4,temp2,10));
	Report("\n");
	system("pause");
	return 0;
}


// Sub Procedures
void FileParse(char* file, int array) {
	ifstream file_in(file);
	char fline[1000];
	long int linecounter = 1;
	PlanetData.Savedata(array,0,file);
	while (file_in.getline(fline,1000)) {
		PlanetData.Savedata(array,linecounter,fline);
		linecounter++;
		string temp = fline;
	}
	PlanetData.arraysizes[array] = linecounter;
}

void QuickScan(int array1,int array2,string file1, string file2) {
	magiccount++;
	cout << "Compairing " << file1 << " and " << file2 << "\n";
	cout << "====================================================\n";
	Report("Planets being Compaired : ");
	Report(file1);
	Report(" and " );
	Report(file2);
	Report("\n");
	Report("=====================================================\n");
	int lines1 = PlanetData.arraysizes[array1];
	int lines2 = PlanetData.arraysizes[array2];
	string fline1 = "";
	string fline2 = "";
	lastline1 = " ";
	lastline2 = " ";
	int k = 1 , l = 1;
	int skipto = 1;
	while ( k <= lines1 ) {
		fline1 = PlanetData.Readdata(array1,k);

		// Cut down on Duplicates
		while ( fline1 == lastline1 ) { 
			k++;
			fline1 = PlanetData.Readdata(array1,k);
		}
		

		string tok11 = Gettok(fline1,1," ");
		string tok12 = Gettok(fline1,2," ");
		if ( tok11 == "Time") {
			if (tok12 == "Trans_id") {
				type1 = "None";
			}
			if (tok12 == "IP") { 
				type1 = "Login";
				k++;
				fline1 = PlanetData.Readdata(array1,k);
			}
		}
		if (tok11 == "Fleet") { 
			type1 = "Fleet";
			k++;
			fline1 = PlanetData.Readdata(array1,k);
		}
		if (tok11 == "No") { type1 = "None"; }
		if (tok11 == "MOTD") { type1 = "None";  }
		if (tok11 == "LAUNCHES") { 
			type1 = "None";
		}
		if (tok11 == "Login") { 
			type1 = "None";
		}
		while ( l <= lines2 ) {
			fline2 = PlanetData.Readdata(array2,l);
			// Cut down on duplicates
			while ( fline2 == lastline2 ) { 
				l++;
				fline2 = PlanetData.Readdata(array2,l);
			}
			string tok21 = Gettok(fline2,1," ");
			string tok22 = Gettok(fline2,2," ");
			if (tok21 == "Time") {
				if (tok22 == "Trans_id") {
					type2 = "None";
				}
				if (tok22 == "IP") { 
					type2 = "Login";
					l++;
					fline2 = PlanetData.Readdata(array2,l);
				}
			}
			if (tok21 == "Fleet") {
				type2 = "Fleet";
				l++;
				fline2 = PlanetData.Readdata(array2,l);
			}
			if (tok21 == "No") { type2 = "None";  }
			if (tok21 == "MOTD") { type2 = "None"; }
			if (tok21 == "LAUNCHES") { 
				type2 = "None";
			}
			if (tok21 == "Login") { 
				type2 = "None";
			}
			LineCompaire(fline1,fline2,file1,file2);
			lastline1 = fline1;
			lastline2 = fline2;
			l++;

		}
		k++;
		l = skipto;
	}	
}

void FileCompaire(char* file1,char* file2) {
	long int filepointer = 0;
	// procedure for compairing files
	cout << "Compairing " << file1 << " and " << file2 << "\n";
	cout << "====================================================\n";
	Report("Planets being Compaired : ");
	Report(file1);
	Report(" and " );
	Report(file2);
	Report("\n");
	Report("=====================================================\n");
	string P1 = file1;
	string P2 = file2;
	ifstream file1_in(file1);
	char fline1[1000];
	char fline2[1000];

	while (file1_in.getline(fline1,1000)) {
		// cut down on duplicates
		while ( fline1 == lastline1 ) { 
			file1_in.getline(fline1,1000);
		}

	ifstream file2_in(file2);
	string tok11 = Gettok(fline1,1," ");
	string tok12 = Gettok(fline1,2," ");
	if (tok11 == "Time") {
		if (tok12 == "Trans_id") {
		type1 = "None";
	}
		if (tok12 == "IP") { 
			type1 = "Login";
			file1_in.getline(fline2,1000);
		}
	}
	if (tok11 == "Fleet") { 
		type1 = "Fleet";
		file1_in.getline(fline1,1000);
	}
	if (tok11 == "No") { type1 = "None"; }
	if (tok11 == "MOTD") { type1 = "None";  }
	if (tok11 == "LAUNCHES") { 
		type1 = "None";
	}
	if (tok11 == "Login") { 
		type1 = "None";
	}
	while (file2_in.getline(fline2,1000)) {
		while ( fline2 == lastline2 ) { 
			file2_in.getline(fline2,1000);
		}

		string tok21 = Gettok(fline2,1," ");
		string tok22 = Gettok(fline2,2," ");
		if (tok21 == "Time") {
			if (tok22 == "Trans_id") {
				type2 = "None";
			}
			if (tok22 == "IP") { 
				type2 = "Login";
				file2_in.getline(fline2,1000);
			}
		}
		if (tok21 == "Fleet") {
			type2 = "Fleet";
			file2_in.getline(fline2,1000);

		}
		if (tok21 == "No") { type2 = "None";  }
		if (tok21 == "MOTD") { type2 = "None"; }
		if (tok21 == "LAUNCHES") { 
			type2 = "None";
		}
		if (tok21 == "Login") { 
			type2 = "None";
		}
		
		LineCompaire(fline1,fline2,P1,P2);
		lastline1 = fline1;
		lastline2 = fline2;
	}
	file2_in.close();
	}
	file1_in.close();
cout << "\nComplete\n\n";
}

//
void LineCompaire(string line1,string line2,string P1,string P2) {
	bool guilty = false;
	Linesanalysed++;

//
// For FLEET data
//
	if ((type1 == "Fleet" ) && (type2 == "Fleet")) {
	string coord1 = Gettok(line1,(Numtok(line1," ") - 1)," ");
	string coord2 = Gettok(line2,(Numtok(line2," ") - 1)," ");
	string galcheck1 = Gettok(coord1,1,":") + Gettok(coord1,2,":");
	string galcheck2 = Gettok(coord2,1,":") + Gettok(coord2,2,":");
	int Tick1 = atoi(Gettok(line1,2," ").c_str());
	int Tick2 = atoi(Gettok(line2,2," ").c_str());
	// if fleets launched within x ticks of each other are going to the same galaxy - dump report
	if (( abs( Tick1 - Tick2 ) <= timeforlaunch && ( galcheck1 == galcheck2))) { 
		guilty = true; 
		// Assign Dodgy points
		Dodgyrating++;
		if (coord1 == coord2) { Dodgyrating++; }
		if ( abs( Tick1 - Tick2 ) <= 1 ) { Dodgyrating++; }
		}
	}
//
// For LOGIN data
	if ((type1 == "Login" ) && (type2 == "Login")) {
		string month1 = Gettok(line1,2," ");
		string month2 = Gettok(line2,2," ");
		string day1 = Gettok(line1,3," ");
		string day2 = Gettok(line2,3," ");
		string ip1 = Gettok(line1,6," ");
		string ip2 = Gettok(line2,6," ");
		int hour1 = atoi(Gettok(Gettok(line1,4," "),1,":").c_str());
		int hour2 = atoi(Gettok(Gettok(line2,4," "),1,":").c_str());
		int min1 = atoi(Gettok(Gettok(line1,4," "),2,":").c_str());
		int min2 = atoi(Gettok(Gettok(line2,4," "),2,":").c_str());
		// If logins are within 10 mins of each other on the same day ( support for date to be added ) - dump report
		if ( (abs((hour1 * 60 + min1) - (hour2 * 60 + min2)) <= timeforcheck ) && ( month1 == month2 ) && ( day1 == day2 )) {
		guilty = true;
		// Assign Dodgypoints
		Dodgyrating++;
		if (abs((hour1 * 60 + min1) - (hour2 * 60 + min2)) <= timeforcheck2 ) { Dodgyrating++; }
		if (abs((hour1 * 60 + min1) - (hour2 * 60 + min2)) <= timeforcheck3 ) { Dodgyrating++; }
		}
	}

	// Report to logfile
	if ( guilty == true ) {
		Report(P1 + " : " + line1 + "\n");
		Report(P2 + " : " + line2 + "\n");
		Report("\n");
		if ( UseSilent == false ) { 
			cout << "Corrolation found : " << line1 << "\t" << line2 <<"\n"; 
		}
	}
}

void Report(string text) {

	ofstream fout(filename.c_str(),ios::app);
	if (!fout) { cout << "Cannot open file for writing\n"; }
	fout << text;
	fout.close();
   }

tickcalcclass.h

using namespace std;
// Class Declairation
//
class Tick;

// Class Prototype

class Tick {
public:
	Tick(); // const
	~Tick(); // dest
	int calc(string line);
private:
	// since starting from aug
	int aug , sep , oct , nov , dec , jan; // just incase round runs on till January
	int ticknum;
	int Hours(int line);
	int Days(string line); 
};


Tick::Tick() {
	// Constructor
	//setup internal class variables
	aug = 30;
	sep = 30;
	oct = 31;
	nov = 30;
	dec = 31;
	jan = 31;
}

Tick::~Tick() {
	// Destructor
}

// Class members


int Tick::Days(string line) {
	// Return days in month
	if ( line == "Aug" ) { return aug; }
	if ( line == "Sep" ) { return sep; }
	if ( line == "Oct" ) { return oct; }
	if ( line == "Nov" ) { return nov; }
	if ( line == "Dec" ) { return dec; }
	if ( line == "Jan" ) { return jan; }
	return 0;
}
int Tick::Hours(int line) {
	//days to hours
	return line * 24;
}

int Tick::calc(string line) {
	int ticknum = 0;
	// Do aargh type calculations here
	// Start apparently saturday 13th September at 12:00 gmt , Will calculate to there
	// Lets do some parsing of the line which came in
	// Line will be in format Day Month Date Time Year Misc
	string month = Gettok(line,2," ");
	int date = atoi(Gettok(line,3," ").c_str());
	int hour = atoi(Gettok(Gettok(line,4," "),1,":").c_str());
	// Got the necessary points. yes i know tick was up to 10 mins off 
	// but it progressed over the ticks slowly,
	// fk off if you want me to calc that in too
	// Right. doing this via a way of converting months to hours
	// and adding on incomplete months 's hours. giving a tick number if there was no rollback
	// will add a thing to account for rollback :S.
	// having to subtract 12 from total as started at 12 gmt
ticknum = Hours( Days(month) - 13 ) + Hours(date) + hour - 12 ;
// for before tickstart 
if (ticknum <= 0) { ticknum = 0; }
	return ticknum;
}

  

tokens.h

// Token functions

#include <string>
#include <iostream>
using namespace std;

/***************\
| Isin function |
\***************/
// Returns 1 or 0 if a token is within another token
// Usage bool Result = Isin(string Token,string Subtoken);
bool Isin(string Token,string Subtoken) 
{
	if ( Token.find(Subtoken) <= Token.length() ) { return 1; }
	else { return 0; }
}

/*******************\
|  Gettok function  | 
\*******************/
// Retrieves a specific token
// Usage : string Result = Gettok(string Input,int Token number, string Sepchar(s))


// functions
string Gettok(string Input,int Token,string Sepchar) 
    {
    Input = Input + Sepchar;
    //temporary variable storage space initialisation
    int counter = 1, start = 0,finish = 0;
    while ( counter <= Token ) {
	finish = ( Input.find(Sepchar,start) + 1);
	// if this is the token we want, return it
	if ( counter == Token ) { return Input.substr(start,(finish - start - 1)); }
	// Otherwise locate the next token
	 else { 
			start = finish;
			counter++;
		}
	}
	return "";
}

/*******************\
|  Numtok Function  |
\*******************/
// Returns the number of tokens
// Usage : int Result = NumTok(string Input,string Sepchar(s))
int Numtok(string Input,string Sepchar)
{
	// set up variable storage
	Input = Input + Sepchar;
	int counter = 0, tokens = 0;
	int lasttok = Input.find_last_of(Sepchar);
	while ( counter <= lasttok ) {
		counter = ( Input.find(Sepchar,counter) + 1 );
		tokens++;
	}
	return tokens;
}


/******************\
|  Istok function  |
\******************/
// Returns 1 if the token is in the input
// Usage : bool Result = Istok(string Input,string Token,string Sepchar(s))

bool Istok(string Input,string Token,string Sepchar) 
    {
    Input = Input + Sepchar;
	string TempToken;
    //temporary variable storage space initialisation
    int counter = 1, start = 0,finish = 0;
    while ( counter <= Numtok(Input,Sepchar)) {
	finish = ( Input.find(Sepchar,start) + 1);
	TempToken = Input.substr(start,(finish - start - 1));
	if ( TempToken == Token ) { return 1 ; }
	// Otherwise locate the next token
	 else { 
			start = finish;
			counter++;
		}
	}
	return 0;
}

/*****************\
| Addtok function |
\*****************/
// Adds the token to the end of the input text but only if its not already in the input
// Usage : string Result = Addtok(string Input,string Token, string Sepchar(s))

string Addtok(string Input,string Token,string Sepchar)
{
	if ( Istok(Input,Token,Sepchar) == 0 ) { return ( Input + Sepchar + Token ) ; }
	else  { return Input; }
}


/*****************\
| Deltok Function |
\*****************/
// Deletes the specified token in the input string if its in there
// Usage : string Result = Deltok(string Input,int Token,string Sepchar(s))

string Deltok(string Input,int Token,string Sepchar)
{
    int counter = 1;
	string Temp = "";
    while ( counter <= Numtok(Input,Sepchar) ) {
		// if this isnt the one to be 'deleted', add it to Temp 
		if ( counter != Token ) { 
			if ( Temp == "" ) { Temp = Temp + Gettok(Input,counter,Sepchar); }
			else { Temp = Temp + Sepchar + Gettok(Input,counter,Sepchar); }
		}
		counter++;
	}
	return Temp ;
}

/******************\
| Findtok function |
\******************/
// Returns the token number of a specified token in text, 0 if its not there
// Usage : int Result = Findtok(string Input,string Token,string Sepchar(s)) 

int Findtok(string Input,string Token,string Sepchar) 
{
        Input = Input + Sepchar;
	string TempToken;
    //temporary variable storage space initialisation
    int counter = 1, start = 0,finish = 0;
    while ( counter <= Numtok(Input,Sepchar)) {
	finish = ( Input.find(Sepchar,start) + 1);
	TempToken = Input.substr(start,(finish - start - 1));
	if ( TempToken == Token ) { return counter ; }
	// Otherwise locate the next token
	else { 
		start = finish;
		counter++;
		}
	}
	return 0;
}

/*****************\
| Instok function |
\*****************/
// Inserts a token at a specified position
// Usage : string Result = Instok(string Input,string Token,int Position,string Sepchar(s))
string Instok(string Input,string Token,int Position,string Sepchar)
{
	// special case, if position is greater then number of tokens
	if (Position > Numtok(Input,Sepchar)) { return ( Input + Sepchar + Token ) ; }
    int counter = 1;
	string Temp = "";
    while ( counter <= Numtok(Input,Sepchar)) {
		if ( counter != Position ) { 
			if ( Temp == "" ) { Temp = Temp + Gettok(Input,counter,Sepchar); }
			else { Temp = Temp + Sepchar + Gettok(Input,counter,Sepchar); }
		}
		// if the position IS where the token is to be inserted
		else { Temp = Temp + Sepchar + Token + Sepchar + Gettok(Input,counter,Sepchar); }
		counter++;
	}
	return Temp ;
}


/**********************\
| Matcktoknum function |
\**********************/
// Returns the NUMBER of tokens that match 
// Usage int Result = Matchtoknum(string Input,string Token,string Sepchar(s))
int Matchtoknum(string Input,string Token,string Sepchar)
{
	string TempToken;
    //temporary variable storage space initialisation
    int counter = 1,tokens = 0;
    while ( counter <= Numtok(Input,Sepchar)) {
	TempToken = Gettok(Input,counter,Sepchar);
	if ( TempToken == Token ) { tokens++ ; }
	// Otherwise locate the next token
	counter++;
	}
	return tokens;
}

/*******************\
| Matcktok function |
\*******************/
// Returns the n-th token that matches 
// Usage string Result = Matchtoknum(string Input,string Token,int Position,string Sepchar(s))
string Matchtok(string Input,string Token,int Position,string Sepchar)
{
	string TempToken;
    //temporary variable storage space initialisation
    int counter = 1,tokens = 1;
    while ( counter <= Numtok(Input,Sepchar)) {
	TempToken = Gettok(Input,counter,Sepchar);
	if ( Isin(TempToken,Token) == 1 ) { 
		if ( Position == tokens ) {	return TempToken ; }
		else { 	tokens++; }
	}
	// Otherwise locate the next token
	counter++;

	}
	return "";
}


/*****************\
| Puttok function |
\*****************/
// Replaces a token at a specified position
// Usage : string Result = Puttok(string Input,string Token,int Position,string Sepchar(s))
string Puttok(string Input,string Token,int Position,string Sepchar)
{
    int counter = 1;
	string Temp = "";
    while ( counter <= Numtok(Input,Sepchar)) {
		if ( counter != Position ) { 
			if ( Temp == "" ) { Temp = Temp + Gettok(Input,counter,Sepchar); }
			else { Temp = Temp + Sepchar + Gettok(Input,counter,Sepchar); }
		}
		// if the position IS where the token is to be replaced
		else { Temp = Temp + Sepchar + Token ; }
		counter++;
	}
	return Temp ;
}

dataclass.h

using namespace std;
// Class Declairation
//
class DataArray;

// Class Prototype

class DataArray {
public:
	// vars 
	int arrayitems; // number of files stored in array form
	int arraysizes[50]; // number of lines in each array
	// funcs 
	string Readdata(int refnum,int linenum);
	void Savedata(int refnum,int linenum,string Data);
private:
	string arraydata[50][10000]; // 50 files and 10000 lines per file should be sufficient

};


//
// Class members

void DataArray::Savedata(int refnum,int linenum,string Data) {
	arraydata[refnum][linenum] = Data;
}

string DataArray::Readdata(int refnum,int linenum) {
	return arraydata[refnum][linenum];
}

statsclass.h

using namespace std;
// Class Declairation
//
class StatsArray;

// Class Prototype

class StatsArray {
public:
	// vars 
	int arrayitems; // number of files stored in array form
	int arraysizes[50]; // number of lines in each array
	// funcs 
	string Readdata(int refnum,int linenum);
	void Savedata(int refnum,int linenum,string Data);
private:
	string arraydata[50][10000]; // 50 files and 10000 lines per file should be sufficient

};


//
// Class members

void StatsArray::Savedata(int refnum,int linenum,string Data) {
	arraydata[refnum][linenum] = Data;
}

string StatsArray::Readdata(int refnum,int linenum) {
	return arraydata[refnum][linenum];
 }