// inputFunctionDemo2.cpp
//
// Demonstrates power function and an input function,
// using text file input.

#include <iostream>
#include <fstream>

using namespace std;

void printInstructions();
double power(float base, int exponent);
bool inputNumbers(float& base, int& exponent, ifstream& inFile);

/*
 * int main()
 *
 * Obtains pairs of numbers from a text file,
 * where each pair consists of a floating-point base
 * and an integer exponent.  For each pair, the base is
 * then raised to the exponent power, and the base,
 * exponent, and power are output to the terminal.
 *
 * Command-line arguments:
 *    argv[0] - filename of this program's executable file
 *    argv[1] - filename oftext data file containing pairs of
 *              numbers, first number float, second number int.
 *
 * Global variable:
 *    cout - standard output stream.
 */
int main(int argc, char** argv)
{
   // Announce purpose of program,
   // if commeand-line argument is missing:
   if ( argc < 2 )  {
      printInstructions();
      return 0;
   }  // if

   // Open file for reading:
   ifstream inputFile;
   inputFile.open(argv[1]);   
   if ( !inputFile )  {
      cout << "Could not open file"
                 << argv[1] << "." << endl;
      return 1;
   }  // if

   // Input pairs of numbers from the text file where
   // each pair consists of a floating-point base and
   // an integer exponent.  For each pair, raise base
   // to the exponent power and display result.
   float enteredBase;
   int enteredExponent;
   while ( inputNumbers(enteredBase, enteredExponent, inputFile) )
   {
      // The inputNumbers function, called above, uses cout.

      // Raise enteredBase to the enteredExponent power:
      double result = power(enteredBase, enteredExponent);

      // Display result:
      cout << enteredBase << " to the " << enteredExponent
               << " power is " << result << "." << endl;
   }  // while

   return 0;
}  // function main

/*
 * void printInstructions()
 *
 * Outputs a message to the terminal,
 * Telling the user how to use this program
 *
 * Global variable:
 *    cout - an ostream object for output to the terminal.
 *           cout is an external variable, declared
 *           in library header file <iostream>.
 */
void printInstructions()
{
   cout << "This program will read pairs of numbers "
          << "x and n from a text file," << endl;
   cout << "where x is a fixed-point number and "
          << "n is an integer." << endl;
   cout << "For each pair, this program will "
          << "output x to the n power." << endl;
   cout << "Enter the filename as a "
          << "command-line argument." << endl;
}  // function printInstructions

/*
 * bool inputNumbers(float& base,
 *                   int& exponent,
 *                   ifstream& inFile)
 *
 * Reads a pair of numbers from the specified
 * file input stream, where the first number
 * is a floating point number, read into base,
 * and the second number is an integer, read
 * into exponent.  If the second number in a 
 * pair is not read successfully, an error
 * message is displayed.
 *
 * Parameters:
 *    base - a reference to the first number
 *           in the pair read from the file.
 *       Precondition: none
 *       Postcondition:  base contains a value
 *           read from the file if input is successful,
 *           garbage otherwise.
 *    exponent - a reference to the second number
 *           in the pair read from the file.
 *       Precondition: none
 *       Postcondition:  exponent contains a value
 *           read from the file if input is successful,
 *           garbage otherwise.
 *    infile - a reference to a file input stream.
 *       Precondition:  inFile has been opened, and
 *           the state of inFile is true.  (All previous
 *           inputs from the file were successful.)
 *       Postcondition:  The state of inFile is true if bpth
 *           base and exponent were input successfully,
 *           false otherwise.  inFile has NOT ended a line.
 *
 * Global variables:
 *    cout - standard output stream, used for error messages.
 *       Precondition:  none.
 *       Postcondition:  If an error message was printed,
 *           cout has ended a line.  Otherwise, nothing
 *           was printed.
 *
 * Returns:  true if both base and exponent were input
 *           sucessfully, false otherwise.
 */
bool inputNumbers(float& base,
                  int& exponent,
                  ifstream& inFile)
{
   // Count of how many data items have been
   // read successfully from the file:
   static int itemNumber = 0;

   // Attempt to read first number of a pair:
   inFile >> base;

   // Check end-of-file:
   if ( !inFile )
      return false;
   itemNumber++;

   // Attempt to read second number of a pair:
   inFile >> exponent;

   // Check input error (i.e. incomplete pair):
   if ( !inFile )
      cout << "File format error.  Only "
              << itemNumber
              << " data items have been read successfully."
              << endl;
   itemNumber++;

   return inFile;
}  // function inputNumbers

/*
 * double power(float base, int exponent)
 *
 * Raises a floating-point number to a
 * specified integer power.
 *
 * No error-checking is done for out-of-range
 * values.
 *
 * Parameters:
 *    base - a number to be raised to a power.
 *       May be any float value such that, for
 *       a given exponent, the result will be
 *       within the double range without
 *       arithmetic overflow or underflow.
 *    exponent - an integer exponent.
 *       May be any int value such that, for
 *       a given base, the result will be
 *       within the double range without
 *       arithmetic overflow or underflow.
 *
 * Returns:
 *    base raised to the exponent power.
 */
double power(float base, int exponent)
{
   // If exponent is negative, do necessary conversions
   // to raise reciprocal of base to a positive power:
   if ( exponent < 0 )  {
      exponent = 0 - exponent;
      base = 1 / base;
   }  // if exponent < 0

   // Raise base to a non-negative power:
   double product = 1;
   for ( int i = 0; i < exponent; i++ )
      product = product * base;
   return product;
}  // function power