// Binary Calculator v0.1
// Binary Calculator v0.1
// Programmer: Bill McQuain
// Platform : P120, Win95, Visual C++ 4.0
// Completed : November 7, 1996
// Completed : November 7, 1996
// Purpose:
// Purpose:
// This program reads simple binary arithmetic expressions from an
// input file (binary.dat), converts the operands to decimal, performs
// the operation and writes the expressions and results to a file
// (binary.out).
// (binary.out).
// It is assumed the binary operands are valid binary numbers; but
// the operator is validated (+, -, *, or /). All calculations are
// integer.
// integer.
#include <fstream.h> // for file streams
#include <iomanip.h> // for manipulators
#include <ctype.h> // for isdigit()
//////////////////////////////////////////////////////////////////////
// Function prototypes:
// Function prototypes:
int BinToDecimal(ifstream& );
char GetOperation(ifstream& );
void SkipWhiteSpace(ifstream& );
int CalcIt(int , int , char );
void PrintResults(ofstream& ,int , int , char , int );
//////////////////////////////////////////////////////////////////////
int main() {
int FirstOperand = 0, // the first operand (in decimal)
SecondOperand = 0; // the second operand (in decimal)
char Operation = '!'; // the operator
int Result; // result of performing the operation
// on the two operands
ifstream inbin; // input file stream
ofstream outbin; // output file stream
///////////////////////////////////////////////////////////////////
// Open files and enable manipulators:
// Open files and enable manipulators:
inbin.open("binary.dat");
outbin.open("binary.out");
outbin.setf(ios::fixed, ios::floatfield);
outbin.setf(ios::showpoint);
///////////////////////////////////////////////////////////////////
// Each pass through the while loop reads the operands and
// operator from a line of the input file, performs the operation
// (if valid) and writes the results to the output file.
// (if valid) and writes the results to the output file.
// The loop will terminate when the end of the input file is
// reached. Note: this assumes the EOF will occur precisely
// after the final bit of the second operand on the last line.
// after the final bit of the second operand on the last line.
while (!inbin.eof()) {
FirstOperand = BinToDecimal(inbin);
Operation = GetOperation(inbin);
SecondOperand = BinToDecimal(inbin);
Result = CalcIt(FirstOperand, SecondOperand, Operation);
PrintResults(outbin, FirstOperand, SecondOperand, Operation,
Result);
}
///////////////////////////////////////////////////////////////////
// Close the input and output files:
inbin.close();
outbin.close();
///////////////////////////////////////////////////////////////////
// Return the (final) value of FirstOperand --- useful when the
// code is being checked.
// code is being checked.
return FirstOperand;
}
//////////////////////////////////////////////////////////////////////
// BinToDecimal reads a binary string from the input stream,
// converts it to decimal and returns the decimal value. If there's
// any whitespace preceding the binary string, it's consumed here.
// any whitespace preceding the binary string, it's consumed here.
// Parameters:
// infile input file stream
// infile input file stream
// Return value:
// DecNumber decimal value of binary string read from input file
// DecNumber decimal value of binary string read from input file
int BinToDecimal(ifstream& infile) {
char ThisBit; // last character read from stream
int DecNumber = 0; // decimal value of binary string
SkipWhiteSpace(infile); // skip whitespace (if any) preceding the
// binary string
infile.get(ThisBit); // read (probable) first bit
///////////////////////////////////////////////////////////////////
// As long as we're still reading bits, update value of DecNumber
// and get another character:
// and get another character:
while (ThisBit == '0' || ThisBit == '1') {
switch (ThisBit) {
case '0': DecNumber = 2*DecNumber;
break;
case '1': DecNumber = 2*DecNumber + 1;
break;
}
infile.get(ThisBit); // get the next character
}
///////////////////////////////////////////////////////////////////
// Whatever the last character read above was, it wasn't part of
// this operand, so put it back and let the next function called
// deal with it:
// deal with it:
infile.putback(ThisBit);
///////////////////////////////////////////////////////////////////
// Return the decimal value of the binary string to the caller:
// Return the decimal value of the binary string to the caller:
return DecNumber;
}
//////////////////////////////////////////////////////////////////////
// GetOperation reads the operator from the input stream and returns
// it to the caller (as a character). Note that I assume the next
// nonwhitespace character after the first operand is the operator,
// which is the only way the input line could be syntactically
// correct.
// correct.
// If there's any whitespace preceding the operator it's consumed
// here.
// here.
// Parameters:
// infile input file stream
// infile input file stream
// Return value:
// Operator decimal value of binary string read from input file
// Operator decimal value of binary string read from input file
char GetOperation(ifstream& infile) {
char Operator; // the operator
SkipWhiteSpace(infile); // skip any preceding whitespace
infile.get(Operator); // read the operator
return Operator; // return it to the caller
}
//////////////////////////////////////////////////////////////////////
// CalcIt computes and returns the result of performing the operation
// on the two operands, if a valid operator was found. If the
// operator was not valid, a value of -1 is returned (something must
// be returned, might as well be -1).
// be returned, might as well be -1).
// Parameters:
// First the first operand
// Second the second operand
// Op the operator (as a character)
// Op the operator (as a character)
// Return value:
// Result the result of the integer operation
// Result the result of the integer operation
int CalcIt(int First, int Second, char Op) {
int Result; // the result
///////////////////////////////////////////////////////////////////
// Determine which operator was found and compute the correct
// result for that case. The guard against a division by zero
// was not specifically required but should be done.
// was not specifically required but should be done.
switch (Op) {
case '+': Result = First + Second;
break;
case '-': Result = First - Second;
break;
case '*': Result = First * Second;
break;
case '/': if (Second != 0)
Result = First / Second;
else
Result = -1;
break;
default : Result = -1;
}
return Result; // return the result to the caller
}
//////////////////////////////////////////////////////////////////////
// SkipWhiteSpace reads characters from the input file until it finds
// a nonwhitespace character and leaves that character at the front
// of the input stream.
// of the input stream.
// Parameters:
// infile input file stream
// infile input file stream
void SkipWhiteSpace(ifstream& infile) {
char ch; // last character read from stream
infile.get(ch); // read a character
///////////////////////////////////////////////////////////////////
// As long as we're reading whitespace, continue reading:
// As long as we're reading whitespace, continue reading:
while (ch == ' ' || ch == '\t' || ch == '\n')
infile.get(ch);
///////////////////////////////////////////////////////////////////
// The last character we read was not whitespace, so put it back:
// The last character we read was not whitespace, so put it back:
infile.putback(ch);
}
//////////////////////////////////////////////////////////////////////
// PrintResults prints out the expression just read (in decimal), and
// either the value of that expression or an error message, as
// appropriate.
// appropriate.
// Parameters:
// outfile output file stream
// First first operand
// Second second operand
// Op operator
// Result result of performing operation on operands
// Result result of performing operation on operands
void PrintResults(ofstream& outfile, int First, int Second, char Op,
int Result) {
outfile << setw(5) << First; // print first operand
outfile << setw(3) << Op; // and operator
outfile << setw(5) << Second; // and second operand
outfile << " = " // and the equals sign
///////////////////////////////////////////////////////////////////
// If the operator isn't valid, print an error message. Otherwise
// if there's a divide-by-zero, print an error message. Otherwise
// just print the result:
// just print the result:
if (Op != '+' && Op != '-' && Op != '*' && Op != '/')
outfile << "invalid operation" << endl;
else
if (Op == '/' && Second == 0)
outfile << "attempt to divide by zero" << endl;
else
outfile << setw(5) << Result << endl;
}