Author Topic: BEGINNING COMPUTER PROGRAMMING (using C++ or C)  (Read 48480 times)

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: BEGINNING COMPUTER PROGRAMMING (using C++ or C)
« Reply #15 on: April 26, 2009, 06:30:03 PM »
Chapter 15: continued ...

And next ... try this and see all the comments in the program ...

Code: [Select]
// editContacts.cpp
// Chapter 15:

// The edit function is added here ... Also note the use of a C++ vector
// container, (similar to an array), to hold each struct of 'MyContacts' (and...
// note the few changes in converting from an array to a STL vector container.)
// We will use push_back ... so our vector of struct's can grow to be as big
// as available RAM ...
// Note: a global boolean variable 'FILE_CHANGES' is used to track file-updates
// Eventually ...
// the Computer updates (edits, deletes, sorts, chops-duplicates-in) its files
// (Actually ... we are preventing duplicate entries of phone numbers on input here, to demo how.)

#include <iostream>
#include <iomanip> // for formatting cout output here ...
#include <fstream>
#include <sstream> // for stringstream conversions
#include <string>
#include <vector> // to hold each struct of 'MyContacts'
#include <cctype> // for isdigit, toupper

// globals ...

using namespace std;

const char MY_FILE[] = "myRecords.dat";

const string indent(14, ' '); // construct string 'indent' with 14 space char's
const string MENU = indent + "1. A dd new contacts\n" +
                    indent + "2. V iew book\n" +
                    indent + "3. E dit book\n" +
                    indent + "4. F ile book\n" +
                    indent + "5. L oad book from file\n" +
                    indent + "6. I nitial memory\n" +
                    indent + "0. Q uit\n" +
                    "Your choice : ";

// a global variable to flag file updates of any changes ... before exiting
bool FILE_CHANGES = false;

struct MyContacts // a 'struct' may be used for a C/C++ style 'data record' ...
{
    string theName;
    string thePhone;
}; // Note: semi-colon here tells compiler we have reached the end of 'struct'


// forward function declarations / function prototypes ...

string takeIn( const string& message );
bool isValidPhone( const string& pNum );
int existPhone( const string& pNum, const vector < MyContacts >& v );
int addBook( vector < MyContacts >& book );
void viewByPhone( int index, vector < MyContacts >& book );
void viewBook( const vector < MyContacts >& v );
void editBook( vector < MyContacts >& v );
int fileBook( const vector < MyContacts >& v );
int loadBook( vector < MyContacts>& v );



int main()
{
    // construct an empty vector to hold each struct of 'MyContacts'
    // the number of records is available via a call to myBook.size() ... now 0
    vector < MyContacts > myBook;

    // update from file ... if file exits ... if any records there
    int numContacts = loadBook( myBook );
    if( numContacts >= 0 )
    {
        cout << "The number of records in memory now is " << numContacts
             << " ... \n\n";
        viewBook( myBook );
    }
    else
    {
        cout << "The file " << MY_FILE << " could not be opened ... "
              << "Perhaps it doesn't exist yet?" << endl;
    }
    
    int choice, numFiled, reply;
    do
    {
        cout << endl << MENU << flush;
        choice = toupper( cin.get() );
        cin.sync(); // 'flush' cin stream ...
        
        switch( choice )
        {
            case '1' : case 'A' : // addBook returns the number of contacts ...
                numContacts = addBook( myBook );
            break;
            case '2' : case 'V' : // viewBook
                viewBook( myBook );
            break;
            case '3' : case 'E' : // editBook
                editBook( myBook );
            break;
            case '4' : case 'F' : // fileBook
                if( numContacts > 0 )
                {
                    numFiled = fileBook( myBook );
                    if( numFiled == numContacts )
                    {
                        cout << "All " << numContacts << " contacts were filed ok ..."
                             << endl;
                        FILE_CHANGES = false; //  update global file flag ...
                    }
                    else
                        cout << "File error ... Only " << numFiled << " of "
                             << numContacts << " filed." << endl;
                }
                else
                {
                    cout << "Do you really want to write an EMPTY file (y/n) ? "
                         << flush;
                    reply = cin.get();
                    cin.sync(); // flush cin stream ...
                    if( reply == 'y' || reply == 'Y' )
                    {
                        numFiled = fileBook( myBook );
                        if( numFiled == 0 )
                            cout << "File " << MY_FILE << " now empty." << endl;
                            if( numFiled == numContacts)
                            {
                                cout << "All " << numContacts
                                     << " contacts were filed ok ..." << endl;
                                FILE_CHANGES = false; // update global file flag
                            }
                        else cout << "Error writing to file " << MY_FILE << endl;
                    }
                    else cout << "Ok ... aborted writing an empty file." << endl;
                }
            break;
            case '5' : case 'L' : // loadBook from file into memory ...
                if( numContacts > 0 )
                {
                    cout << "Do you want to over-write the " << numContacts
                         << " in memory (y/n) ? " << flush;
                    reply = toupper( cin.get() );
                    cin.sync();
                    if( reply == 'Y' )
                    {
                        myBook.clear(); // re-set myBook to the empty vector
                        numContacts = loadBook( myBook);
                        cout << numContacts << " records were loaded into memory ..."
                             << endl;
                        FILE_CHANGES = false; // update flag ...
                    }
                    else cout << "Ok ... over-write aborted ..."
                              << endl;
                }
                else // numContacts == 0 to start ...
                {
                    numContacts = loadBook( myBook ); // so load from file ...
                    if( numContacts >= 0 )
                    {
                        cout << numContacts << " records were loaded into memory ..."
                             << endl;
                        FILE_CHANGES = false; // update file flag ...
                    }
                    else
                    {
                        numContacts = 0; // reset to zero (from -1 set above)
                        cout << "The file " << MY_FILE << " could not be opened ..."
                             << " Perhaps it doesn't exist yet?" << endl;
                    }
                }
            break;
            case '6' : case 'I' : // set memory counter to zero for over-writes
                if( numContacts > 0 )
                {
                    cout << "Do you want to ignore " << numContacts
                         << " in memory (y/n) ? " << flush;
                    reply = toupper( cin.get() );
                    cin.sync();
                    if( reply == 'Y' )
                    {
                        myBook.clear(); // re-set myBook to the empty vector
                        numContacts = 0;
                        FILE_CHANGES = true; // update file flag
                        cout << numContacts << " records now in memory ..." << endl;
                    }
                    else cout << "Ok ... memory 'ignore' aborted ..." << endl;
                }
            break;
            case '0' : case 'Q' :
                if( FILE_CHANGES )
                {
                    cout << "Do you want to update the file with the "
                         << numContacts << " records in memory (y/n) ? " << flush;
                    reply = toupper( cin.get() );
                    cin.sync();
                    if( reply == 'Y' )
                    {
                        numFiled = fileBook( myBook );
                        if( numFiled == numContacts )
                        {
                            cout << "All " << numContacts << " contacts were filed ok ..."
                                 << endl;
                            // FILE_CHANGES = false; //  update global file flag
                        }
                        else
                            cout << "File error ... Only " << numFiled << " of "
                                 << numContacts << " filed." << endl;
                    }
                    else cout << "Ok ... file update aborted ..." << endl;
                }
                cout << "Exit program (y/n) ? ";
                reply = toupper( cin.get() );
                cin.sync();
                if( reply == 'Y' )
                {
                    return 0;
                }
                cout << "Ok ...  'Exit program' aborted ..." << endl;
                choice = 'a'; // to abort exit at end of do{...}while(...)
            break;
            default : cout << "Not implemented yet ..." << endl;
        }
    }while( choice != '0' );
}


// prompts for input via the passed in 'message'
// and returns the string that the user entered ...
string takeIn( const string& message )
{
    string tmpStr;
    cout << message << ": " << flush;
    getline( cin, tmpStr );
    return tmpStr;
}

// validate that the phone number is a 10 digit string like: 1234567890
// and to save making a local copy can pass in the C++ string by 'const ref'
bool isValidPhone( const string& pNum )
{
        if( pNum.length() != 10 )
        {
            cout << "\nError: Phone number must have 10 digits.\n";
            return false;
        }
        for( int j = 0; j<10; ++ j )
        {
            if( !isdigit( pNum[j] ) )
            {
                cout << "\nError: Integers only for Phone number.\n";
                return false; // break out if this for loop right now ...
            }
        }
        // if reach here ...
        return true;
}

int existPhone( const string& pNum, const vector < MyContacts >& v )
{
    for( unsigned i = 0; i < v.size(); ++ i)
        if( v[i].thePhone == pNum ) return i;
    // else if reach here ...
    return -1; // as flag that doesn't exist
}

// the number of contacts in the book is returned ...
int addBook( vector < MyContacts >& book )
{
    string reply;
    bool more = true;
    int i = book.size();
    MyContacts mcTmp;
    while( more )
    {
        stringstream ss;
        ss << "[" << i << "] ";
        string tmpStr = ss.str(); // convert stringstream 'ss' to string 'tmpStr'
        // note C++ string 'tmpStr' is in the middle, so we can concatenate here
        mcTmp.theName  = takeIn( "Name"+tmpStr+"(or press 'Enter' to exit) " );

        if( mcTmp.theName.length() == 0 ) return i; // 0 len, so exit function

        mcTmp.thePhone = takeIn( "Phone number"+tmpStr+"... all 10 digits  " );
        if( !isValidPhone(mcTmp.thePhone) ) continue; // from top of while now
        
        if( existPhone(mcTmp.thePhone, book) > -1 )
        {
            cout << "That number is used ...\n";
            continue;
        }

        cout << "Ok ...   (y/n) ? " << flush;
        getline( cin, reply );
        if( !( reply[0] == 'y' || reply[0] == 'Y') ) continue; // at top 'while

        book.push_back( mcTmp ); // ok ... add this record to the end of vector
        ++i; // since reached here, data accepted above, so increment counter
        FILE_CHANGES = true; // update global variable

        cout << "More ... (y/n) ? " << flush; // defaults to yes (i.e. 'true')
        getline( cin, reply );
        more = !( reply[0] == 'n' || reply[0] == 'N' );
    }// end while ...

    return i; // i.e. the count of new contacts
}

void viewByPhone( int index, vector < MyContacts >& book )
{
    cout << right << book[index].thePhone + " " + book[index].theName << endl;
}

// Note: we can pass in a const vector by ref ... since here,
// we are just printing out values ... (i.e. no changes)
void viewBook( const vector < MyContacts >& v )
{
    if( v.size() == 0 ) return;

    int i;
    for( i = 0; i < v.size(); ++i )
    {   // 39 char's total width for each, so have just 2*39=78 char's on a line
        cout << right << "[" << setw(2) << i+1 <<"] "
             << left << setw(33) << v[i].thePhone + " " + v[i].theName
             << " "; // Note: 5 + 33 + 1 = 39 char's
        if( (i+1) % 2 == 0 ) cout << endl; // 2 on a line ...
    }
    if( i % 2 ) cout << endl; // i.e. if (the above) i+1 = 1  ...
}

void editBook( vector < MyContacts >& v )
{
    cout << "Enter phone number of contact to edit: " << flush;
    string pNumStr;
    getline( cin, pNumStr );
    if( !isValidPhone( pNumStr ) )
    {
        cout << "Invalid! ... Valid numbers are 10 digits ..." << endl;
        return;
    }
    int i;
    if( (i = existPhone( pNumStr, v )) < 0 )
    {
        cout << "That number is not here ..." << endl;
        return;
    }
    
    // ok we reached here ... so take in name
    viewByPhone( i, v );
    cout << "\nEdit this one ... (y/n) ? " << flush;
    int reply = toupper( cin.get() );
    cin.sync();
    if( !(reply == 'Y') ) { cout << "Edit aborted ...\n"; return; }

    // ok we reached here ... so ...
    cout << "Enter edited name  : ";
    string nameStr, phoneStr;
    getline( cin, nameStr );

    do
    {
        cout << "Enter edited phone : ";
        getline( cin, phoneStr );
    }while( !isValidPhone( phoneStr ) && (existPhone(phoneStr, v) && phoneStr !=pNumStr ) );
    
    cout << "Ok to update with " << phoneStr << " " << nameStr << " (y/n) ? "
         << flush;
    reply = toupper( cin.get() );
    cin.sync();
    if( reply == 'Y' )
    {
        v[i].theName = nameStr;
        v[i].thePhone = phoneStr;
        cout << "Updated ...\n";
        FILE_CHANGES = true; // update global file flag
    }
    else cout << "Edit aborted ...\n";
}

// uses global variable MY_FILE
int fileBook( const vector < MyContacts >& v )
{
    ofstream fout( MY_FILE );
    if( ! fout ) return -1; // to signal error condition ...
    int i;
    for( i = 0; i < v.size(); ++i )
    {
        fout << v[i].theName << endl
             << v[i].thePhone << endl;
    }
    fout.close();
    FILE_CHANGES = false; // update global file flag ...
    return i;
}

// uses global variable MY_FILE ... Note: vector is 'passed in/back by ref.'
int loadBook( vector < MyContacts>& v )
{
    ifstream fin( MY_FILE ); // open an istream stream to the file
    if( !fin ) return  -1; // to signal error condition ...
    int i = 0;
    MyContacts mcTmp; // get a 'temp' struct to hold each new record ...
    while // here we fill the array from the file ...
    (

        getline(fin, mcTmp.theName) &&
        getline(fin, mcTmp.thePhone)
    )
    {
        ++i;
        v.push_back( mcTmp ); // add each new record to the end of the vector
    }

    fin.close(); // close the input file, i now holds the count of records read
    return i; // return the number of records read into the vector
}


Chapter 15 continues on the next page ...
« Last Edit: May 20, 2010, 07:18:09 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: BEGINNING COMPUTER PROGRAMMING (using C++ or C)
« Reply #16 on: April 26, 2009, 06:46:53 PM »
Chapter 15: continued ... adding an STL sort function to sort our vector container of MyContacts ...


There was a lot introduced on the last page, and here ... so take your time and see all the new syntax and code ...

Code: [Select]
// sortContacts.cpp
// Chapter 15:

// The STL sort function is added here ...


#include <iostream>
#include <iomanip> // for formatting cout output here ...
#include <fstream>
#include <sstream> // for stringstream conversions
#include <string>
#include <vector> // to hold each struct of 'MyContacts'
#include <cctype> // for isdigit, toupper
#include <algorithm> // for sorting a vector container ...

// globals ...

using namespace std;

const char MY_FILE[] = "myRecords.dat";

const string indent(14, ' '); // construct string 'indent' with 14 space char's
const string MENU = indent + "1. A dd new contacts\n" +
                    indent + "2. V iew book\n" +
                    indent + "3. E dit book\n" +
                    indent + "4. S ort book\n" +
                    indent + "5. F ile book\n" +
                    indent + "6. L oad book from file\n" +
                    indent + "7. I nitial memory\n" +
                    indent + "0. Q uit\n" +
                    "Your choice : ";

// a global variable to flag file updates of any changes ... before exiting
bool FILE_CHANGES = false;

struct MyContacts // a 'struct' may be used for a C/C++ style 'data record' ...
{
    string theName;
    string thePhone;
}; // Note: semi-colon here tells compiler we have reached the end of 'struct'


// forward function declarations / function prototypes ...

string takeIn( const string& message );
bool isValidPhone( const string& pNum );
int existPhone( const string& pNum, const vector < MyContacts >& v );
int addBook( vector < MyContacts >& book );
void viewByPhone( int index, vector < MyContacts >& book );
void viewBook( const vector < MyContacts >& v );
void editBook( vector < MyContacts >& v );
bool compare_nocaseName(const MyContacts& first, const MyContacts& second);
bool compare_phone(const MyContacts& first, const MyContacts& second);
int fileBook( const vector < MyContacts >& v );
int loadBook( vector < MyContacts>& v );



int main()
{
    // construct an empty vector to hold each struct of 'MyContacts'
    // the number of records is available via a call to myBook.size() ... now 0
    vector < MyContacts > myBook;

    // update from file ... if file exits ... if any records there
    int numContacts = loadBook( myBook );
    if( numContacts >= 0 )
    {
        cout << "The number of records in memory now is " << numContacts
             << " ... \n\n";
        viewBook( myBook );
    }
    else
    {
        cout << "The file " << MY_FILE << " could not be opened ... "
              << "Perhaps it doesn't exist yet?" << endl;
    }
    
    int choice, numFiled, reply;
    do
    {
        cout << endl << MENU << flush;
        choice = toupper( cin.get() );
        cin.sync(); // 'flush' cin stream ...
        
        switch( choice )
        {
            case '1' : case 'A' : // addBook returns the number of contacts ...
                numContacts = addBook( myBook );
            break;
            case '2' : case 'V' : // viewBook
                viewBook( myBook );
            break;
            case '3' : case 'E' : // editBook
                editBook( myBook );
            break;
            case '4' : case 'S' : // sort ...
                cout << "Sort by name or phone (n/p) ? " << flush;
                reply = toupper( cin.get() );
                cin.sync(); // flush cin stream ...
                if( reply == 'P' )
                {
                    sort(myBook.begin(), myBook.end(), compare_phone);
                    cout << "Now sorted by phone numbers ...\n";
                    FILE_CHANGES = true;
                }
                else if( reply == 'N' )
                {
                    sort(myBook.begin(), myBook.end(), compare_nocaseName);
                    FILE_CHANGES = true;
                    cout << "Now sorted by names ...\n";
                }
                else cout << "Not sorted ...\n";
            break;
            case '5' : case 'F' : // fileBook
                if( numContacts > 0 )
                {
                    numFiled = fileBook( myBook );
                    if( numFiled == numContacts )
                    {
                        cout << "All " << numContacts << " contacts were filed ok ..."
                             << endl;
                        FILE_CHANGES = false; //  update global file flag ...
                    }
                    else
                        cout << "File error ... Only " << numFiled << " of "
                             << numContacts << " filed." << endl;
                }
                else
                {
                    cout << "Do you really want to write an EMPTY file (y/n) ? "
                         << flush;
                    reply = cin.get();
                    cin.sync(); // flush cin stream ...
                    if( reply == 'y' || reply == 'Y' )
                    {
                        numFiled = fileBook( myBook );
                        if( numFiled == 0 )
                            cout << "File " << MY_FILE << " now empty." << endl;
                            if( numFiled == numContacts)
                            {
                                cout << "All " << numContacts
                                     << " contacts were filed ok ..." << endl;
                                FILE_CHANGES = false; // update global file flag
                            }
                        else cout << "Error writing to file " << MY_FILE << endl;
                    }
                    else cout << "Ok ... aborted writing an empty file." << endl;
                }
            break;
            case '6' : case 'L' : // loadBook from file into memory ...
                if( numContacts > 0 )
                {
                    cout << "Do you want to over-write the " << numContacts
                         << " in memory (y/n) ? " << flush;
                    reply = toupper( cin.get() );
                    cin.sync();
                    if( reply == 'Y' )
                    {
                        myBook.clear(); // re-set myBook to the empty vector
                        numContacts = loadBook( myBook);
                        cout << numContacts << " records were loaded into memory ..."
                             << endl;
                        FILE_CHANGES = false; // update flag ...
                    }
                    else cout << "Ok ... over-write aborted ..."
                              << endl;
                }
                else // numContacts == 0 to start ...
                {
                    numContacts = loadBook( myBook ); // so load from file ...
                    if( numContacts >= 0 )
                    {
                        cout << numContacts << " records were loaded into memory ..."
                             << endl;
                        FILE_CHANGES = false; // update file flag ...
                    }
                    else
                    {
                        numContacts = 0; // reset to zero (from -1 set above)
                        cout << "The file " << MY_FILE << " could not be opened ..."
                             << " Perhaps it doesn't exist yet?" << endl;
                    }
                }
            break;
            case '7' : case 'I' : // set memory counter to zero for over-writes
                if( numContacts > 0 )
                {
                    cout << "Do you want to ignore " << numContacts
                         << " in memory (y/n) ? " << flush;
                    reply = toupper( cin.get() );
                    cin.sync();
                    if( reply == 'Y' )
                    {
                        myBook.clear(); // re-set myBook to the empty vector
                        numContacts = 0;
                        FILE_CHANGES = true; // update file flag
                        cout << numContacts << " records now in memory ..." << endl;
                    }
                    else cout << "Ok ... memory 'ignore' aborted ..." << endl;
                }
            break;
            case '0' : case 'Q' :
                if( FILE_CHANGES )
                {
                    cout << "Do you want to update the file with the "
                         << numContacts << " records in memory (y/n) ? " << flush;
                    reply = toupper( cin.get() );
                    cin.sync();
                    if( reply == 'Y' )
                    {
                        numFiled = fileBook( myBook );
                        if( numFiled == numContacts )
                        {
                            cout << "All " << numContacts << " contacts were filed ok ..."
                                 << endl;
                            // FILE_CHANGES = false; //  update global file flag
                        }
                        else
                            cout << "File error ... Only " << numFiled << " of "
                                 << numContacts << " filed." << endl;
                    }
                    else cout << "Ok ... file update aborted ..." << endl;
                }
                cout << "Exit program (y/n) ? ";
                reply = toupper( cin.get() );
                cin.sync();
                if( reply == 'Y' )
                {
                    return 0;
                }
                cout << "Ok ...  'Exit program' aborted ..." << endl;
                choice = 'a'; // to abort exit at end of do{...}while(...)
            break;
            default : cout << "Not implemented yet ..." << endl;
        }
    }while( choice != '0' );
}


// prompts for input via the passed in 'message'
// and returns the string that the user entered ...
string takeIn( const string& message )
{
    string tmpStr;
    cout << message << ": " << flush;
    getline( cin, tmpStr );
    return tmpStr;
}

// validate that the phone number is a 10 digit string like: 1234567890
// and to save making a local copy can pass in the C++ string by 'const ref'
bool isValidPhone( const string& pNum )
{
        if( pNum.length() != 10 )
        {
            cout << "\nError: Phone number must have 10 digits.\n";
            return false;
        }
        for( int j = 0; j<10; ++ j )
        {
            if( !isdigit( pNum[j] ) )
            {
                cout << "\nError: Integers only for Phone number.\n";
                return false; // break out if this for loop right now ...
            }
        }
        // if reach here ...
        return true;
}

// returns the index, if it exists ... or -1 if not exists ...
int existPhone( const string& pNum, const vector < MyContacts >& v )
{
    for( unsigned i = 0; i < v.size(); ++ i)
        if( v[i].thePhone == pNum ) return i;
    // else if reach here ...
    return -1; // as flag that doesn't exist
}

// the number of contacts in the book is returned ...
int addBook( vector < MyContacts >& book )
{
    string reply;
    bool more = true;
    int i = book.size();
    MyContacts mcTmp;
    while( more )
    {
        stringstream ss;
        ss << "[" << i << "] ";
        string tmpStr = ss.str(); // convert stringstream 'ss' to string 'tmpStr'
        // note C++ string 'tmpStr' is in the middle, so we can concatenate here
        mcTmp.theName  = takeIn( "Name"+tmpStr+"(or press 'Enter' to exit) " );

        if( mcTmp.theName.length() == 0 ) return i; // 0 len, so exit function

        mcTmp.thePhone = takeIn( "Phone number"+tmpStr+"... all 10 digits  " );
        if( !isValidPhone(mcTmp.thePhone) ) continue; // from top of while now
        
        if( existPhone(mcTmp.thePhone, book) > -1 )
        {
            cout << "That number is used ...\n";
            continue;
        }

        cout << "Ok ...   (y/n) ? " << flush;
        getline( cin, reply );
        if( !( reply[0] == 'y' || reply[0] == 'Y') ) continue; // at top 'while

        book.push_back( mcTmp ); // ok ... add this record to the end of vector
        ++i; // since reached here, data accepted above, so increment counter
        FILE_CHANGES = true; // update global variable

        cout << "More ... (y/n) ? " << flush; // defaults to yes (i.e. 'true')
        getline( cin, reply );
        more = !( reply[0] == 'n' || reply[0] == 'N' );
    }// end while ...

    return i; // i.e. the count of new contacts
}

// a valid index must be passed in ...
void viewByPhone( int index, vector < MyContacts >& book )
{
    //cout << right << book[index].thePhone + " " + book[index].theName << endl;
    cout << right << book.at(index).thePhone + " " + book.at(index).theName
         << endl; // with bounds checking ...
}

// Note: we can pass in a const vector by ref ... since here,
// we are just printing out values ... (i.e. no changes)
void viewBook( const vector < MyContacts >& v )
{
    if( v.size() == 0 )
    {
        cout << "The book is empty ...\n";
        return;
    }

    int i;
    for( i = 0; i < v.size(); ++i )
    {   // 39 char's total width for each, so have just 2*39=78 char's on a line
        cout << right << "[" << setw(2) << i+1 <<"] "
             << left << setw(33) << v[i].thePhone + " " + v[i].theName
             << " "; // Note: 5 + 33 + 1 = 39 char's
        if( (i+1) % 2 == 0 ) cout << endl; // 2 on a line ...
    }
    if( i % 2 ) cout << endl; // i.e. if (the above) i+1 = 1  ...
}

void editBook( vector < MyContacts >& v )
{
    cout << "Enter phone number of contact to edit: " << flush;
    string pNumStr;
    getline( cin, pNumStr );
    if( !isValidPhone( pNumStr ) )
    {
        cout << "Invalid! ... Valid numbers are 10 digits ..." << endl;
        return;
    }
    int i;
    if( (i = existPhone( pNumStr, v )) < 0 )
    {
        cout << "That number is not here ..." << endl;
        return;
    }
    
    // ok we reached here ... so take in name
    viewByPhone( i, v );
    cout << "\nEdit this one ... (y/n) ? " << flush;
    int reply = toupper( cin.get() );
    cin.sync();
    if( !(reply == 'Y') ) { cout << "Edit aborted ...\n"; return; }

    // ok we reached here ... so ...
    cout << "Enter edited name  : ";
    string nameStr, phoneStr;
    getline( cin, nameStr );

    do
    {
        cout << "Enter edited phone : ";
        getline( cin, phoneStr );
    }while( !isValidPhone( phoneStr ) && (existPhone(phoneStr, v) && phoneStr !=pNumStr ) );
    
    cout << "Ok to update with " << phoneStr << " " << nameStr << " (y/n) ? "
         << flush;
    reply = toupper( cin.get() );
    cin.sync();
    if( reply == 'Y' )
    {
        v[i].theName = nameStr;
        v[i].thePhone = phoneStr;
        cout << "Updated ...\n";
        FILE_CHANGES = true; // update global file flag
    }
    else cout << "Edit aborted ...\n";
}

// uses global variable MY_FILE
int fileBook( const vector < MyContacts >& v )
{
    ofstream fout( MY_FILE );
    if( ! fout ) return -1; // to signal error condition ...
    int i;
    for( i = 0; i < v.size(); ++i )
    {
        fout << v[i].theName << endl
             << v[i].thePhone << endl;
    }
    fout.close();
    FILE_CHANGES = false; // update global file flag ...
    return i;
}

// uses global variable MY_FILE ... Note: vector is 'passed in/back by ref.'
int loadBook( vector < MyContacts>& v )
{
    ifstream fin( MY_FILE ); // open an istream stream to the file
    if( !fin ) return  -1; // to signal error condition ...
    int i = 0;
    MyContacts mcTmp; // get a 'temp' struct to hold each new record ...
    while // here we fill the array from the file ...
    (

        getline(fin, mcTmp.theName) &&
        getline(fin, mcTmp.thePhone)
    )
    {
        ++i;
        v.push_back( mcTmp ); // add each new record to the end of the vector
    }

    fin.close(); // close the input file, i now holds the count of records read
    return i; // return the number of records read into the vector
}


// name comparison here is NOT case sensitive ...
bool compare_nocaseName(const MyContacts& first, const MyContacts& second)
{
  unsigned int i=0;
  while( i<first.theName.length() && i<second.theName.length() )
  {
    if( tolower(first.theName[i]) < tolower(second.theName[i]) ) return true;
    else if( tolower(first.theName[i]) > tolower(second.theName[i]) ) return false;
    ++i;
  }
  if( first.theName.length() < second.theName.length() ) return true;
  else if( first.theName.length() > second.theName.length() ) return false;
  else return first.thePhone < second.thePhone;
}

bool compare_phone(const MyContacts& first, const MyContacts& second)
{
    return first.thePhone < second.thePhone;
}

Chapter 15 continues on the next page ...
« Last Edit: March 19, 2010, 06:41:58 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: BEGINNING COMPUTER PROGRAMMING (using C++ or C)
« Reply #17 on: April 26, 2009, 06:56:19 PM »
Chapter 15: continues and concludes here ...


This is the last piece of C++ code in this thread for now. The following code demo's the STL list, and iterators too. You now have MANY powerful tools to use for your data processing.


Shalom,
David

P.S.
I hope you enjoyed and learned a few things from this set of introductory C++ programs ... Please take a look and profit here too ...We may need these insights even more ... and perhaps very soon.

http://sites.google.com/site/andeveryeyeshallseehim/


Code: [Select]
// deleteContacts.cpp
// Chapter 15:


// The STL list delete function is added here ...
// Note we have switched from a STL vector conatiner to a STL list container ...
// to allow easy deletes ...
// Note the use of iterators like 'it' and the syntax: it->theName, it->thePhone


#include <iostream>
#include <iomanip> // for formatting cout output here ...
#include <fstream>
#include <sstream> // for stringstream conversions
#include <string>
#include <list> // to hold each struct of 'MyContacts'
#include <cctype> // for isdigit, toupper

// globals ...

using namespace std;

const char MY_FILE[] = "myRecords.dat";

const string indent(14, ' '); // construct string 'indent' with 14 space char's
const string MENU = indent + "1. A dd new contacts\n" +
                    indent + "2. V iew contacts in the book\n" +
                    indent + "3. E dit/D elete a contact in the book\n" +
                    indent + "4. S ort book\n" +
                    indent + "5. F ile book\n" +
                    indent + "6. L oad book from file\n" +
                    indent + "7. I nitial memory\n" +
                    indent + "0. Q uit\n" +
                    "Your choice : ";

// a global variable to flag file updates of any changes ... before exiting
bool FILE_CHANGES = false;

struct MyContacts // a 'struct' may be used for a C/C++ style 'data record' ...
{   // constructor ...
    MyContacts(string name, string phone) : theName(name), thePhone(phone) {}
    string theName;
    string thePhone;
}; // Note: semi-colon here tells compiler we have reached the end of 'struct'


// forward function declarations / function prototypes ...

string takeIn( const string& message );
bool isValidPhone( const string& pNum );
// returns a valid iterator to phone# if exits in list ... otherwise returns NULL
list< MyContacts >::iterator existPhone( const string& pNum, list< MyContacts >& book );
int addBook( list < MyContacts >& book );
void viewByPhone( const list< MyContacts >::iterator it );
void viewBook( const list < MyContacts >& v );
void editBook( list < MyContacts >& v );
bool compare_nocaseName(const MyContacts& first, const MyContacts& second);
bool compare_phone(const MyContacts& first, const MyContacts& second);
int fileBook( const list < MyContacts >& v );
int loadBook( list < MyContacts>& v );


int main()
{
    // construct an empty list to hold each struct of 'MyContacts'
    // the number of records is available via a call to myBook.size() ... now 0
    list < MyContacts > myBook;

    // update from file ... if file exits ... if any records there
    int numContacts = loadBook( myBook );
    if( numContacts >= 0 )
    {
        cout << "The number of records in memory now is " << numContacts
             << " ... \n\n";
        viewBook( myBook );
    }
    else
    {
        cout << "The file " << MY_FILE << " could not be opened ... "
              << "Perhaps it doesn't exist yet?" << endl;
    }
    
    int choice, numFiled, reply;
    do
    {
        cout << endl << MENU << flush;
        choice = toupper( cin.get() );
        cin.sync(); // 'flush' cin stream ...
        
        switch( choice )
        {
            case '1' : case 'A' : // addBook returns the number of contacts ...
                numContacts = addBook( myBook );
            break;
            case '2' : case 'V' : // viewBook
                viewBook( myBook );
            break;
            case '3' : case 'E' : case 'D' : // edit/delete a contact ...
                editBook( myBook );
                numContacts = myBook.size(); // update in case of deletes ...
            break;
            case '4' : case 'S' : // sort ...
                cout << "Sort by name or phone (n/p) ? " << flush;
                reply = toupper( cin.get() );
                cin.sync(); // flush cin stream ...
                if( reply == 'P' )
                {
                    myBook.sort(compare_phone);
                    cout << "Now sorted by phone numbers ...\n";
                    FILE_CHANGES = true;
                }
                else if( reply == 'N' )
                {
                    myBook.sort(compare_nocaseName);
                    FILE_CHANGES = true;
                    cout << "Now sorted by names ...\n";
                }
                else cout << "Not sorted ...\n";
            break;
            case '5' : case 'F' : // fileBook
                if( numContacts > 0 )
                {
                    numFiled = fileBook( myBook );
                    if( numFiled == numContacts )
                    {
                        cout << "All " << numContacts << " contacts were filed ok ..."
                             << endl;
                        FILE_CHANGES = false; //  update global file flag ...
                    }
                    else
                        cout << "File error ... Only " << numFiled << " of "
                             << numContacts << " filed." << endl;
                }
                else
                {
                    cout << "Do you really want to write an EMPTY file (y/n) ? "
                         << flush;
                    reply = cin.get();
                    cin.sync(); // flush cin stream ...
                    if( reply == 'y' || reply == 'Y' )
                    {
                        numFiled = fileBook( myBook );
                        if( numFiled == 0 )
                            cout << "File " << MY_FILE << " now empty." << endl;
                            if( numFiled == numContacts)
                            {
                                cout << "All " << numContacts
                                     << " contacts were filed ok ..." << endl;
                                FILE_CHANGES = false; // update global file flag
                            }
                        else cout << "Error writing to file " << MY_FILE << endl;
                    }
                    else cout << "Ok ... aborted writing an empty file." << endl;
                }
            break;
            case '6' : case 'L' : // loadBook from file into memory ...
                if( numContacts > 0 )
                {
                    cout << "Do you want to over-write the " << numContacts
                         << " in memory (y/n) ? " << flush;
                    reply = toupper( cin.get() );
                    cin.sync();
                    if( reply == 'Y' )
                    {
                        list <MyContacts> tmp; // contruct an empty list
                        myBook = tmp; // re-set myBook to the empty list
                        numContacts = loadBook( myBook);
                        cout << numContacts << " records were loaded into memory ..."
                             << endl;
                        FILE_CHANGES = false; // update flag ...
                    }
                    else cout << "Ok ... over-write aborted ..."
                              << endl;
                }
                else // numContacts == 0 to start ...
                {
                    numContacts = loadBook( myBook ); // so load from file ...
                    if( numContacts >= 0 )
                    {
                        cout << numContacts << " records were loaded into memory ..."
                             << endl;
                        FILE_CHANGES = false; // update file flag ...
                    }
                    else
                    {
                        numContacts = 0; // reset to zero (from -1 set above)
                        cout << "The file " << MY_FILE << " could not be opened ..."
                             << " Perhaps it doesn't exist yet?" << endl;
                    }
                }
            break;
            case '7' : case 'I' : // set memory counter to zero for over-writes
                if( numContacts > 0 )
                {
                    cout << "Do you want to ignore " << numContacts
                         << " in memory (y/n) ? " << flush;
                    reply = toupper( cin.get() );
                    cin.sync();
                    if( reply == 'Y' )
                    {
                        list <MyContacts> tmp; // contruct an empty list
                        myBook = tmp; // re-set myBook to the empty list
                        numContacts = 0;
                        FILE_CHANGES = true; // update file flag
                        cout << numContacts << " records now in memory ..." << endl;
                    }
                    else cout << "Ok ... memory 'ignore' aborted ..." << endl;
                }
            break;
            case '0' : case 'Q' :
                if( FILE_CHANGES )
                {
                    cout << "Do you want to update the file with the "
                         << numContacts << " records in memory (y/n) ? " << flush;
                    reply = toupper( cin.get() );
                    cin.sync();
                    if( reply == 'Y' )
                    {
                        numFiled = fileBook( myBook );
                        if( numFiled == numContacts )
                        {
                            cout << "All " << numContacts << " contacts were filed ok ..."
                                 << endl;
                            // FILE_CHANGES = false; //  update global file flag
                        }
                        else
                            cout << "File error ... Only " << numFiled << " of "
                                 << numContacts << " filed." << endl;
                    }
                    else cout << "Ok ... file update aborted ..." << endl;
                }
                cout << "Exit program (y/n) ? ";
                reply = toupper( cin.get() );
                cin.sync();
                if( reply == 'Y' )
                {
                    return 0;
                }
                cout << "Ok ...  'Exit program' aborted ..." << endl;
                choice = 'a'; // to abort exit at end of do{...}while(...)
            break;
            default : cout << "Not implemented yet ..." << endl;
        }
    }while( choice != '0' );
}


// prompts for input via the passed in 'message'
// and returns the string that the user entered ...
string takeIn( const string& message )
{
    string tmpStr;
    cout << message << ": " << flush;
    getline( cin, tmpStr );
    return tmpStr;
}

// validate that the phone number is a 10 digit string like: 1234567890
// and to save making a local copy can pass in the C++ string by 'const ref'
bool isValidPhone( const string& pNum )
{
        if( pNum.length() != 10 )
        {
            cout << "\nError: Phone number must have 10 digits.\n";
            return false;
        }
        for( int j = 0; j<10; ++ j )
        {
            if( !isdigit( pNum[j] ) )
            {
                cout << "\nError: Integers only for Phone number.\n";
                return false; // break out if this for loop right now ...
            }
        }
        // if reach here ...
        return true;
}

// returns a valid iterator if ID is used already ... otherwise returns NULL
list< MyContacts >::iterator existPhone( const string& pNum, list< MyContacts >& book )
{
    list< MyContacts >::iterator it;
    for( it = book.begin(); it != book.end(); ++it )
    {
        if( it->thePhone == pNum )
            return it;
    }
    return NULL;
}

// the number of contacts in the book is returned ...
// (and the updated list of MyContacts objects is returned by ref.)
int addBook( list < MyContacts >& book )
{
    string reply;
    bool more = true;
    int i = book.size();

    while( more )
    {
        stringstream ss;
        ss << "[" << i+1 << "] ";
        string tmpStr = ss.str(); // convert stringstream 'ss' to string 'tmpStr'
        // note C++ string 'tmpStr' is in the middle, so we can concatenate here
        string name  = takeIn( "Name"+tmpStr+"(or press 'Enter' to exit) " );

        if( name.length() == 0 ) return i; // 0 len, so exit function

        string phone = takeIn( "Phone number"+tmpStr+"... all 10 digits  " );
        if( !isValidPhone(phone) ) continue; // from top of while now

        if( existPhone(phone, book) != NULL )
        {
            cout << "That number is used ...\n";
            continue;
        }

        cout << "Ok ...   (y/n) ? " << flush;
        getline( cin, reply );
        if( !( reply[0] == 'y' || reply[0] == 'Y') ) continue; // at top 'while

        book.push_back( MyContacts(name, phone) ); // ok ... add this record to the end of list
        ++i; // since reached here, data accepted above, so increment counter
        FILE_CHANGES = true; // update global variable

        cout << "More ... (y/n) ? " << flush; // defaults to yes (i.e. 'true')
        getline( cin, reply );
        more = !( reply[0] == 'n' || reply[0] == 'N' );
    }// end while ...

    return i; // i.e. the count of new contacts
}

void viewByPhone( const list< MyContacts >::iterator it )
{
    cout << right << it->thePhone + " " + it->theName << endl;
}

// Note: we can pass in a const list by ref ... since here,
// we are just printing out values ... (i.e. no changes)
void viewBook( const list < MyContacts >& v )
{
    if( v.size() == 0 )
    {
        cout << "The book is empty ...\n";
        return;
    }
    

    int i=0;
    list< MyContacts >::const_iterator it;
    for( it =v.begin(); it != v.end(); it++, i++ )
    {   // 39 char's total width for each, so have just 2*39=78 char's on a line
        cout << right << "[" << setw(2) << i+1 <<"] "
             << left << setw(33) << it->thePhone + " " + it->theName
             << " "; // Note: 5 + 33 + 1 = 39 char's
        if( (i+1) % 2 == 0 ) cout << endl; // 2 on a line ...
    }
    if( i % 2 ) cout << endl; // i.e. if (the above) i+1 = 1  ...
}

// uses gloabal variable FILE_CHANGES ...
void editBook( list < MyContacts >& v )
{
    cout << "Enter phone number of contact to edit/delete: " << flush;
    string pNumStr;
    getline( cin, pNumStr );
    if( !isValidPhone( pNumStr ) )
    {
        cout << "Invalid! ... Valid numbers are 10 digits ..." << endl;
        return;
    }
    list< MyContacts >::iterator it;
    if( (it = existPhone( pNumStr, v )) == NULL )
    {
        cout << "That number is not here ..." << endl;
        return;
    }
    
    // ok we reached here ... so take in conatct ...
    viewByPhone( it );
    cout << "\nEdit/Delete this one ... (e/d) ? " << flush;
    int reply = toupper( cin.get() );
    cin.sync();
    if( !(reply == 'E' || reply == 'D') )
    {
        cout << "Edit/Delete aborted ...\n";
        return;
    }

    if(reply == 'D')
    {
        v.erase( it ); // Ok ... delete it ...
        cout << "Contact deleted ...\n";
        FILE_CHANGES = true; // update global file flag ...
        return;
    }

    // ok we reached here ... so ...
    cout << "Enter edited name  : ";
    string nameStr, phoneStr;
    getline( cin, nameStr );
    for( ;; )
    {
        cout << "Enter edited phone : ";
        getline( cin, phoneStr );
        if( !isValidPhone(phoneStr) )
        {
            cout << "Valid numbers are 10 digits ...\n";
            continue; // loop to get a valid number ...
        }
        if(existPhone(phoneStr, v)!=NULL) // i.e. the number exits
        {
            if(phoneStr!=pNumStr) // see if it is other than the 'old number'
            {
                cout << "That phone number is used ...\n";
                continue; // loop to get a good number ...
            }
            else break; // ok to use 'old' number ...
        }
        else break; // ok to use a new number that doesn't exist yet ...
    }
    
    cout << "Ok to update with " << phoneStr << " " << nameStr << " (y/n) ? "
         << flush;
    reply = toupper( cin.get() );
    cin.sync();
    if( reply == 'Y' )
    {
        it->theName = nameStr;
        it->thePhone = phoneStr;
        cout << "Updated ...\n";
        FILE_CHANGES = true; // update global file flag
    }
    else cout << "Edit aborted ...\n";
}

// uses global variable MY_FILE
int fileBook( const list < MyContacts >& v )
{
    ofstream fout( MY_FILE );
    if( ! fout ) return -1; // to signal error condition ...
    int i;
    list< MyContacts >::const_iterator it;
    for( i = 0, it = v.begin(); it != v.end(); it++, i++ )
    {
        fout << it->theName << endl
             << it->thePhone << endl;
    }
    fout.close();
    FILE_CHANGES = false; // update global file flag ...
    return i;
}

// uses global variable MY_FILE ... Note: list is 'passed in/back by ref.'
int loadBook( list < MyContacts>& v )
{
    ifstream fin( MY_FILE ); // open an istream stream to the file
    if( !fin ) return  -1; // to signal error condition ...
    int i = 0;
    string name, phone;
    while // here we fill the array from the file ...
    (

        getline(fin, name) &&
        getline(fin, phone)
    )
    {
        ++i;
        v.push_back( MyContacts(name, phone) ); // add each new record to the end of the list
    }

    fin.close(); // close the input file, i now holds the count of records read
    return i; // return the number of records read into the list
}


// name comparison here is NOT case sensitive ...
bool compare_nocaseName(const MyContacts& first, const MyContacts& second)
{
  unsigned int i=0;
  while( i<first.theName.length() && i<second.theName.length() )
  {
    if( tolower(first.theName[i]) < tolower(second.theName[i]) ) return true;
    else if( tolower(first.theName[i]) > tolower(second.theName[i]) ) return false;
    ++i;
  }
  if( first.theName.length() < second.theName.length() ) return true;
  else if( first.theName.length() > second.theName.length() ) return false;
  else return first.thePhone < second.thePhone;
}

bool compare_phone(const MyContacts& first, const MyContacts& second)
{
    return first.thePhone < second.thePhone;
}


You may like to see C simulations, Cvec and Clist, of the above C++ STL vector and list programs here:

http://developers-heaven.net/forum/index.php/topic,106.msg563.html#msg563


or here also ...

Cvec
http://www.dreamincode.net/code/snippet5142.htm

Clist
http://www.dreamincode.net/code/snippet5297.htm
« Last Edit: April 12, 2010, 10:46:54 AM by David »


Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: BEGINNING COMPUTER PROGRAMMING (using C++ or C)
« Reply #19 on: November 23, 2009, 06:03:44 PM »
Update:

You also might like to see this new link at ...

http://sites.google.com/site/andeveryeyeshallseehim/

Shalom.

David
« Last Edit: January 25, 2010, 03:03:06 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: BEGINNING COMPUTER PROGRAMMING (using C++ or C)
« Reply #20 on: January 26, 2010, 07:08:09 AM »
Addendum:

Code: [Select]
// guessIt5
#include <iostream>
#include <cstdlib> // re. rand
#include <ctime>  // re. time

using namespace std;

// This function prompts for input and returns only a valid integer
int getValid( char prompt[], int low, int high)
{
    for( ;; )
    {
        cout << prompt << flush;
        int tmp;
        cin >> tmp;
        if( !cin.good() )
        {
            cin.clear(); // in case error flags set ...
            cin.sync(); // flush cin stream ...
            cout << "Non integer entered ... ";
            continue;
        }
   
        if( tmp < low || tmp > high )
        {
            cout << "Out of range " << low << ".." << high << " ... ";
            cin.sync(); // flush cin stream ...
            continue;
        }
       
        // else ... if reach here ...
        cin.sync(); // flush cin stream ...
        return tmp;
    }
}

// Note: void function (i.e. procedure) playgame is the main game
// Note 2: the use of 'pass by reference' ...
void playgame( int& computerCents, int& playerCents )
{
    cout << "THE COMPUTER will roll the dice AFTER\n"
         << "YOU ENTER a number in the RANGE 2..12\n";
    int userNum = getValid("Your guess 2..12 : ", 2, 12);
   
    // get two random numbers 1..6 for each die
    int die1 = rand() % 6 + 1;
    int die2 = rand() % 6 + 1;
   
    // see if sum matches
    if( die1 + die2 == userNum )
    {
        cout << "MATCH!\n";         // report success
        playerCents += userNum;     // player wins
        computerCents -= userNum;   // computer loses
    }
    else
    {
        cout << "NO match!\n";      // report failure
        playerCents -= userNum;     // player loses
        computerCents += userNum;   // computer wins
    }
   
    cout << "You entered " << userNum << endl
         << "And the computer rolled " << die1 << " & " << die2
         << " or " << die1 + die2 << "." << endl;
}


int main()
{
    // initialize random seed
    srand ( time(NULL) );

    int cCents = getValid("Computer stakes 100..1000 (cents) : ", 100, 1000);
    int cCentsInitial = cCents; // keep a copy
    int pCents = getValid("Player   stakes 100..1000 (cents) : ", 100, 1000);
    int pCentsInitial = pCents;
    cout << "\nThe computer staked " << cCents << " and the player staked "
         << pCents << " cents." << endl;
   
    int reply,
        numGames = 0;
    // since we presume that the user wants to play at least one time ...
    do // ... we can use the do..while(..) structure
    {
        ++numGames;
        playgame( cCents, pCents ); // computer cents and player cents updated
        if( pCents > 0 && cCents > 0 )
        {
            cout << "\nAfter game "<<numGames<<" player has "
                 << pCents<<" cents\n"
                 << "and the computer has " << cCents << " cents\n"
                 << "\nPlay again (y/n) ? ";
            reply = cin.get(); // NOTE! cin.get() return type is an 'int'
            cin.sync(); // flush cin stream ...
        }
    }while( !(reply=='n' || reply=='N') && pCents > 0 && cCents > 0 );
   
    // don't allow, (i.e. correct for), 'in-hole' stuations ...
    if( pCents < 0 )            // player in hole
    {
        cCents -= -pCents;      // i.e. decrease computer balance
        pCents = 0;              // so now can up balance of player to zero
    }
    else if( cCents < 0 )       // computer in hole
    {
        pCents -= cCents;       // decrease player balance
        cCents = 0;             // so now can up balance of computer to zero
    }
   
    // can insert the starting 'stakes' here ...
    // cCents, and pCents hold the values we need to print out with message
    cout << "\nAfter " << numGames << " games, the computer has "
         << cCents << " cents\n"
         << "and the player has " << pCents << " cents" << endl;

    // calclate the computer winnings
    int cWins = cCents - cCentsInitial;
   
    // calculate the player winnings
    int pWins = pCents - pCentsInitial;
   
    if( cWins > 0 )             // computer wins
    {                           // take the negative of pWins ...
        cout << "The computer wins " << cWins
             << " and the player loses " << -pWins << endl;
    }
    else                        // computer loses
    {                           // take neg cWins ...
        cout << "The player wins " << pWins
             << " and the computer loses " << -cWins << endl;
    }
   
    cout << "\nPress 'Enter' to exit ... " << flush;
    cin.get(); // wait for 'Enter' ...
}

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: BEGINNING COMPUTER PROGRAMMING (using C++ or C)
« Reply #21 on: May 20, 2010, 07:22:58 PM »
Related links to see:

Using STL map and list (C++ STL map, list tutorial)
http://www.dreamincode.net/code/snippet5377.htm

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: BEGINNING COMPUTER PROGRAMMING (using C++ or C)
« Reply #22 on: June 01, 2010, 10:52:43 PM »
Another simple student class ...

Code: [Select]
// this example uses code ...
// modified to use list and const_iterator, derived ...
// from a demo by 'Bench' at DIC
// and illustrates ...
// - friend functions in a class
// - operator overloading to ease read/write records (from a CSV file, here)
// - STL list container
// - and using iterators like 'it' in ...
//   std::list< Student >::const_iterator it;
//   to access elements in a list (a STL container)

#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <list>

class Student
{
public:
    friend std::ostream& operator<< (std::ostream&, const Student&);
    friend std::istream& operator>> (std::istream&, Student&);
private:
    std::string name;
    int id;
    double fees;
};

std::ostream& operator<<(std::ostream& out, const Student& s)
{
    out << std::setw(16) << std::left << s.name  << ' '
        << std::setw(10) << s.id    << ' '
        << std::setw(7)  << std::right
        << std::setprecision(2) << std::fixed << s.fees;
    return out;
}

std::istream& operator>>(std::istream& in, Student& s)
{
    std::getline(in, s.name, ',');  //read name
    in >> s.id;                     //read id
    in.ignore();                    //ignore next comma
    in >> s.fees;                   //read fees
    in.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
    return in;
}



const char* FNAME = "Students.txt"; // as per example below inside /* */

/*
Peter Pan,1234,2499.99
Paul Simon,2468,3000.00
Fred Perry,1357,1250.50
Tom Jones,5678,600.00
Harry Hill,9876,2255.00
*/

int main()
{
    std::ifstream fin( FNAME );
    std::list< Student > stud_list;
    Student stud;
    
    while( fin >> stud )
        stud_list.push_back( stud );
        
    std::cout << stud_list.size()
              << " students were successfully read into the student list ...\n"
              << "   Name               ID          Fees\n";
    std::list< Student >::const_iterator it;
    int i = 0;
    for( it = stud_list.begin(); it != stud_list.end(); ++it )
              std::cout << ++i << ": " << *it << std::endl;
    
    std::cout << "\nPress 'Enter' to continue ... " << std::flush;
    std::cin.get();
}
« Last Edit: June 02, 2010, 03:39:52 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: BEGINNING COMPUTER PROGRAMMING (using C++ or C)
« Reply #23 on: June 01, 2010, 11:23:17 PM »
And a few steps up from using parallel arrays to hold your data ...
(Illustrates using sstream to ease data processing.)


Code: [Select]
// structBook.cpp // using struct Book (instead of parallel arrays)
// this version 2010-06-01

#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;


const int MAX_RECORDS = 5;

struct Book
{
    string title;
    float price;
    int quantity;
};

void showBook( const Book& );
void showBooks( Book[], int );
void takeInStock( Book[], int& );
void editBook( Book[], int&, int );

int main()
{
    Book store[MAX_RECORDS] = {{"nothing",0,0},{"Book 1",77.5,4},{"Book 2",66,3}};
    int count = 3;

    if(count > 0) showBooks( store, count );
    else cout << "Store is empty\n";
    
    cout << endl;
    takeInStock( store, count );
    if(count > 0) showBooks( store, count );
    else cout << "Store is empty\n";
    
    for( ; ; )
    {
        cout << "\nEnter index of book to edit: " << flush;
        string tmp;
        getline( cin, tmp );
        int i;
        if( istringstream(tmp) >> i )
        {
            editBook( store, count, i );
        }
        else
        {
            cout << "Invalid index of " << tmp << " was entered ... Try again.\n";
            continue;
        }
        cout << "More y/n ? " << flush;
        int reply = cin.get();
        cin.sync();
        if( reply == 'n' || reply == 'N' ) break;
    }
    
    if(count > 0) showBooks( store, count );
    else cout << "Store is empty\n";
    
    cout << "\nPress 'Enter' to exit ... " << flush;
    cin.get();
}


void showBook( const Book& b)
{
    cout << setw(15) << left << b.title
         << setw(10) << right << b.price
         << fixed << setprecision(2)
         << setw(16) << right << b.quantity << endl;
}

void showBooks( Book st[], int size )
{
    cout << "* * * * ALL AVAILABLE BOOK TITLES * * * *\n\n"
         << setw(15) << left << "Title"
         << setw(10) << right << "Price"
         << setw(16) << right << "Quanity" << endl
         << setw(15) << left << "====="
         << setw(10) << right << "====="
         << setw(16) << right << "=======" << endl;

    for( int i = 0; i < size; ++i ) showBook( st[i] );
}

void takeInStock( Book st[], int& size )
{
    for( ; size < MAX_RECORDS ; )
    {
        cout << "Enter new title: " << flush;
        getline( cin, st[size].title );
        
        cout << "Enter price: " << flush;
        string tmp;
        getline( cin, tmp );
        if( istringstream( tmp ) >> st[size].price )
        {
            // pass ...
        }
        else
        {
            cout << "Price must be a number ... try again ... ";
            continue;
        }
        
        cout << "Enter quanity: " << flush;
        getline( cin, tmp );
        if( istringstream( tmp ) >> st[size].quantity )
        {
            ++size;
        }
        else
        {
            cout << "Price must be a number ... try again ... ";
            continue;
        }
        
        cout << "More y/n ? " << flush;
        int reply = cin.get();
        cin.sync();
        if( reply == 'n' || reply == 'N' ) break;
    }
    
    if( size == MAX_RECORDS ) cout << "Store is full." << endl;
}

void editBook( Book st[], int& size, int index )
{
    int reply;
    string tmp, msg = "edited";
    if( index > size-1 || index < 0 )
    {
        cout << index << " NOT in valid range of 0.." << size-1 << endl;
        if( index < MAX_RECORDS && size < MAX_RECORDS )
        {
            cout << "Add to end anyways ... y/n ? " << flush;
            reply = cin.get();
            cin.sync();
            if( reply == 'y' || reply == 'Y' )
            {
                index = size++;
                msg = "new";
                goto addNew;
            }
        }
        // else ...
        return;
    }
    
    // else
    showBook( st[index] );
    cout << "ok to edit y/n ? " << flush;
    reply = cin.get();
    cin.sync();
    if( !(reply == 'y' || reply == 'Y' ) ) return;

addNew:
    // else ...
    for( ; ; )
    {
        cout << "Enter " << msg << " title: " << flush;
        getline( cin, st[index].title );

        cout << "Enter " << msg << " price: " << flush;
        getline( cin, tmp );
        if( istringstream( tmp ) >> st[index].price )
        {   /* pass ... */ }
        else
        {
            cout << "Price must be a number ... try again ... ";
            continue;
        }

        cout << "Enter " << msg << " quanity: " << flush;
        getline( cin, tmp );
        if( istringstream( tmp ) >> st[index].quantity )
        {   /* pass ... */ }
        else
        {
            cout << "Quanity must be an integer ... try again ... ";
            continue;
        }
        
        cout << "Ok y/n ? " << flush;
        reply = cin.get();
        cin.sync();
        if( reply == 'y' || reply == 'Y' )
        {
            if( index == MAX_RECORDS ) cout << "Store is full ... " << endl;
            break;
        }
    }
}


Code: [Select]
// structBookStore.cpp // using struct Book and struct Store
// this version 2010-06-01

#include <iostream>
#include <sstream>
#include <iomanip>
using namespace std;


const int MAX_RECORDS = 5;

struct Book
{
    string title;
    float price;
    int quantity;
};

struct Store
{
    Book bStore[MAX_RECORDS];
    int num_recs;
    Store() : num_recs(0) {} // default constructor ... initial num_recs to 0
};

void showBook( const Book& );
void showStore( const Store& );
void takeInStock( Store& );
void editBook( Store&, int );

int main()
{
    Book shipment1[] = {{"nothing",0,0},{"Book 1",77.5,4},{"Book 2",66,3}};
    Store st; // calls default constructor to initial st.num_recs to zero (0)
  
    int i = 0;
    while( st.num_recs < MAX_RECORDS && i < int(sizeof shipment1/sizeof shipment1[0]) )
    {
        st.bStore[st.num_recs++] = shipment1[i++];
    }
    showStore( st );

    cout << endl;
    takeInStock( st );
    showStore( st );
    
    for( ; ; )
    {
        cout << "\nEnter index of book to edit: " << flush;
        string tmp;
        getline( cin, tmp );
        int i;
        if( istringstream(tmp) >> i )
        {
            editBook( st, i );
        }
        else
        {
            cout << "Invalid index of " << tmp << " was entered ... Try again.\n";
            continue;
        }
        cout << "More y/n ? " << flush;
        int reply = cin.get();
        cin.sync();
        if( reply == 'n' || reply == 'N' ) break;
    }
    
    showStore( st );

    cout << "\nPress 'Enter' to exit ... " << flush;
    cin.get();
}


void showBook( const Book& b)
{
    cout << setw(15) << left << b.title
         << setw(10) << right << b.price
         << fixed << setprecision(2)
         << setw(16) << right << b.quantity << endl;
}

void showStore( const Store& st)
{
    if( st.num_recs )
    {
        cout << "     * * * * ALL AVAILABLE BOOK TITLES * * * *\n\n"
             << "     " << setw(15) << left << "Title"
             << setw(10) << right << "Price"
             << setw(16) << right << "Quanity" << endl
             << "     " << setw(15) << left << "====="
             << setw(10) << right << "====="
             << setw(16) << right << "=======" << endl;

        for( int i = 0; i < st.num_recs; ++i )
        {
            cout << "<" << setw(2) << setfill('0') << i << ">"
                 << setfill(' ') << " ";
            showBook( st.bStore[i] );
        }
    }
    else cout << "Store is empty\n";
}

void takeInStock( Store& st )
{
    for( ; st.num_recs < MAX_RECORDS ; )
    {
        cout << "Enter new title: " << flush;
        getline( cin, st.bStore[st.num_recs].title );
        
        cout << "Enter price: " << flush;
        string tmp;
        getline( cin, tmp );
        if( istringstream( tmp ) >> st.bStore[st.num_recs].price )
        {
            // pass ...
        }
        else
        {
            cout << "Price must be a number ... try again ... ";
            continue;
        }
        
        cout << "Enter quanity: " << flush;
        getline( cin, tmp );
        if( istringstream( tmp ) >> st.bStore[st.num_recs].quantity )
        {
            ++st.num_recs;
        }
        else
        {
            cout << "Price must be a number ... try again ... ";
            continue;
        }
        
        cout << "More y/n ? " << flush;
        int reply = cin.get();
        cin.sync();
        if( reply == 'n' || reply == 'N' ) break;
    }
    
    if( st.num_recs == MAX_RECORDS ) cout << "Store is full." << endl;
}

void editBook( Store& st, int index )
{
    int reply;
    string tmp, msg = "edited";
    if( index > st.num_recs-1 || index < 0 )
    {
        cout << index << " NOT in valid range of 0.." << st.num_recs-1 << endl;
        if( index < MAX_RECORDS && st.num_recs < MAX_RECORDS )
        {
            cout << "Add to end anyways ... y/n ? " << flush;
            reply = cin.get();
            cin.sync();
            if( reply == 'y' || reply == 'Y' )
            {
                index = st.num_recs++;
                msg = "new";
                goto addNew;
            }
        }
        // else ...
        return;
    }
    
    // else
    showBook( st.bStore[index] );
    cout << "ok to edit y/n ? " << flush;
    reply = cin.get();
    cin.sync();
    if( !(reply == 'y' || reply == 'Y' ) ) return;

addNew:
    // else ...
    for( ; ; )
    {
        cout << "Enter " << msg << " title: " << flush;
        getline( cin, st.bStore[index].title );

        cout << "Enter " << msg << " price: " << flush;
        getline( cin, tmp );
        if( istringstream( tmp ) >> st.bStore[index].price )
        {   /* pass ... */ }
        else
        {
            cout << "Price must be a number ... try again ... ";
            continue;
        }

        cout << "Enter " << msg << " quanity: " << flush;
        getline( cin, tmp );
        if( istringstream( tmp ) >> st.bStore[index].quantity )
        {   /* pass ... */ }
        else
        {
            cout << "Quanity must be an integer ... try again ... ";
            continue;
        }
        
        cout << "Ok y/n ? " << flush;
        reply = cin.get();
        cin.sync();
        if( reply == 'y' || reply == 'Y' )
        {
            if( index == MAX_RECORDS ) cout << "Store is full ... " << endl;
            break;
        }
    }
}

« Last Edit: June 01, 2010, 11:29:55 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: BEGINNING COMPUTER PROGRAMMING (using C++ or C)
« Reply #24 on: June 02, 2010, 03:17:55 AM »
And class action ...


Code: [Select]
// classBookStore.cpp // using class Book and class Store
// this version 2010-06-01


#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdlib> // re. exit(1)
using namespace std;


const int MAX_RECORDS = 5; // keep this small for testing ...

class Book
{
public:
    Book(string t="", float p=0, int q=0) : title(t), price(p), quantity(q) {}
    void showBook();
private:
    string title;
    float price;
    int quantity;
};

class Store
{
public:
    Store() : num_recs(0) {} // default constructor ... initial num_recs to 0
    void push_back( Book b );
    void showStore();
    void takeInStock();
    void editBook( int );
    int size() { return num_recs; } // inline ...
private:
    Book bStore[MAX_RECORDS];
    int num_recs;
};


int main() /////////////////////////// BEGIN MAIN //////////////////////////////
{
    Book shipment1[] =
    {
        Book("Book 0",100,1),
        Book("Book 1",77.5,4),
        Book("Book 2",66,3)
    };
    Store st; // calls default constructor to initial st.num_recs to zero (0)
  
    int i = 0;
    while( st.size() < MAX_RECORDS && i < int(sizeof shipment1/sizeof shipment1[0]) )
    {
        st.push_back( shipment1[i++] );
    }
    st.showStore();

    cout << endl;
    st.takeInStock();
    st.showStore();

    for( ; ; )
    {
        cout << "\nEnter index of book to edit (-1 to exit) : " << flush;
        string tmp;
        getline( cin, tmp );
        int i;
        if( istringstream(tmp) >> i )
        {
            st.editBook( i );
        }
        else
        {
            cout << "Invalid index of " << tmp << " was entered ... Try again.\n";
            continue;
        }
            
        cout << "More y/n ? " << flush;
        int reply = cin.get();
        cin.sync();
        if( reply == 'n' || reply == 'N' ) break;
    }
    
    st.showStore();

    cout << "\nPress 'Enter' to exit ... " << flush;
    cin.get();
} //////////////////////////////// END MAIN ////////////////////////////////////

void Book::showBook()
{
    cout << setw(15) << left << title
         << setw(10) << right << price
         << fixed << setprecision(2)
         << setw(16) << right << quantity << endl;
}

void Store::push_back( Book b )
{
    if( num_recs < MAX_RECORDS ) bStore[num_recs++] = b;
    else
    {
        cerr << "Store full ... increase MAX_RECORDS above "
             << MAX_RECORDS << " and recompile ...\n\n"
             <<"Press 'Enter' to exit ... " << flush;
        string dummy;
        getline( cin, dummy );
        exit(1);
    }
}

void Store::showStore()
{
    if( num_recs )
    {
        cout << "     * * * * ALL AVAILABLE BOOK TITLES * * * *\n\n"
             << "     " << setw(15) << left << "Title"
             << setw(10) << right << "Price"
             << setw(16) << right << "Quanity" << endl
             << "     " << setw(15) << left << "====="
             << setw(10) << right << "====="
             << setw(16) << right << "=======" << endl;

        for( int i = 0; i < num_recs; ++i )
        {
            cout << "<" << setw(2) << setfill('0') << i << ">"
                 << setfill(' ') << " ";
            bStore[i].showBook();
        }
    }
    else cout << "Store is empty\n";
}

void Store::takeInStock()
{
    string title;
    float price;
    int quantity;
    while( num_recs < MAX_RECORDS )
    {
        cout << "Enter new title: " << flush;
        getline( cin, title );

        cout << "Enter price: " << flush;
        string tmp;
        getline( cin, tmp );
        if( istringstream( tmp ) >> price )
        {
            // pass ...
        }
        else
        {
            cout << "Price must be a number. Try again ... ";
            continue;
        }

        cout << "Enter quanity: " << flush;
        getline( cin, tmp );
        if( istringstream( tmp ) >> quantity )
        {
            // pass ...
        }
        else
        {
            cout << "Quanity must be an integer. Try again ... ";
            continue;
        }

        cout << "Ok y/n ? " << flush;
        int reply = cin.get();
        cin.sync();
        if( reply == 'y' || reply == 'y' )
            push_back( Book(title, price, quantity) );
        else
            cout << "skipped ...\n";

        cout << "More y/n ? " << flush;
        reply = cin.get();
        cin.sync();
        if( reply == 'n' || reply == 'N' ) break;
    }

    if( num_recs == MAX_RECORDS ) cout << "Store is full." << endl;
}

void Store::editBook( int index )
{
    if( index == -1 ) return;
    
    int reply;
    string tmp, msg = "edited";
    if( index > num_recs-1 || index < 0 )
    {
        cout << index << " NOT in valid edit range of 0.." << num_recs-1 << endl;
        if( index < MAX_RECORDS && num_recs < MAX_RECORDS )
        {
            cout << "But there's room ... Add to end anyways y/n ? " << flush;
            reply = cin.get();
            cin.sync();
            if( reply == 'y' || reply == 'Y' )
            {
                index = num_recs++;
                msg = "new";
                goto addNew;
            }
        }
        // else ...
        return;
    }
    
    // else
    bStore[index].showBook();
    cout << "ok to edit y/n ? " << flush;
    reply = cin.get();
    cin.sync();
    if( !(reply == 'y' || reply == 'Y' ) ) return;

addNew:
    // else ...
    for( ; ; )
    {
        cout << "Enter " << msg << " title: " << flush;
        string title;
        getline( cin, title );

        cout << "Enter " << msg << " price: " << flush;
        getline( cin, tmp );
        float price;
        if( istringstream( tmp ) >> price )
        {   /* pass ... */ }
        else
        {
            cout << "Price must be a number ... try again ... ";
            continue;
        }

        cout << "Enter " << msg << " quanity: " << flush;
        getline( cin, tmp );
        int quantity;
        if( istringstream( tmp ) >> quantity )
        {   /* pass ... */ }
        else
        {
            cout << "Quanity must be an integer ... try again ... ";
            continue;
        }
        
        cout << "Ok y/n ? " << flush;
        reply = cin.get();
        cin.sync();
        if( reply == 'y' || reply == 'Y' )
        {
            bStore[index] = Book( title, price, quantity );
            if( index == MAX_RECORDS ) cout << "Store is full ... " << endl;
            break;
        }
    }
}
« Last Edit: June 02, 2010, 03:42:35 AM by David »