// Name:  McCabe, Micheal H.
// Date:  March 16, 2009
// calc_v3.cpp (In-Class Edits & Modifications)

// File Edit History:
//
// File created on 03/11/2009 following in-class coding examples by Prof.
// Schuyler.  Additional work done on 03/12 and 03/13.  Additional in-class
// coding examples added on 03/16.  Changed function Help_Function to Helpscreen
// based on directions in Assignment 17.  Added function IsDigit and ReadInputFile
// based on in-class assignment 03/17.  More work on 03/18 to add WriteOutputFile.
// Afternoon of 03/18 -- began adding arithmetic functions (slowly)

// List of library functions needed.

#include <iostream>
#include <string>
#include <iomanip>
#include <fstream>
#include <cstdlib>
#include <cmath>

// Namespace definition

using namespace std;

// Compiler definitions

#define MAX_USER_LIST 100


#define N1			       Data[1]
#define N2			       Data[2]
#define USER_ENTRIES	   Data[0]
#define START_USER_DATA	   3

#define HELP_e 		 "'e'  to enter N1 and N2\n"
#define HELP_i		 "'i'  to enter a list of values (Q to stop)\n"
#define HELP_fi      "'fi' File input:  prompt for a filename and read values into list [] \n"
#define HELP_fo      "'fo' File Output: prompt for a filename and write list values out. \n"
#define HELP_plus    "'+'  Add (N1 + N2) \n"
#define HELP_minus   "'-'  Subtract (N1 - N2) \n"
#define HELP_star    "'*'  Multiply (N1 * N2) \n"
#define HELP_slash   "'/'  Divide (N1 / N2) \n"
#define HELP_caret   "'^'  Raise any real N1 to the power of N2 for any integer N2 (+|-) \n"
#define HELP_exclaim "'!'  Calculate the factorial for any integer N1 (round if real) \n"
#define HELP_c       "'c'  Clear (N1, N2) \n"
#define HELP_cL      "'cL' Clear the memory list of all values. \n"
#define HELP_h       "'h'  Help \n"
#define HELP_l       "'l'  List all the values currently in List () \n"
#define HELP_q       "'q'  Quit \n"
#define HELP_o       "'o'  Output the last calculation results to the screen. \n"
#define HELP_a       "'a'  Average of the values in list [] \n"
#define HELP_d       "'d#' Delete the value at the index # in List [] \n"
#define HELP_m       "'m#' Memorize (save) the last calculation result at index # in list. \n"
#define HELP_s       "'s'  Sum all the values in List [] \n"
#define HELP_sd      "'sd' Calulate the standard deviation in the list [] \n"
#define HELP_p       "'p'  Calculate the product of the values in the list \n"
#define HELP_M1      "'M1' Prompt for index '#' and store N1 into list[#] \n"
#define HELP_M2      "'M2' Prompt for index '#' and store N2 into list[#] \n"
#define HELP_N1      "'N1' Prompt for index '#' and store List[#] into N1 \n"
#define HELP_N2      "'N2' Prompt for index '#' and store List[#] into N2 \n"
#define NO_COMMAND	 " No command recognized\n"
#define CMD_PROMPT   "Enter Command: "

// Function prototypes

void helpscreen();
bool IsDigit(char chr2);
int ReadInputFile(int start, float data[]);
int WriteOutputFile(int start, float data[]);
void enterN1N2();
float adder(float V1, float V2);
float subtractor(float V1, float V2);
float multiplier(float V1, float V2);
float divider(float V1, float V2);
float exponentiator(float V1, float V2);
int factorial (int num);
void clearn();
void clearl();
void list();



// Global variables

float Data[MAX_USER_LIST];

// Main Routine

int main()
{
bool command_loop = true;
char cmd_chr1;
char cmd_chr2;
string temp;
int elements_read=0; //This value is returned by ReadInputFile
int i=0; //Just an index variable I'll use to debug the file i/o

while (command_loop)
	{
    temp="";
    cout << CMD_PROMPT;
	cin.get(cmd_chr1);
	cin.get(cmd_chr2);
	
	// Decode it
	
	switch (cmd_chr1)
	{
		case 'e':
			enterN1N2();
			break;
		case 'i':
			temp = HELP_i;
			break;
		case 'f':
             if (cmd_chr2 == 'i')
                {
                elements_read=ReadInputFile(START_USER_DATA, Data);
                //This loop just displays the data we read from the file to check
                //for functionality.  Can be discarded when program is working.
                if (elements_read != 0)
                   {cout << elements_read << " items read from file..." << endl;
                   for (i=START_USER_DATA; i<=Data[0]+START_USER_DATA-1; i++)
                       {
                       cout << i << ": " << Data[i] << endl;
                       }
                   }
                   }
             else if (cmd_chr2 == 'o')
                  WriteOutputFile(START_USER_DATA, Data);
                  else temp=NO_COMMAND;
             break;
        case '+':
             temp = HELP_plus;
             break;
        case '-':
             temp = HELP_minus;
             break;
        case '*':
             temp = HELP_star;
             break;
        case '/':
             temp = HELP_slash;
             break;
        case '^':
             temp = HELP_caret;
             break;
        case '!':
             temp = HELP_exclaim;
             break;
        case 'c':
             cout << HELP_c;
             cout << HELP_cL;
             temp="";
             break;
        case 'h':
             helpscreen();
             temp = "";
             break;
        case 'l':
             temp = HELP_l;
             break;
        case 'q':
             command_loop = false;
             temp = "Bye, Bye!";
             break;
        case 'o':
             temp = HELP_o;
             break;
        case 'a':
             temp = HELP_a;
             break;
        case 'd':
             temp = HELP_d;
             if (IsDigit(cmd_chr2))
                ;
             break;
        case 'm':
             temp = HELP_m;
             break;
        case 's':
             cout << HELP_s;
             cout << HELP_sd;
             temp="";
             break;
        case 'p':
             temp = HELP_p;
             break;
        case 'M':
             if (cmd_chr2 == '1')
                temp=HELP_M1;
                else if (cmd_chr2 == '2')
                     temp=HELP_M2;
                     else temp=NO_COMMAND;
             break;
        case 'N':
              if (cmd_chr2 == '1')
                temp=HELP_N1;
                else if (cmd_chr2 == '2')
                     temp=HELP_N2;
                     else temp=NO_COMMAND;
             break;
		default:
			temp = "NO_COMMAND \n";
	}		
	cout << temp;
	
	// Clear current line out (if needed)
	
	if (cmd_chr2 != '\n')
	   cin.ignore(100, '\n');
	}
}



void helpscreen()
{
cout <<  HELP_e;
cout <<  HELP_i;
cout <<  HELP_fi;
cout <<  HELP_fo;
cout <<  HELP_plus;
cout <<  HELP_minus;
cout <<  HELP_star;
cout <<  HELP_slash;
cout <<  HELP_caret;
cout <<  HELP_exclaim;
cout <<  HELP_c;
cout <<  HELP_cL;
cout <<  HELP_h;
cout <<  HELP_l;
cout <<  HELP_q;
cout <<  HELP_o;
cout <<  HELP_a;
cout <<  HELP_d;
cout <<  HELP_m;
cout <<  HELP_s;
cout <<  HELP_sd;
cout <<  HELP_p;
cout <<  HELP_M1;
cout <<  HELP_M2;
cout <<  HELP_N1;
cout <<  HELP_N2;
return;
}



bool IsDigit(char chr2)
{
// Tests whether or not the char chr2 is a digit
bool flag = true;
if ( (int) chr2 < 48 || (int) chr2 >57 )
   flag = false;
return flag;     
}


int ReadInputFile(int start, float data[])
{
    int records=0;
    int count=0;
    float element;
    int return_value=0;
    string inputfilename;
    cin.ignore(100, '\n');
    cout << "Please enter a filename to open:  ";
    cin >> inputfilename;
    if (cin)
       {
       cout << "Thank you.  Attempting to open file " << inputfilename << endl;  
       ifstream inputfile;
       inputfile.open(inputfilename.c_str());
       if (inputfile.is_open())
          {
          inputfile >> records;
          cout << "Records: " << records << endl;
          if (inputfile.fail()) 
             {
             cout << "Error:  Data Error in the file. \n";
             return_value=0;
             }
          else
              {
              while (count<=records and !inputfile.eof())
                 {
                 inputfile >> element;
                 if (inputfile.good())
                    {
                    data[start+count]=element;
                    count++;
                    }
                 }
              if (count<records)
                 {
                 cout << "Error: Unexpected end of file.  (Insufficient data)\n";
                 return_value=0;
                 }
              else
                  {
                  data[0]=count;
                  return_value=count;
                  }
                  }
                  }
          else
              {
              cout << "Error:  Could not open file. \n";
              return_value=0;
              }
       inputfile.close();
       }
    else
        {
        cout << "Filename input not recognized.  Try Again.\n";
        }
    return return_value;      
}


int WriteOutputFile(int start, float data[])
    {  
    int return_value=0;
    int i;
    int records;
    string outputfilename;
    cin.ignore(100, '\n');
    cout << "Please enter a filename to open:  ";
    cin >> outputfilename;
    if (cin)
       {
       cout << "Thank you.  Attempting to open file " << outputfilename << endl;  
       ofstream outputfile;
       outputfile.open(outputfilename.c_str());
       if (outputfile.is_open())
          {
          records=(int)data[0];
          cout << "Writing " << records << " records to disk." << endl;
          outputfile << data[0] << endl;
          for (i=start; i<start+records; i++)
              {
              outputfile << data[i] << endl;
              cout << i << ": " << data[i] << endl;
              }
              outputfile.close();
          }
       }
       else
           {
               cout << "Error.  Output file could not be opened! \n";
               return_value=911;
           }           

    return return_value;
    }

void enterN1N2()
{
     cout << "Please enter a value for N1: ";
     cin >> N1;
     cout << "Please enter a value for N2: ";
     cin >> N1;
     return;
}

float adder(float V1, float V2)
{
      float sum;
      sum=V1+V2;
      return sum;
}

float subtractor(float V1, float V2)
{
      float difference;
      difference=V1-V2;
      return difference;
}

float multiplier(float V1, float V2)
{
      float product;
      product=V1*V2;
      return product;
}

float divider(float V1, float V2)
{
      float quotient;
      quotient=V1/V2;
      return quotient;
}

float exponentiator(float V1, float V2)
{
      float power;
      power=pow(V1,V2); // where V1 is the base and V2 is the exponent
      return power;
}


// Here's where my lack of mathematical ability is coming back to bite me!
// I don't want to try recursion, so we'll do this by iteration...
      
int factorial (int num)
{
    int result=1;
    for (int i=1; i<=num; ++i)
        result=result*=i;
    return result;
}

void clearn()
{
     N1=0;
     N2=0;
     return;
}

void clearl()
{
     int i;
     for (i=0; i<=MAX_USER_LIST; i++)
         Data[i]=0;
     return;
}

void list()
{
     int i;
     int m;
     m=(int)Data[0];
     for (i=START_USER_DATA; i<=m; i++)
         cout << i << ": " << Data[i] << endl;
     return;
}
           
void output_result();

