UQ Students should read the Disclaimer & Warning

Note: This page dates from 2005, and is kept for historical purposes.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>COMP2301 - Assignment 4 - File I/O in C++</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
<!--
.wrong {
    background: #FF9999;
}
body {
    background: url(_img/DSC04989.jpg) fixed center;
    font-family: "Arial Unicode MS", Arial, Helvetica, sans-serif;
}
th, td, textarea {
    border: 1px solid #000000;
    padding: 0 1ex;
    background: transparent;
    overflow: hidden;
}
table {
    border: none;
}
-->
</style>
</head>
<body> 
<h1>COMP2301 &ndash; Assignment Four &ndash; File I/O in C++</h1> 
<p> This assignment is a pass/fail assignment. I achieved a pass.</p> 
<p>The goal of this assignment is to gain experience using C++ for object-oriented
    programming. </p> 
<p> In this assignment, you will become familiar with: </p> 
<ul> 
    <li>C++ I/O methods: operator &lt;&lt; and operator &gt;&gt; </li> 
    <li>Use of classes in C++ </li> 
    <li>Some aspects of the standard template library (STL) </li> 
</ul> 
<h2>Specification </h2> 
<p>Develop a command-line program to read and manipulate a file of internet banking
    transactions. Each individual transaction starts on a new line and contains
    six comma separated transaction details. </p> 
<ol> 
    <li> Timestamp: 10-digit: [yymmddhhnnss],&nbsp;&nbsp; [yy] = year, [mm] = month,
        [dd] = day, [hh] = hour (from [00] to [23]), [nn] = minutes,&nbsp; [ss] = seconds. </li> 
    <li> Customer’s last name: </li> 
    <li> Customer reference number: 10-digit number. </li> 
    <li> Account type : “Check” for (Checking account), “Sav” for (Savings account)
        or “Cred” for (Credit card account). </li> 
    <li> Transaction type : “Dep” for (Deposit) or “With” for (Withdrawal). </li> 
    <li> Transaction amount: [dollars.cc], where [dolars] = integer dollars and&nbsp; [cc]
        = integer cents. </li> 
</ol> 
<p>Example input file containing four transaction: <em>( Timestamp,
        Customer’s last name, customer reference number, Account type , Transaction
        type , Transaction amount ) </em><br /> 
    <textarea name="a" cols="82" rows="4" readonly="readonly" title="Sample Input File">0405031220, Howard, 6434199921, Check, With, 230.20 
0405040936, Schwarzenegger, 4873123321, Sav, Dep, 5000000.00 
0405031322, Jackson, 3856927195, Cred, With, 2500.00 
0405051816, Schwarzenegger, 4873123321, Sav, With, 2000000.00 </textarea> 
      </p> 
<h2>Functions required for the command line interface </h2> 
<ul> 
    <li> The program sorts the transactions when run from the command line in three
        ways: <br /> 
&nbsp;&nbsp;&nbsp; transactionlist [ [/t] | [/n] | [/c] ] INPUTFILE [OUTPUTFILE] <br /> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /t
[DEFAULT]&nbsp;&nbsp;&nbsp; : sort transactions in Numeric order by Time Stamp <br /> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :
sort transactions in Alphabetic order by Last Name <br /> 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; :
sort transactions in Numeric order by Time Stamp of combined deposit balance </li> 
    <li> An error is generated if more than one command line switch is entered. </li> 
    <li> If no command line switch is entered the default operation executes and
        the program writes the sorted transactions to standard output (cout). </li> 
    <li> If an [OUTPUTFILE] is specified the program writes the sorted transactions
        to the named file.&nbsp; Existing file content should be overwritten. </li> 
    <li> If [/c] the combined balance switch is entered all transactions with identical
        customer reference numbers AND identical account types must be combined into
        one transaction.
        <ul> 
            <li> Time stamp of the combined transaction = Time stamp of the last transaction
                that corresponds to the appropriate customer reference number and account
                type </li> 
            <li> Transaction type of the combined transaction is “CombDep” (CombinedDeposit) </li> 
            <li> Transaction amount is the [sum of all appropriate deposits] - [sum of
                all appropriate withdrawals] </li> 
        </ul> 
    </li> 
    <li> You are to implement the operator &lt;&lt;, operator &gt;&gt;, operator
        /=, operator + and comparison operators.
        <ul> 
            <li> operator &lt;&lt;, operator &gt;&gt; are to be used to read the file
                and write to cout. </li> 
            <li> operator /=&nbsp; is used to test if two transactions have identical
                customer reference numbers AND account types. </li> 
            <li> operator + combines two transactions. </li> 
        </ul> 
    </li> 
</ul> 
<h2>General </h2> 
<ul> 
    <li> You will need to write a class called “transaction” in this assignment. </li> 
    <li> You must <strong>NOT</strong>use stdio.h (i.e. scanf, printf, etc.). </li> 
    <li> You may use strcpy, sscanf, and other string manipulation routines included
        in string.h. </li> 
    <li> You <strong>MUST</strong> use the Standard Template Library’s list (or
        vector). </li> 
    <li> Running your program with no command line parameters must generate a usage
        statement. </li> 
    <li> All transactions with identical customer reference numbers have identical
        last names </li> 
    <li> Transaction amount for a combined balance may be negative. </li> 
    <li> Reasonable error checking is required, the program must handle the following
        events gracefully
        <ul> 
            <li> the specified input file does not exist. </li> 
            <li> an incorrect number of command line parameters are given. </li> 
            <li> the file contains invalid records or an invalid record structure. </li> 
        </ul> 
    </li> 
    <li> <a href="#h">Transaction.h</a> header file may be obtained by downloading
        the Zip file for assignment 4.</li> 
</ul> 
<p><a href=".//COMP2301-assignment-4-transaction.exe" title="Downloadable application - Stopwatch">Compiled
        (WIN32) binary</a> (188 KB)<br /> 
    <a href="#h">transaction.h</a><br /> 
    <a href="#cpp">transaction.cpp</a></p> 
<p>transaction.h<br /> 
    <textarea name="h" cols="82" rows="180" readonly="readonly" title="C++ Header File">/*
 *
 *    Subsystem:        TRANSACTION
 *
 *    File Name:        transaction.h
 *
 *    Author:            Stefan Lehmann
 *    Modified:        Ned Martin 40529927, 18-MAY-2004
 *
 *    Date Created:        07/03/2004
 *
 *    Description:        Header file for Transaction class.
 *
 */

#ifndef __TRANSACTION_H__
#define __TRANSACTION_H__

class Transaction;

istream&amp; operator >> (istream&amp; ioStream, Transaction&amp; iTransaction);
ostream&amp; operator &lt;&lt; (ostream&amp; ioStream, const Transaction&amp; iTransaction);

class Transaction
{
public:

    /*
     * Name:    Transaction()
     *
     * Purpose:    Default Constructor
     *
     * Method:    Initialise data members
     */
    Transaction();

    /*
     * Name:    Transaction()
     *
     * Purpose:    Constructor with arguments
     *
     * Method:    Initialise data members with given info
     */
    Transaction(long iTimeStamp, char *iCustomerName, long iCustomerRefNum, 
        char *iAccountType, char *iTransactionType, float iAmount);


    /*
     * Name:    ~Transaction()
     *
     * Purpose:    Destructor
     *
     * Method:    Deallocate memory
     */
    ~Transaction();


    // operators

    /*
     * Name:    operator ==
     *
     * Purpose:    Equality operator
     *
     * Method:    Checks if Transaction is the same.
     */
    bool operator== (const Transaction&amp; iRightParameter);

    /*
     * Name:    operator !=
     *
     * Purpose:    Inequality operator
     *
     * Method:    Checks if Transaction is NOT the same.
     */
    bool operator!= (const Transaction&amp; iRightParameter);


    /*
     * Name:    operator /=
     *
     * Purpose:    Combined transaction test operator
     *
     * Method:    Checks if Transaction has identical customer ref#
     *        and account type
     */
    bool operator/= (const Transaction&amp; iRightParameter);

    /*
     * Name:    operator &lt;
     *
     * Purpose:    Less than
     *
     * Method:    Checks if Transaction is less than.
     */
    bool operator&lt; (const Transaction&amp; iRightParameter);

    /*
     * Name:    operator >
     *
     * Purpose:    Greater than
     *
     * Method:    Checks if Transaction is greater than.
     */
    bool operator> (const Transaction&amp; iRightParameter);

    /*
     * Name:    operator =
     *
     * Purpose:    Copy
     *
     * Method:    Ensure a deep copy.
     */
    Transaction&amp; operator= (const Transaction&amp; iRightParameter);

    /*
     * Name:    operator +
     *
     * Purpose:    Combine
     *
     * Method:    Combine Transaction with other Transaction
     */
    Transaction&amp; operator+ (const Transaction&amp; iRightParameter);


    static void Transaction::setSortBy (int iFieldToSortBy)
    {
        mSortBy = iFieldToSortBy;
    }

    // Friend functions

    /*
     * Name:    operator >>
     *
     * Purpose:    Input operation
     *
     * Method:    Assume comma separated values, Time Stamp first.
     */
    friend istream&amp; operator >> (istream&amp; ioStream,
        Transaction&amp; iTransaction);

    /*
     * Name:    operator &lt;&lt;
     *
     * Purpose:    Output operation
     *
     * Method:    Output comma separated values, Time Stamp first.
     */
    friend ostream&amp; operator &lt;&lt; (ostream&amp; ioStream, 
        const Transaction&amp; iTransaction);


    enum
    {
        kSORT_BY_TIMESTAMP
    };


private:

    static int mSortBy;
    // Insert Transaction data entries here

    // Transaction data entries
    long    TimeStamp;
    char    CustomerName[300];

    // value exceeds long, changed to char array
    char    CustomerRefNum[300];
    char    AccountType[300];
    char    TransactionType[300];
    float    Amount;


};


#endif //__TRANSACTION_H__
</textarea> 
</p> 
<p>transaction.cpp<br /> 
    <textarea name="cpp" cols="82" rows="574" readonly="readonly" title="C++ Code">/*
 * Author:        Ned Martin #40529927
 *
 * Creation Date:    18-MAY-2004
 *
 * Version:        FINAL 18-MAY-2004
 *
 * Copyright:        Copyright (c) 2004 Ned Martin, Student s40529927,
 *            for COMP2301, University of Queensland
 *
 * Description:        Assignment 4 for COMP2301
 *            Reads an input file, parses file for tokens, reads each
 *            line into a Transaction, stores Transactions in a list,
 *            and depending on commandline input, sorts list in a
 *            variety of ways, or combines specific Transactions,
 *            then either prints them out to cout or to a specified
 *            file. May also cause hair loss.
 *
 * Restrictions:    Basic error checking is performed on the input file,
 *            but generally it is assumed to be in a valid format as
 *            per the assignment specification.
 *
 * Usage:        [ [/t] | [/n] | [/c] ] INPUTFILE [OUTPUTFILE]
 *                /t [DEFAULT]    : sort transactions in Numeric
 *                order by Time Stamp
 *                /n        : sort transactions in
 *                Alphabetic order by Last Name
 *                /c        : sort transactions in Numeric
 *                order by Time Stamp of combined 
 *
 * Tab Stops:        Eight spaces
 */


#include &lt;stdlib.h>    // EXIT_SUCCESS, EXIT_FAILURE
#include &lt;iostream>    // cout, cerr, shift operators
#include &lt;fstream>    // file streams
#include &lt;list>        // list, iterator
#include &lt;string>    // strlen, string functions
#include &lt;iomanip>    // setw, setfill, setprecision


using namespace std;

#include &quot;transaction.h&quot;

bool combine;        // flag specifying when we are combining transactions

// set mSortBy to 0 so we sort by Numeric Order of Timestampe by default
int Transaction::mSortBy = 0;


/*
 * Function:    stripSpace
 *
 * Purpose:    Strips leading spaces from a string.
 *
 * Method:    Accepts pointer to char string and returns pointer to first
 *        non-space character in string pointed to.
 *
 * Returns:    char pointer to stripped string.
 */
char* stripSpace
(
    char* temp    // pointer to string
)
{
    int    ii;        // counter
    char    *p;        // holds temporary string

    p = temp;

    for (ii = 0; ii &lt; strlen (temp); ii++)
    {
        // first non-space char is found so exit loop
        if (!isspace (temp[ii]))
        {
            break;
        }
    }
    p += ii;

    strcpy (temp, p);
    return temp;

} // end stripSpace

/*
 * Name:    Transaction()
 *
 * Purpose:    Default Constructor
 *
 * Method:    Initialise data members
 *
 * Note:    There is nothing to do here.
 */
Transaction::Transaction()
{
    // There is nothing to initialise
}

/*
 * Name:    ~Transaction()
 *
 * Purpose:    Destructor
 *
 * Method:    Deallocate memory
 *
 * Note:    There is nothing to do here.
 */
Transaction::~Transaction()
{
    // There is nothing to destroy.
}



// begin redefining operators

/*
 * Name:    operator /=
 *
 * Purpose:    Combined transaction test operator
 *
 * Method:    Checks if Transaction has identical customer ref#
 *        and account type
 */
bool Transaction::operator/= 
(
    const Transaction&amp; iRightParameter    // right hand operand
)
{
    // return true when customer ref num and account type of both
    // transactions are equal
    return (!(strcmp (CustomerRefNum, iRightParameter.CustomerRefNum))
        &amp;&amp; !(strcmp (AccountType, iRightParameter.AccountType)));

} // end operator/=

/*
 * Name:    operator &lt;
 *
 * Purpose:    Less than
 *
 * Method:    Checks if Transaction is less than.
 */
bool Transaction::operator&lt; 
(
    const Transaction&amp; iRightParameter    // right hand operand
)
{
    // sorting by customer name
    if( mSortBy )
    {
        return (strcmp (CustomerName, iRightParameter.CustomerName)
            == -1);
    }
    // sorting by timestamp
    else
    {
        return (TimeStamp &lt; iRightParameter.TimeStamp);

    }
} // end operator&lt;

/*
 * Name:    operator >
 *
 * Purpose:    Greater than
 *
 * Method:    Checks if Transaction is greater than.
 *
 * Note:    This is not currently used.
 */
bool Transaction::operator> 
(
    const Transaction&amp; iRightParameter    // right hand operand
)
{
    // sorting by customer name
    if( mSortBy )
    {
        return (strcmp (CustomerName, iRightParameter.CustomerName)
            == 1);
    }
    // sorting by timestamp
    else
    {
        return (TimeStamp > iRightParameter.TimeStamp);

    }
} // end operator>

/*
 * Name:    operator +
 *
 * Purpose:    Combine
 *
 * Method:    Combine Transaction with other Transaction
 */
Transaction&amp; Transaction::operator+ 
(
    const Transaction&amp; iRightParameter    // right hand operand
)
{
    float    amount = 0;        // holds temporary amount

    // set timestamp to new timestamp only if new timestamp is newer
    if( iRightParameter.TimeStamp > TimeStamp )
    {
        TimeStamp = iRightParameter.TimeStamp;
    }

    // set type of transaction to &quot;CombDep&quot;
    strcpy (TransactionType, &quot;CombDep&quot;);

    // sum amounts
    // negative amount if transaction type is withdrawal
    if( strcmp (iRightParameter.TransactionType, &quot;With&quot;) == 0 )
    {
        amount -= iRightParameter.Amount;
    }
    // positive amount if transaction is deposit
    else
    {
        amount += iRightParameter.Amount;
    }
    // negative amount if transaction type is withdrawal
    if( strcmp (TransactionType, &quot;With&quot;) == 0 )
    {
        amount -= Amount;
    }
    // positive amount if transaction is deposit
    else
    {
        amount += Amount;
    }
    
    Amount = amount;

    return *this;
} // end operator+

/*
 * Name:    operator >>
 *
 * Purpose:    Input operation
 *
 * Method:    Assume comma separated values, Time Stamp first.
 */
istream&amp; operator >> 
(
    istream&amp; ioStream,        // input ioStream
    Transaction&amp; iTransaction    // output Transaction
)
{
    char    tempString[300];    // temporary array
    char    delim = ',';        // deliminator

    // tokenise on deliminators

    // long
    ioStream.getline (tempString, 256, delim);
    stripSpace(tempString);
    iTransaction.TimeStamp = atol (tempString);

    // invalid timestamp
    if( !(iTransaction.TimeStamp > 0) )
    {
        cerr &lt;&lt; &quot;Invalid Input Detected&quot; &lt;&lt; endl;
        exit (EXIT_FAILURE);
    }
    
    //char[]
    ioStream.getline (tempString, 256, delim);
    stripSpace(tempString);
    strcpy (iTransaction.CustomerName, tempString);

    // long
    ioStream.getline (tempString, 256, delim);
    stripSpace(tempString);
    strcpy (iTransaction.CustomerRefNum, tempString);

    // char[]
    ioStream.getline (tempString, 256, delim);
    stripSpace(tempString);
    strcpy (iTransaction.AccountType, tempString);

    // char[]
    ioStream.getline (tempString, 256, delim);
    stripSpace(tempString);
    strcpy (iTransaction.TransactionType, tempString);

    // float
    // read to end of line
    ioStream.getline (tempString, 256);
    stripSpace(tempString);
    iTransaction.Amount = atof (tempString);

    return ioStream;

} // end operator >>

/*
 * Name:    operator &lt;&lt;
 *
 * Purpose:    Output operation
 *
 * Method:    Output comma separated values, Time Stamp first.
 */
ostream&amp; operator &lt;&lt; 
(
    ostream&amp; ioStream,            // output ioStream
    const Transaction&amp; iTransaction        // input Transaction
)
{

    // long
    // set width to 10 and fill with 0's
    ioStream &lt;&lt; setw (10) &lt;&lt; setfill ('0')
        &lt;&lt; iTransaction.TimeStamp &lt;&lt; &quot;, &quot;;

    // char*
    ioStream &lt;&lt; iTransaction.CustomerName &lt;&lt; &quot;, &quot;;
    
    // long
    ioStream &lt;&lt; iTransaction.CustomerRefNum &lt;&lt; &quot;, &quot;;
    
    // char*
    ioStream &lt;&lt; iTransaction.AccountType &lt;&lt; &quot;, &quot;;
    
    // char*
    ioStream &lt;&lt; iTransaction.TransactionType &lt;&lt; &quot;, &quot;;
    
    // float
    // set precision to 2 and fixed notation
    ioStream &lt;&lt; setprecision (2) &lt;&lt; fixed &lt;&lt; iTransaction.Amount &lt;&lt; endl;

    return ioStream;

} // end operator &lt;&lt;

// end operators


/*
 * Function:    checkSwitch
 *
 * Purpose:    Checks commandline input for valid switches.
 *
 * Method:    Accepts array of characters and tests to see if it contains
 *        valid switches. Sets bool combine to true if switch was 'c',
 *        sets mSortBy to 1 if switch was 'n'.
 *
 * Returns:    true if valid switch was encountered.
        false otherwise.
 */
bool checkSwitch
(
    char args[]    // array containing possible switch
)
{
    // check if it is a valid argument beginning with '/' or '-'
    switch( args[0] )
    {
        case '/':
        case '-': 
            break;
        default :
            return false;
    }

    // check that the second char is a valid char, 't', 'n' or 'c'
    switch( args[1] )
    {
        // sort transactions in Numeric order by Time Stamp
        case 't':
            //Transaction::setSortBy ( 0 ) is already set
            // dont need to do anything here
            break;

        // sort transactions in Alphabetic order by Last Name
        case 'n': 
            Transaction::setSortBy ( 1 );
            break;

        // sort transactions in Numeric order by Time Stamp of combined
        // deposit balance
        case 'c':
            combine = true;
            break;

        // is not valid switch
        default :
            return false;
            break;
    }
    // is a valid switch
    return true;

} // end checkSwitch

/*
 * Function:    main
 *
 * Purpose:    Does heaps of things, causes headaches and hair loss.
 *
 * Method:    Parses commandline input, creates Transactions from an input
 *        file, adds them to list, sorts this list, possibly combines
 *        transactions, and prints them out to cout or a file.
 *
 * Returns:    EXIT_SUCCESS on success
 */
int main
(
    int argc,
    char *argv[]
)
{

    ofstream    outputFile;    // Output file
    ifstream    inputFile;    // Input file

    bool    printToFile = false;    // file printing flag

    list&lt;Transaction> transactions;        // list to hold Transactions

    list&lt;Transaction>::iterator transactionsIterator; // iterator over list


    // create a new Transaction
    Transaction *transaction = new Transaction();

    // parse commandline arguments
    switch( argc - 1 )
    {
    // switch, inputfile, outputfile
    case 3:
        // check switch
        checkSwitch(argv[1]);

        // open files
        inputFile.open (argv[2]);
        outputFile.open (argv[3]);

        break;
    
    // input file, output file OR switch, input file
    case 2:
        // if 1 is switch then 2 is input file
        if( checkSwitch(argv[1]) )
        {
            // 2 is input file
            inputFile.open (argv[2]);
            
        }
        // else 1 is input and 2 is output
        else
        {
            inputFile.open (argv[1]);
            outputFile.open (argv[2]);
        }
        break;

    // input file
    case 1:
        // open file
        inputFile.open (argv[1]);

        break;

    // is an error so print error msg and exit
    default : 
        cerr &lt;&lt; &quot;Usage: &quot; &lt;&lt; argv[0] &lt;&lt; &quot; &quot;;
        cerr &lt;&lt; &quot;[ [/t] | [/n] | [/c] ] INPUTFILE [OUTPUTFILE]\n&quot;;
        cerr &lt;&lt; &quot;/t [DEFAULT]\t: sort transactions in Numeric order by &quot;
        &lt;&lt; &quot;Time Stamp\n&quot;;
        cerr &lt;&lt; &quot;/n\t\t: sort transactions in Alphabetic order by Last &quot;
            &lt;&lt; &quot;Name\n&quot;;
        cerr &lt;&lt; &quot;/c\t\t: sort transactions in Numeric order by Time &quot;
            &lt;&lt; &quot;Stamp of combined deposit balance&quot; &lt;&lt; endl;

        exit (EXIT_FAILURE);
        break;
    }

    // input file is bad so print error and exit
    if( !inputFile.good() )
    {
        cerr &lt;&lt; &quot;Invalid Input File&quot; &lt;&lt; endl;
        exit (EXIT_FAILURE);
    }
    // output file is open so we are printing to output file
    if( outputFile.is_open() )
    {
        printToFile = true;
    }

    // for each line in the input file
    while( !inputFile.eof() )
    {
        // parse input stream into transaction
        inputFile >> *transaction;

        // add Transaction to list
        transactions.push_back(*transaction);
    }


    // sort list of transactions depending on mSortBy flag
    transactions.sort();


    /*
    Combine transactions
        assume transactions are sorted by cust ref

    for all ii
        for all jj where jj = ii + 1
            if transaction[ii] /= transaction[jj]
            then combine transactions by
            transaction[ii] = transaction[ii] + transaction[jj]
            remove transaction[jj] from list
    */
    if( combine )
    {
        // create iterators over the list of Transactions
        list&lt;Transaction>::iterator ii;
        list&lt;Transaction>::iterator jj;

        for (ii = transactions.begin(); ii != transactions.end(); ii++)
        {
            for (jj = ii; jj != transactions.end(); jj++)
            {
                if( (ii != jj) &amp;&amp; (*ii /= *jj) )
                {
                    *ii + *jj;

                    if (jj != transactions.end())
                    {
                        transactions.erase(jj++);
                    }
                }
            }
        }
    }

    // print list of transactions
    for (transactionsIterator = transactions.begin();
        transactionsIterator != transactions.end();
        transactionsIterator++)
    {
        // print to file
        if( printToFile )
        {
            outputFile &lt;&lt; *transactionsIterator;
        }
        // print to cout
        else
        {
            cout &lt;&lt; *transactionsIterator;
        }
    }

    // close files
    outputFile.close();
    inputFile.close();

    // destroy transaction
    delete transaction;

    return EXIT_SUCCESS;
} // end main
</textarea> 
    <br /> 
    Code &copy; Copyright 2004 Ned Martin</p> 
<p>19-May-2004</p> 
</body>
</html>