Programming Assignment Three COP 4020

Base Two Class

Restatement of the Project

Assumptions Made

Difficulties Encountered

Using the Program

Class Functions

source code and report by

Phil Porvaznik
  PhilVaz

Andy Thoreson
planaria@gte.net

Tino Cash
cash@eng.usf.edu

Steve Bassi
  sbassi@eng.usf.edu

Download All Files BaseTwo.zip

Printable Version of this Report

C++ Source File

Log  

 

C++ Source Code

Restatement of the Project

We are asked to create an arbitrarily long Base Two (binary) class. Typical math operations along with standard bitwise logical operations can be performed on binary strings the user enters. Allowance is to be made for Add, Subtract, Multiply, Divide (integer division), increment, decrement, modulus (remainder), power function (raise to a non-negative power), and comparison operations less than (<), less than or equal (<=), greater than (>), greater than or equal (>=). The bitwise operations include OR, AND, NOT, XOR (exclusive or). The driver program (in the main function) is to allow the user to enter a string of binary numbers into variables with the math and bitwise operations performed on them giving a binary result. The variables can be redefined and the variable list can be viewed and cleared (deleted).

Assumptions Made

There are two major assumptions. First, the sign of the binary number is held by the leftmost or highest bit (0=positive number, 1=negative). So 0101 is +5 (positive 5) in decimal, while 1101 is -5 (negative 5) in decimal. Second, any binary strings that are less than 32 bits are considered padded with zeros when doing the math and bitwise operations, while the sign bit (leftmost) is evaluated separately in the bitwise operations.

For example, 0101 which is +5 in decimal, is considered 00000000000000000000000000000101. This is important since the bitwise operations don't "appear" to give correct results if different lengths of binary strings are entered. If one enters 0101 (positive 5 decimal)  as variable "X", and 10001010 (negative -10 decimal) as variable "Y", the following results are obtained: X OR Y = 10000000000000000000000000001111, X AND Y =  00000000000000000000000000000000 (32 0's), X XOR Y = (same as OR in this example), NOT X = 11111111111111111111111111111010, etc.

Difficulties Encountered

The main difficulty upon reading the assignment is how the program will be able to "understand" binary numbers, and how the program is going to store them. Since typical math operations (+, -, *, /, mod, pow) will only work with decimal numbers, we decided to take the "easy" route and convert the number to decimal first, then perform the math operation and convert the number back to binary for output. Since the modulus function (mod 2 is required for conversion back to binary) is illegal in C++ with LONG DOUBLE, this unfortunately limited our input of binary numbers to 32 bits (4 bytes, which is a LONG INT, or simply INT in 32-bit systems). Taking the highest bit for sign into account this gives us a range of +2147483647 to -2147483647 (2 raised to the 31st power approx).

At first we thought we could allow for 64 bit numbers (8 byte), or possibly 80 bit numbers (10 bytes), since C++ does have a type for LONG DOUBLE (80 bits or 10 bytes). However, an "overflow error" had to be trapped, especially when doing multiplication or raise to power, since 64 bits times 64 bits = 128 bits. We solved this issue by allowing just 32 bits for input, but actually storing the math result as a LONG DOUBLE (80 bit) number, then checking for the "overflow error", and if the number was within the 32-bit range saving the result back as LONG INT.

How the binary numbers were going to be stored was another difficulty. One could use an array of boolean (true, false) for each of the binary strings, but we decided on a character array of 1's and 0's since this makes the output with COUT simple.

Another difficulty was that some of us were unfamiliar with the type of "object-oriented" programming required by the assignment. The idea that the binary strings and variable names had to be "hidden" from the rest of the program was a radical concept for those of us experienced only with "procedural" type programming in the past. One book that helped me (Phil Porvaznik) overcome this difficulty and understand the concept of "data hiding", making the functions within the class "public" which is how the rest of the program accesses the data, etc is Object-Oriented Programming in C++ (Third Edition) by Robert Lafore (Sams Publishing, 1999).

Using the Program

The program, written as a "console application" has a typical menu-type system to give the user the ability to enter a variable, enter a binary amount, perform a math operation, perform a comparison, or perform a bitwise operation. The complete menu options are:

(A) Enter a new variable and amount
(C) Change an existing amount
(E) Add two variables
(G) Multiply two variables
(I) Increment a variable
(K) Modulus function
(M) Binary OR
(O) Binary XOR
(Q) Compare < (less than)
(S) Compare > (greater than)
(X) Exit

(B) List all variables and amounts
(D) Clear/Delete variables list
(F) Subtract two variables
(H) (integer) Divide two variables
(J) Decrement a variable
(L) Raise to Power function
(N) Binary AND
(P) Binary NOT
(R) Compare <= (less than or equal)
(T) Compare >= (greater than or equal)  

The program will not allow division by zero, nor will it raise a number to a negative power. It allows for input of 32 bit (4 byte) numbers, allows them to be stored in variables (up to 19 characters for variable names), and then performs the math or bitwise operation the user wants on any two of the variables. The operations for increment, decrement, and bitwise NOT require only one variable as input. Note: variable names are "case sensitive," so XVAR is a different variable than xvar.

The menu is displayed to the screen with a question mark "?". A screen shot looks like this:

Class Functions

The class is named BaseTwo and contains the following private data, protected functions, and public functions by order of appearance in the source code.

private data

VariableName[20] declared as char array, contains the variable name associated with the binary amount

BinaryAmount[33] declared as char array, contains a 32-bit binary string of 1's and 0's, the first bit ( element BinaryAmount[0] ) is the sign (0=positive, 1=negative)

protected functions

BinToDec

long int BinToDec (char BinaryString[33]) const -- converts from binary string to decimal, returns a long integer (32 bit number) based on binary string (char array of 32 1's 0's)

DecToBin

void DecToBin (long int DecimalAmount, char BinaryString[ ]) const -- converts from decimal to binary string, uses the char array BinaryString to store the result which is passed by reference

public functions

DisplayVariable

void DisplayVariable( ) -- used to display the private data VariableName and BinaryAmount

SetOne

void SetOne( ) -- used to set a "01" string (positive 1) into BinaryAmount for increment or decrement

CheckForVariable

bool CheckForVariable (char VarName[ ]) -- used to check if variable name exists, returns TRUE if exists, otherwise FALSE

GetVariableName

void GetVariableName( ) -- used to get the variable name to add to variable list

GetBinaryAmount

void GetBinaryAmount( ) -- used to get the binary amount (char array of 32 1's 0's) associated with variable name

AddBin

void AddBin(const BaseTwo &BinaryInput, char BinaryResult[ ]) const -- adds two BaseTwo numbers, uses BinToDec and DecToBin for conversion to decimal and back to binary, stores result in BinaryResult which is a char array passed by reference

SubBin

void SubBin(const BaseTwo &BinaryInput, char BinaryResult[ ]) const -- subtracts two BaseTwo numbers, uses BinToDec and DecToBin for conversion to decimal and back to binary, stores result in BinaryResult which is a char array passed by reference

MulBin

void MulBin(const BaseTwo &BinaryInput, char BinaryResult[ ]) const -- multiplies two BaseTwo numbers, uses BinToDec and DecToBin for conversion to decimal and back to binary, stores result in BinaryResult which is a char array passed by reference

DivBin

void DivBin(const BaseTwo &BinaryInput, char BinaryResult[ ]) const -- divides (integer division) two BaseTwo numbers, uses BinToDec and DecToBin for conversion to decimal and back to binary, stores result in BinaryResult which is a char array passed by reference

ModBin

void ModBin(const BaseTwo &BinaryInput, char BinaryResult[ ]) const -- performs modulus (remainder) function on two BaseTwo numbers, uses BinToDec and DecToBin for conversion to decimal and back to binary, stores result in BinaryResult which is a char array passed by reference

PowBin

void PowBin(const BaseTwo &BinaryInput, char BinaryResult[ ]) const -- performs raise to a power of two BaseTwo numbers, uses BinToDec and DecToBin for conversion to decimal and back to binary, raises the first number to the power of the second number, stores result in BinaryResult which is a char array passed by reference

OrBin

void OrBin(const BaseTwo &BinaryInput, char BinaryResult[ ]) const -- performs a bitwise binary OR on two BaseTwo numbers, stores result in BinaryResult which is a char array passed by reference

XOrBin

void XOrBin(const BaseTwo &BinaryInput, char BinaryResult[ ]) const -- performs a bitwise binary Exclusive OR on two BaseTwo numbers, stores result in BinaryResult which is a char array passed by reference

AndBin

void AndBin(const BaseTwo &BinaryInput, char BinaryResult[ ]) const -- performs a bitwise binary AND on two BaseTwo numbers, stores result in BinaryResult which is a char array passed by reference

NotBin

void NotBin(char BinaryResult[ ]) const -- performs a bitwise binary NOT on a BaseTwo number, stores result in BinaryResult which is a char array passed by reference

CompareBin

int CompareBin(const BaseTwo &BinaryInput) const -- compares two BaseTwo numbers, returns 0 if the two binary strings are equal, -1 if the first is less than the second, and +1 if the first is greater than the second: example

Result = BinaryArray[ x ].CompareBin(BinaryArray[ y ])

IF BinaryArray[ x ] = BinaryArray[ y ] THEN Result = 0

IF BinaryArray[ x ] < BinaryArray[ y ] THEN Result = -1

IF BinaryArray[ x ] > BinaryArray[ y ] THEN Result = +1

other functions

GetAVariable

bool GetAVariable (char Prompt[ ], BaseTwo BinaryArray[ ], int NumOfVars, int &i ) -- called from main( ) and used to get a valid variable to perform the above math or bitwise operations, displays the Prompt which is up to 50 characters in length, and checks if variable exists using class function CheckForVariable, if variable name is found, returns TRUE, otherwise FALSE, index i is passed by reference which contains the element in the BaseTwo array where the variable name was found 

Log

The log of the BaseTwo program is as follows:

Andy: 10 hours for main( ), menu options, function calls, and testing

_____________________________

Andy Thoreson



Tino: 10 hours for class BaseTwo design, class functions, and testing

_____________________________

Tino Cash



Steve: 10 hours for decimal to binary and binary to decimal converter, and testing

_____________________________

Steve Bassi



Phil: 20 hours for putting it all together in one file, getting it to compile, debug, comments, and documentation/manual/report

_____________________________

Phil Porvaznik

Total Hours = 50

C++ Source Code

/**********************************************************
  Group Project for COP 4020
  Base Two Class with math and logical (bitwise) functions
***********************************************************
  includes the following class functions
  AddBin, SubBin, MulBin, DivBin, ModBin, PowBin,
  OrBin, AndBin, XOrBin, NotBin and CompareBin for < <= > >=  
  for Base Two numbers entered as 32-bit binary strings  
*********************************************************** 
  source code with comments and documentation
  by Phil Porvaznik   (PhilVaz)
     Andy Thoreson    (planaria@gte.net)
     Tino Cash        (cash@eng.usf.edu)
     Steve Bassi      (sbassi@eng.usf.edu)		  	 	 
***********************************************************/
#include <iostream.h>
#include <string.h>   // for string functions
#include <ctype.h>    // for toupper()
#include <math.h>     // for math functions
#include <process.h>  // for exit(0)
// *****************************************
//
// CLASS BaseTwo definition
//
// *****************************************
class BaseTwo
{
private:
   char VariableName[20];  // variable name for reference
   char BinaryAmount[33];  // binary string 32 bits of 1's 0's
protected:
   // ******************************************
   //
   // Binary to Decimal converter function
   //
   // ******************************************		
   long int BinToDec (char BinaryString[33]) const
   {
      // Decimal Amount is a long int for conversion
      // which allows for 32-bit (4 byte) numbers        			    		
      long int DecimalAmount = 0;
      // power of 2, begin at first bit	
      long int Pow2 = 1;		
      // go from lowest bit (on right of string)
      // to highest bit (on left of string)
      // and compute decimal amount			
      for (int i = (strlen(BinaryString) - 1); i >= 1; i--)
      {
         // if bit is 1 add corresponding power of 2			
         if (BinaryString[i] == '1')
            DecimalAmount = DecimalAmount + Pow2;
         // move to next power of 2 bit			
         Pow2 = Pow2 * 2;
      }
      // check for sign in highest bit (element 0 in array)
      // 0 = positive, 1 = negative
      if (BinaryString[0] == '1')
         DecimalAmount = -DecimalAmount;
      cout << "Decimal Amount = " << DecimalAmount << "\n";	  
      return DecimalAmount;
   } // END BinToDec
   // ********************************************
   //
   // Decimal to Binary converter function
   //
   // ********************************************		
   void DecToBin (long int DecimalAmount, char BinaryString[]) const
   {
      long int Remainder;    // remainder after modulus function
      int BinaryPosition;    // position in char array
      bool Negative = false; // check for negative sign   	  
      if (DecimalAmount < 0)
      {
         Negative = true;    // if < 0 then sign is negative
         DecimalAmount = -DecimalAmount; // work with positive
      }
      // make all digits of Binary String zero
      for (int i=0; i<=31; i++)
         BinaryString[i] = '0';
      // set end of string and begin at high bit position = 31	  	  
      BinaryString[32] = '\0';		  
      BinaryPosition = 31;	  	  	  
      while (DecimalAmount >= 1)
      {
         Remainder = DecimalAmount % 2;     // get remainder of mod 2
         DecimalAmount = DecimalAmount / 2; // int divide number by 2	  
         // bit is 1 if we have remainder, otherwise leave 0			
         if (Remainder == 1)
            BinaryString[BinaryPosition] = '1';
         // move to next lowest bit			
         BinaryPosition--;					 	  
      }
      // check if negative, if so make lowest bit 1	  
      if (Negative)
         BinaryString[0] = '1';	  
   } // END DecToBin
public:
   // ***************************************
   //
   // Display Variable function
   //
   // ***************************************
   void DisplayVariable ()
   {
      unsigned int i;
      cout << VariableName;
      // line up columns with correct spacing	  
      for (i=1; i <= (22 - strlen(VariableName)); i++)
         cout << " ";
      cout << BinaryAmount << "\n";   
   } // END DisplayVariable
   // ***************************************
   //
   // Set Binary Amount to 01 for
   // increment and decrement
   //
   // ***************************************   
   void SetOne ()
   {
      strcpy (BinaryAmount, "01");
   } // END SetOne
   // ***************************************
   //
   // Check Variable Name function
   //
   // ***************************************
   bool CheckForVariable (char VarName[])
   {
      // if var names equal return true
      // otherwise false
      if (strcmp(VarName, VariableName) == 0)
         return true;
      else
         return false;
   } // END CheckForVariable   
   // ***************************************
   //
   // Get Variable Name function
   //
   // ***************************************	   
   void GetVariableName ()
   {
      char VarName[80]; // for temp variable name
      bool valid = false; // for whether valid variable name	  
      while (!valid) // while NOT valid
      {
         cout << "Enter a new variable name: ";
         cin.getline(VarName,80);
	 // check if variable name < 20 chars and at least 1 char	  
         if (strlen(VarName) > 19 || strlen(VarName) < 1)
         cout << "Sorry, variable names must be less than 20 chars, and at least 1 char\n";		   
         else
         {
            // copy the entered variable name into class data
            strcpy(VariableName, VarName);
            valid = true;
         }			
      }
				        
   } // END GetVariableName
   // ***************************************
   //
   // Get Binary Amount function
   //
   // ****************************************	
   void GetBinaryAmount ()
   {
      char BinaryString[80]; // for binary data 1's 0's		
      bool valid = false;    // for whether valid binary number   
      while (!valid) // while NOT valid
      {
         // prompt for input of valid 32-bit binary number
         cout << "Enter up to 32-bit binary number of 1's and 0's\n";
         cout << "Highest bit (on the left) is the sign (0=positive, 1=negative)\n";      		   
         // get a line of 80 chars	   	   
         cin.getline(BinaryString,80);		   
         // however make sure they actually entered less than 33 bits
         valid = true;		 	  	  
         if (strlen(BinaryString) > 32 || strlen(BinaryString) < 2)
         {
            cout << "Please enter a binary number at least 2 bits but less than 33 bits\n\n";
            valid = false;
         }     
         else
         {
            // they entered <= 32 bits so check if valid binary number
            // can only contain 1's or 0's, set initial to true
            for (unsigned int i=0; i < strlen(BinaryString); i++)
            {
               if (BinaryString[i] != '0' && BinaryString[i] != '1')
               {
                  cout << "Sorry, that does not appear to be a valid binary number\n\n";
                  valid = false;
                  break; // break out of FOR loop
               }
            } // END FOR
         } // END ELSE
      } // END WHILE
      // they entered valid binary number
      // so copy into binary amount class data
      strcpy (BinaryAmount, BinaryString);		  		   			
   } // END GetBinaryAmount
   // *************************************
   //
   // Add Binary function
   //
   // *************************************	 	
   void AddBin(const BaseTwo &BinaryInput, char BinaryResult[]) const
   {
      char BinaryString1[33], BinaryString2[33];  // input strings
      long int Decimal1, Decimal2, DecimalResult; // decimal conversion
      long double temp;  // for overflow check
      // save two input binary strings	  	  
      strcpy(BinaryString1, BinaryAmount);
      strcpy(BinaryString2, BinaryInput.BinaryAmount);
      // convert them to decimal	  
      Decimal1 = BinToDec(BinaryString1);
      Decimal2 = BinToDec(BinaryString2);
      // perform add, save result as long double	  
      temp = long double (Decimal1) + long double (Decimal2);	  
      cout.precision(50);	  
      cout << "Decimal Result = " << temp << "\n";	  
      // check if overflow
      if (temp > 2147483647 || temp < -2147483647)
         strcpy(BinaryResult, "OVERFLOW on addition");	 	  
      else
      {
         DecimalResult = long int (temp);	  
         // convert to binary
         DecToBin(DecimalResult, BinaryResult);
      }      
   } // END AddBin
   // *************************************
   //
   // Subtract Binary function
   //
   // *************************************		
   void SubBin(const BaseTwo &BinaryInput, char BinaryResult[]) const
   {
      char BinaryString1[33], BinaryString2[33];  // input strings
      long int Decimal1, Decimal2, DecimalResult; // decimal conversion
      long double temp;  // for overflow check
      // save two input binary strings	  	  
      strcpy(BinaryString1, BinaryAmount);
      strcpy(BinaryString2, BinaryInput.BinaryAmount);
      // convert them to decimal	  
      Decimal1 = BinToDec(BinaryString1);
      Decimal2 = BinToDec(BinaryString2);
      // perform subtract, save result as long double	  
      temp = long double (Decimal1) - long double (Decimal2);
      cout.precision(50);	  
      cout << "Decimal Result = " << temp << "\n";	  
      // check if overflow
      if (temp > 2147483647 || temp < -2147483647)
         strcpy(BinaryResult, "OVERFLOW on subtraction");	  	  
      else
      {
         DecimalResult = long int (temp);	  
         // convert to binary
         DecToBin(DecimalResult, BinaryResult);
      }      
   } // END SubBin
   // *************************************
   //
   // Multiply Binary function
   //
   // *************************************		
   void MulBin(const BaseTwo &BinaryInput, char BinaryResult[]) const
   {
      char BinaryString1[33], BinaryString2[33];  // input strings
      long int Decimal1, Decimal2, DecimalResult; // decimal conversion
      long double temp;  // for overflow check
      // save two input binary strings	  	  
      strcpy(BinaryString1, BinaryAmount);
      strcpy(BinaryString2, BinaryInput.BinaryAmount);
      // convert them to decimal	  
      Decimal1 = BinToDec(BinaryString1);
      Decimal2 = BinToDec(BinaryString2);
      // perform multiply, save result as long double	  
      temp = long double (Decimal1) * long double (Decimal2);
      cout.precision(50);	  
      cout << "Decimal Result = " << temp << "\n";
      // check if overflow
      if (temp > 2147483647 || temp < -2147483647)
         strcpy(BinaryResult, "OVERFLOW on multiply");	  	  
      else
      {
         DecimalResult = long int (temp);	  
         // convert to binary
         DecToBin(DecimalResult, BinaryResult);
      }      
   } // END MulBin
   // *******************************************
   //
   // Divide (integer division) Binary function
   //
   // *******************************************
   void DivBin(const BaseTwo &BinaryInput, char BinaryResult[]) const
   {
      char BinaryString1[33], BinaryString2[33];  // input strings
      long int Decimal1, Decimal2, DecimalResult; // decimal conversion
      long double temp;  // for overflow check
      // save two input binary strings	  	  
      strcpy(BinaryString1, BinaryAmount);
      strcpy(BinaryString2, BinaryInput.BinaryAmount);
      // convert them to decimal	  
      Decimal1 = BinToDec(BinaryString1);
      Decimal2 = BinToDec(BinaryString2);
      // special: check if division by zero error
      if (Decimal2 == 0)
         strcpy(BinaryResult, "ERROR: division by zero attempted");
      else
      {
         // perform int division, save result as long double	  
         temp = Decimal1 / Decimal2;
         cout.precision(50);	  
         cout << "Decimal Result = " << temp << "\n";	  
         // check if overflow
         if (temp > 2147483647 || temp < -2147483647)
            strcpy(BinaryResult, "OVERFLOW on division");	  	  
         else
         {
            DecimalResult = long int (temp);	  
            // convert to binary
            DecToBin(DecimalResult, BinaryResult);
         }
      }
   } // END DivBin
   // *****************************
   //
   // Modulus Binary function
   //
   // *****************************	
   void ModBin(const BaseTwo &BinaryInput, char BinaryResult[]) const
   {
      char BinaryString1[33], BinaryString2[33];  // input strings
      long int Decimal1, Decimal2, DecimalResult; // decimal conversion
      long double temp;  // for overflow check
      // save two input binary strings	  	  
      strcpy(BinaryString1, BinaryAmount);
      strcpy(BinaryString2, BinaryInput.BinaryAmount);
      // convert them to decimal	  
      Decimal1 = BinToDec(BinaryString1);
      Decimal2 = BinToDec(BinaryString2);
      // perform modulus, save result as long double	  
      temp = Decimal1 % Decimal2;
      cout.precision(50);	  
      cout << "Decimal Result = " << temp << "\n";	  
      // check if overflow
      if (temp > 2147483647 || temp < -2147483647)
         strcpy(BinaryResult, "OVERFLOW on modulus");	  	  
      else
      {
         DecimalResult = long int (temp);	  
         // convert to binary
         DecToBin(DecimalResult, BinaryResult);
      }
   } // END ModBin
   // ********************************
   //
   // Power Binary function
   //
   // accepts only non-negative powers
   //
   // ********************************	
   void PowBin(const BaseTwo &BinaryInput, char BinaryResult[]) const
   {
      char BinaryString1[33], BinaryString2[33];  // input strings
      long int Decimal1, Decimal2, DecimalResult; // decimal conversion
      long double temp;  // for overflow check
      // save two input binary strings	  	  
      strcpy(BinaryString1, BinaryAmount);
      strcpy(BinaryString2, BinaryInput.BinaryAmount);
      // convert them to decimal	  
      Decimal1 = BinToDec(BinaryString1);
      Decimal2 = BinToDec(BinaryString2);
      if (Decimal2 < 0)
         strcpy (BinaryResult, "ERROR: negative power attempted");
      else
      {
         // perform raise to power, save result as long double	  
         temp = pow(Decimal1, Decimal2);
         cout.precision(50);	  
         cout << "Decimal Result = " << temp << "\n";	  	  
         // check if overflow
         if (temp > 2147483647 || temp < -2147483647)
            strcpy(BinaryResult, "OVERFLOW on raise to power");	  	  
         else
         {
            DecimalResult = long int (temp);	  
            // convert to binary
            DecToBin(DecimalResult, BinaryResult);
         }
      }
   } // END PowBin
   // ******************************
   //
   // Bitwise OR Binary function
   //
   // ******************************	
   void OrBin (const BaseTwo &BinaryInput, char BinaryResult[]) const
   {
      char BinaryString1[33], BinaryString2[33]; // input strings
      unsigned int pos1, pos2; // bit position for string1, string2
      char c1, c2; // temp char for string1, string2
      // make all digits of binary result zero
      for (int i=0; i<=31; i++)
         BinaryResult[i] = '0';
      // set end of string
      BinaryResult[32] = '\0';
      // save two input binary strings
      strcpy(BinaryString1, BinaryAmount);
      strcpy(BinaryString2, BinaryInput.BinaryAmount);
      i = 31; // start at low bit (rightmost) of binary result
      // start at low bit (rightmost) of input strings	  
      pos1 = strlen(BinaryString1) - 1;
      pos2 = strlen(BinaryString2) - 1;
      // loop through all 31 bits of binary result string	  	  
      while (i > 0)
      {
         if (pos1 > 0)
            c1 = BinaryString1[pos1]; // get the bit value
         else
            c1 = '0'; // if reached first bit, fill with 0
         if (pos2 > 0)
            c2 = BinaryString2[pos2]; // get the bit value
         else
            c2 = '0'; // if reached first bit, fill with 0
         // perform bitwise OR, either c1 or c2, make 1
         // otherwise leave 0		 
         if (c1 == '1' || c2 == '1')
            BinaryResult[i] = '1';
         i--;           // decrement result bit position
         if (pos1 > 0)
            pos1--;     // decrement string1 bit position
         if (pos2 > 0)
            pos2--;     // decrement string2 bit position
      } // END WHILE
      // check for sign bit (position 0)
      c1 = BinaryString1[0];
      c2 = BinaryString2[0];
      if (c1 == '1' || c2 == '1')
         BinaryResult[0] = '1';
   } // END OrBin
   // ***************************************
   //
   // Bitwise Exclusive OR Binary function
   //
   // ***************************************
   void XOrBin(const BaseTwo &BinaryInput, char BinaryResult[]) const
   {
      char BinaryString1[33], BinaryString2[33]; // input strings
      unsigned int pos1, pos2; // bit position for string1, string2
      char c1, c2; // temp char for string1, string2
      // make all digits of binary result zero
      for (int i=0; i<=31; i++)
         BinaryResult[i] = '0';
      // set end of string
      BinaryResult[32] = '\0';
      // save two input binary strings
      strcpy(BinaryString1, BinaryAmount);
      strcpy(BinaryString2, BinaryInput.BinaryAmount);
      i = 31; // start at low bit (rightmost) of binary result
      // start at low bit (rightmost) of input strings	  
      pos1 = strlen(BinaryString1) - 1;
      pos2 = strlen(BinaryString2) - 1;
      // loop through all 31 bits of binary result string	  	  
      while (i > 0)
      {
         if (pos1 > 0)
            c1 = BinaryString1[pos1]; // get the bit value
         else
            c1 = '0'; // if reached first bit, fill with 0
         if (pos2 > 0)
            c2 = BinaryString2[pos2]; // get the bit value
         else
            c2 = '0'; // if reached first bit, fill with 0
         // perform bitwise XOR, either c1 or c2, make 1
         // if both 0 or both 1 leave 0		 
         if ((c1 == '0' && c2 == '1') || (c1 == '1' && c2 == '0'))
            BinaryResult[i] = '1';
         i--;           // decrement result bit position
         if (pos1 > 0)
            pos1--;     // decrement string1 bit position
         if (pos2 > 0)
            pos2--;     // decrement string2 bit position
      } // END WHILE
      // check for sign bit (position 0)
      c1 = BinaryString1[0];
      c2 = BinaryString2[0];
      if ((c1 == '0' && c2 == '1') || (c1 == '1' && c2 == '0'))
         BinaryResult[0] = '1';
   } // END XOrBin
   // *********************************
   //
   // Bitwise AND Binary function
   //
   // *********************************	
   void AndBin(const BaseTwo &BinaryInput, char BinaryResult[]) const
   {
      char BinaryString1[33], BinaryString2[33]; // input strings
      unsigned int pos1, pos2; // bit position for string1, string2
      char c1, c2; // temp char for string1, string2
      // make all digits of binary result zero
      for (int i=0; i<=31; i++)
         BinaryResult[i] = '0';
      // set end of string
      BinaryResult[32] = '\0';
      // save two input binary strings
      strcpy(BinaryString1, BinaryAmount);
      strcpy(BinaryString2, BinaryInput.BinaryAmount);
      i = 31; // start at low bit (rightmost) of binary result
      // start at low bit (rightmost) of input strings	  
      pos1 = strlen(BinaryString1) - 1;
      pos2 = strlen(BinaryString2) - 1;
      // loop through all 31 bits of binary result string	  	  
      while (i > 0)
      {
         if (pos1 > 0)
            c1 = BinaryString1[pos1]; // get the bit value
         else
            c1 = '0'; // if reached first bit, fill with 0
         if (pos2 > 0)
            c2 = BinaryString2[pos2]; // get the bit value
         else
            c2 = '0'; // if reached first bit, fill with 0
         // perform bitwise AND, both c1 and c2, make 1
         // otherwise leave 0		 
         if (c1 == '1' && c2 == '1')
            BinaryResult[i] = '1';
         i--;           // decrement result bit position
         if (pos1 > 0)
            pos1--;     // decrement string1 bit position
         if (pos2 > 0)
            pos2--;     // decrement string2 bit position
      } // END WHILE
      // check for sign bit (position 0)
      c1 = BinaryString1[0];
      c2 = BinaryString2[0];
      if (c1 == '1' && c2 == '1')
         BinaryResult[0] = '1';
   } // END AndBin
   
   // *****************************************
   //
   // Bitwise NOT Binary function definition
   //
   // *****************************************   
   void NotBin(char BinaryResult[]) const
   {
      char BinaryString1[33]; // input string1
      unsigned int pos1; // bit position for string1
      char c1; // temp char for string1
      // make all digits of binary result zero
      for (int i=0; i<=31; i++)
         BinaryResult[i] = '0';
      // set end of string
      BinaryResult[32] = '\0';
      // save input binary string
      strcpy(BinaryString1, BinaryAmount);	  
      i = 31; // start at low bit (rightmost) of binary result
      // start at low bit (rightmost) of input strings	  
      pos1 = strlen(BinaryString1) - 1;	  
      // loop through all 31 bits of binary result string	  	  
      while (i > 0)
      {
         if (pos1 > 0)
            c1 = BinaryString1[pos1]; // get the bit value
         else
            c1 = '0'; // if reached first bit, fill with 0
         // perform bitwise NOT, opposite value of c1		 		 
         if (c1 == '0')
            BinaryResult[i] = '1';
         else
            BinaryResult[i] = '0';		 
         i--;           // decrement result bit position
         if (pos1 > 0)
            pos1--;     // decrement string1 bit position
      } // END WHILE
      // check for sign bit (position 0)
      c1 = BinaryString1[0];
      if (c1 == '0')
         BinaryResult[0] = '1';
      else
         BinaryResult[0] = '0';
   } // END NotBin
   // *************************************
   //
   // Compare Binary Numbers function
   //
   // *************************************
   int CompareBin(const BaseTwo &BinaryInput) const
   {
      long int Decimal1, Decimal2;
      char BinaryString1[33], BinaryString2[33];
      // save two binary strings	  	  
      strcpy(BinaryString1, BinaryAmount);
      strcpy(BinaryString2, BinaryInput.BinaryAmount);
      // convert them to decimal	  
      Decimal1 = BinToDec(BinaryString1);
      Decimal2 = BinToDec(BinaryString2);
      int CompareResult = 0;     // if equal  = 0	  
      if (Decimal1 < Decimal2)
         CompareResult = -1;    // if 1 < 2  = -1
      if (Decimal1 > Decimal2)   
         CompareResult = 1;     // if 1 > 2  = +1
      return CompareResult;	  	  	  
   } // END CompareBin   
}; // END Class BaseTwo definition
//
// GetAVariable function prototype
//
bool GetAVariable (char Prompt[50], BaseTwo BinaryArray[99], int NumOfVars, int &i);
//
// MAIN starts here
//
void main()
{
   BaseTwo BinaryArray[99]; // allow up to 99 variables
   BaseTwo TempOne;         // TempOne set to "01"
   TempOne.SetOne();        // for increment/decrement
   int NumOfVars = 0;       // number of variables entered   	
   bool Found, Found2;      // bool for variable name found
   int i,j;                 // int i,j for loops
   int Result;              // for comparison function   
   char BinaryString[80];   // temp binary amount   	
   char menu[80], c;        // char for menu selection	
   // ***************************************************
   //
   // menu infinite loop, quits with exit(0) when done
   //
   // ***************************************************		
   while (1)
   {
      cout << "\nMake a selection: (type ? for menu options) ";
      cin.getline(menu,80);
      c = toupper(menu[0]); // get first char, make UPPERCASE, ignore rest				
      switch (c)
      {
      case 'A' :
      //
      // Enter a new variable and amount
      //
      {   
         if (NumOfVars < 99)
         {
            // increment number of variables
            // get both variable name and binary amount
            NumOfVars++;
            BinaryArray[NumOfVars].GetVariableName();
            BinaryArray[NumOfVars].GetBinaryAmount();
         }
         else
            cout << "Sorry, the variable list is full\n";		  
            break; // break out of SWITCH statement
      }
      case 'B' :
      //
      // List all variables and amounts
      //
      {
         if (NumOfVars < 1)
            cout << "Sorry, the variable list is empty\n";
         else
         {
            // we have at least one variable
            // display headings, variables and amounts
            cout << "\nVariable              Binary Amount\n";
            cout << "========              =============\n\n";
            for (i=1; i<=NumOfVars; i++)
               BinaryArray[i].DisplayVariable();
         }
         break; // break out of SWITCH statement
      }
      case 'C' :
      //
      // Change an existing amount
      //
      {
         cout << "CHANGE AN EXISTING BINARY AMOUNT\n";
         Found = GetAVariable ("Enter the variable name to change", BinaryArray, NumOfVars, i);
         if (Found) // if variable exists, get new binary amount
            BinaryArray[i].GetBinaryAmount();
         else
            cout << "Sorry, variable name not found\n";
         break; // break out of SWITCH statement
      }
      case 'D' :
      //
      // Clear/Delete variables list
      //
      {
         cout << "Are you sure you want to delete ALL variables? (y/n) ";
         cin.getline(menu,80);
         c = menu[0];
         if (c == 'y') // if user confirms clear list
         {
            NumOfVars = 0;
            cout << "Variables list deleted!\n";
         }
         break; // break out of SWITCH statement
      }
      case 'E' :
      //
      // Add two variables
      //
      {
         cout << "ADD TWO VARIABLES -- Format: Var1 + Var2\n";
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for addition", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for addition", BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, add them using AddBin
            BinaryArray[i].AddBin(BinaryArray[j], BinaryString);
            cout << "The result of the addition = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";         
         break; // break out of SWITCH statement		 
      }
      case 'F' :
      //
      // Subtract two variables
      //
      {
         cout << "SUBTRACT TWO VARIABLES -- Format: Var1 - Var2\n";
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for subtraction", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for subtraction", BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, subtract them using SubBin
            BinaryArray[i].SubBin(BinaryArray[j], BinaryString);
            cout << "The result of the subtraction = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";						
         break; // break out of SWITCH statement
      }
      case 'G' :
      //
      // Multiply two variables
      //
      {
         cout << "MULTIPLY TWO VARIABLES -- Format: Var1 * Var 2\n";
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for multiplication", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for multiplication", BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, multiply them using MulBin
            BinaryArray[i].MulBin(BinaryArray[j], BinaryString);
            cout << "The result of the multiplication = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";		 
         break; // break out of SWITCH statement
      }
      case 'H' :
      //
      // Divide (integer division) two variables
      //
      {
         cout << "(Integer) DIVIDE TWO VARIABLES -- Format: Var1 / Var2\n";		
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for division", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for division", BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, divide them using DivBin
            BinaryArray[i].DivBin(BinaryArray[j], BinaryString);
            cout << "The result of the (integer) division = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";			
         break; // break out of SWITCH statement
      }
      case 'I' :
      //
      // Increment a variable
      //
      {
         cout << "INCREMENT A VARIABLE\n";
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter the variable name to increment", BinaryArray, NumOfVars, i);
         if (Found)
         {
            // variable found, increment using TempOne "01" with AddBin
            BinaryArray[i].AddBin(TempOne, BinaryString);
            cout << "The result of the increment = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, the variable name is not found\n";			
         break; // break out of SWITCH statement
      }
      case 'J' :
      //
      // Decrement a variable
      //
      {
         cout << "DECREMENT A VARIABLE\n";
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter the variable name to decrement", BinaryArray, NumOfVars, i);
         if (Found)
         {
            // variable found, decrement using TempOne "01" with SubBin
            BinaryArray[i].SubBin(TempOne, BinaryString);
            cout << "The result of the decrement = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, the variable name is not found\n";					
         break; // break out of SWITCH statement
      }
      case 'K' :
      //
      // Modulus function
      //
      {
         cout << "MODULUS (REMAINDER) WITH TWO VARIABLES -- Format: Var1 MOD Var2\n";			
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for modulus", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for modulus", BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, find modulus (remainder) using ModBin
            BinaryArray[i].ModBin(BinaryArray[j], BinaryString);
            cout << "The result of modulus = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";			
         break; // break out of SWITCH statement
      }
      case 'L' :
      //
      // Raise to Power function
      //
      {
         cout << "RAISE TO POWER WITH TWO VARIABLES -- Format: Var1 RAISED TO Var2\n";
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for raise to power", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for raise to power", BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, raise to power using PowBin
            BinaryArray[i].PowBin(BinaryArray[j], BinaryString);
            cout << "The result of raise to power = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";						
         break; // break out of SWITCH statement
      }
      case 'M' :
      //
      // Binary OR
      //
      {
         cout << "BITWISE BINARY (OR) ON TWO VARIABLES -- Format: Var1 OR Var2\n";			
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for bitwise OR", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for bitwise OR", BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, perform bitwise OR with OrBin
            BinaryArray[i].OrBin(BinaryArray[j], BinaryString);
            cout << "The result of bitwise OR = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";			
         break; // break out of SWITCH statement
      }
      case 'N' :
      //
      // Binary AND
      //
      {
         cout << "BITWISE BINARY (AND) ON TWO VARIABLES -- Format: Var1 AND Var2\n";			
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for bitwise AND", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for bitwise AND", BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, perform bitwise AND with AndBin
            BinaryArray[i].AndBin(BinaryArray[j], BinaryString);
            cout << "The result of bitwise AND = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";			
         break; // break out of SWITCH statement
      }
      case 'O' :
      //
      // Binary XOR
      //
      {
         cout << "BITWISE BINARY (EXCLUSIVE OR) ON TWO VARIABLES -- Format: Var1 XOR Var2\n";			
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for bitwise XOR", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for bitwise XOR", BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, perform bitwise XOR with XOrBin
            BinaryArray[i].XOrBin(BinaryArray[j], BinaryString);
            cout << "The result of bitwise XOR = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";			
         break; // break out of SWITCH statement
      }
      case 'P' :
      //
      // Binary NOT
      //
      {
         cout << "BITWISE BINARY (NOT) ON A VARIABLE -- Format: NOT Var1\n";			
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for bitwise NOT", BinaryArray, NumOfVars, i);
         if (Found)
         {
            // variable found, perform bitwise NOT with NotBin
            BinaryArray[i].NotBin(BinaryString);
            cout << "The result of bitwise NOT = " << BinaryString << "\n";
         }
         else
            cout << "Sorry, the variable name is not found\n";			
         break; // break out of SWITCH statement
      }
      case 'Q' :
      //
      // Compare < (less than)
      //
      {
         cout << "COMPARE < TWO VARIABLES -- Format: Is Var1 < Var2 ?\n";			
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for < compare", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for < compare",BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, compare them using CompareBin
            Result = BinaryArray[i].CompareBin(BinaryArray[j]);
            // if Result < 0 then Var1 < Var2			
            if (Result < 0)
               strcpy (BinaryString, "TRUE");
            else
               strcpy (BinaryString, "FALSE");
            cout << "The result of < compare is " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";			
         break; // break out of SWITCH statement
      }
      case 'R' :
      //
      // Compare <= (less than or equal)
      //
      {
         cout << "COMPARE <= TWO VARIABLES -- Format: Is Var1 <= Var2 ?\n";			
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for <= compare", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for <= compare",BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, compare them using CompareBin
            Result = BinaryArray[i].CompareBin(BinaryArray[j]);
            // if Result <= 0 then Var1 <= Var2			
            if (Result <= 0)
               strcpy (BinaryString, "TRUE");
            else
               strcpy (BinaryString, "FALSE");
            cout << "The result of <= compare is " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";			
         break; // break out of SWITCH statement
      }
      case 'S' :
      //
      // Compare > (greater than)
      //
      {
         cout << "COMPARE > TWO VARIABLES -- Format: Is Var1 > Var2 ?\n";			
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for > compare", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for > compare",BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, compare them using CompareBin
            Result = BinaryArray[i].CompareBin(BinaryArray[j]);
            // if Result > 0 then Var1 > Var2			
            if (Result > 0)
               strcpy (BinaryString, "TRUE");
            else
               strcpy (BinaryString, "FALSE");
            cout << "The result of > compare is " << BinaryString << "\n";
            }
         else
            cout << "Sorry, one of the variable names not found\n";			
         break; // break out of SWITCH statement
      }
      case 'T' :
      //
      // Compare >= (greater than or equal)
      //
      {
         cout << "COMPARE >= TWO VARIABLES -- Format: Is Var1 >= Var2 ?\n";			
         // call the GetAVariable function, returns true if variable found		          
         Found = GetAVariable ("Enter Var1 for >= compare", BinaryArray, NumOfVars, i);
         Found2 = GetAVariable ("Enter Var2 for >= compare",BinaryArray, NumOfVars, j);
         if (Found && Found2)
         {
            // both variables found, compare them using CompareBin
            Result = BinaryArray[i].CompareBin(BinaryArray[j]);
            // if Result >= 0 then Var1 >= Var2			
            if (Result >= 0)
               strcpy (BinaryString, "TRUE");
            else
               strcpy (BinaryString, "FALSE");
            cout << "The result of >= compare is " << BinaryString << "\n";
         }
         else
            cout << "Sorry, one of the variable names not found\n";			
         break; // break out of SWITCH statement
      }
      case '?' :
      //
      // Display the full menu options
      //
      {
         cout << "\n                 Menu and Binary Operations\n";
         cout << "                 ==========================\n\n";
         cout << "(A) Enter a new variable and amount (B) List all variables and amounts\n";
         cout << "(C) Change an existing amount       (D) Clear/Delete variables list\n";
         cout << "(E) Add two variables               (F) Subtract two variables\n";
         cout << "(G) Multiply two variables          (H) (integer) Divide two variables\n";
         cout << "(I) Increment a variable            (J) Decrement a variable\n";
         cout << "(K) Modulus function                (L) Raise to Power function\n";
         cout << "(M) Binary OR                       (N) Binary AND\n";
         cout << "(O) Binary XOR                      (P) Binary NOT\n";
         cout << "(Q) Compare < (less than)           (R) Compare <= (less than or equal)\n";
         cout << "(S) Compare > (greater than)        (T) Compare >= (greater than or equal)\n";
         cout << "(X) Exit\n";
         break; // break out of SWITCH statement
      }
      case 'X' : exit(0);
      default : cout << "Sorry, that item is not a selection\n";			   
      } // END SWITCH		
   } // END WHILE MENU
} // END MAIN
// ****************************************
//
// GetAVariable function definition
//
// ****************************************
bool GetAVariable (char Prompt[], BaseTwo BinaryArray[], int NumOfVars, int &i)
{
   char VarName[80];   	
   cout << Prompt << "\n";
   cin.getline(VarName,80);
   // check if variable exists, set to not found
   for (i=1; i<=NumOfVars; i++)
   {
      if (BinaryArray[i].CheckForVariable(VarName))
         return true;
   }
   return false;
}

END OF FILE GO TO TOP