Author Topic: Six Fast Steps to Programming in C++  (Read 41711 times)

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Six Fast Steps to Programming in C++
« on: February 13, 2011, 01:51:01 AM »
Update!  please see this next link:


The following quick tutorial may be of interest to new students of C++ ...


Update: added example programs, one that uses the C++ library list container to process strings ...and an example of splitting (tokenizing) a line of text ... using a custom split function that splits a string into 'words' as per your choice of 'delimiters'. This example parses lines of text like "two thousand and eleven" and returns the corresponding integer 2011. 


The first part consists of a series of 6 example programs that students may like to have for reference and to use as a working 'shell' from which to start a project.

1. The first program is just a most basic 'shell' that compiles, and when run, askes the user to press 'Enter' to exit/continue ...

2. The next program illustrates how to get valid numeric input in a loop and how to ask for more at the end of a do..while loop that calls the function 'more()'

3. The next program demo's a way to get and validate user input using a FUNCTION to get valid input

4. The next three programs progress from inputing numbers into an ARRAY that has the size fixed at compile time ... to using a VECTOR ... and then a LIST container to hold as many numbers as the user wishes (limited only by available memory). They also illustrate how to SORT, FIND, or ERASE elements from the respective containers. 

(All the numeric input examples above find the sum and average value of the numbers input.)


1.
Code: [Select]
// shell.cpp

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>

using namespace std;

int main()
{
    // You may need to 'un-comment' the 'cin.sync();' line BELOW, to pause your
    // program, IF (char's and) a '\n' char remains after/if 'input above' ...
   
    // cin.sync(); // effect is same as 'clear/empty' all char's in cin stream

    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


2.
Code: [Select]
// more.cpp //  // 2015-08-26 //


// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>

//using namespace std;

bool more() // defaults to 'true'/'yes' ... unless 'n' or 'N' entered
{
    std::cout << "More (y/n) ? " << std::flush;
    int reply = std::cin.get();
    std::cin.sync(); // 'flush' cin stream  ...
    if( reply == 'n' || reply == 'N' ) return false;
    // else ...
    return true;
}



int main()
{
    int count = 0, sum = 0;

    for( ; ; ) // an example C/C++ forever loop ... until 'break'
    {
        std::cout << "Enter next integer to sum: " << std::flush;
        int testInt;
        if( std::cin >> testInt && std::cin.get() == '\n' ) // Note 'and if number entered is followed immediately' ... by the '\n' //
            ++ count, sum += testInt;
        else
        {
            std::cin.clear(); // clear cin error flag(s) ...
            std::cin.sync(); // 'flush' cin stream ...
            std::cout << "Error! Integers in valid range only, please ...\n";
        }
       
        // make sure cin stream is 'empty' before calling 'more()' ...
        if( !more() ) break;
    }

    std::cout << "\nFor " << count << " numbers entered, sum was " << sum
              << " and average was " << double(sum)/count << std::endl;


    std::cout << "\nPress 'Enter' to continue/exit ... " << std::flush;
    std::cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


3.
Code: [Select]
// getValidInt.cpp //  // 2017-05-23 //


// http://developers-heaven.net/forum/index.php/topic,46.0.html


#include <iostream>
using namespace std;

int getValidInt( const char prompt[] )
{
    for( ; ; ) // an example of a C/C++ forever loop ... until 'return'
    {
        cout << prompt;
        int testInt;
        cin >> testInt;
        if( cin.good() && cin.get() == '\n' ) // Note 'and if number entered is followed immediately' ... by the '\n' //
            return testInt;
        // else ...
        cin.clear(); // clear cin error flag(s) ...
        cin.sync();
        cout << "Invalid input! Integers only please ...\n" ;
    }
}

bool more()// defaults to 'true'/'yes' ... unless 'n' or 'N' entered
{
    cout << "More (y/n) ? ";
    int reply = cin.get();
    cin.sync(); // 'flush' cin stream ...
    if( reply == 'n' || reply == 'N' ) return false;
    // else ...
    return true;
}




int main()
{
    int count = 0, sum = 0;

    do
    {
        int testInt = getValidInt( "Enter next integer to sum: " );
        sum += testInt;
        ++ count;
    }
    while( more() ); // make sure cin stream is 'empty' before calling more()

    cout << "\nFor " << count << " numbers entered, sum was " << sum
         << " and average was " << float(sum)/count << endl;

    cout << "\nPress 'Enter' to continue/exit ... ";
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


4. First an array of integers ... (see if you can fix up the following to avoid the potential 'divide by zero error' problem in these next three examples) ...
Code: [Select]
// arrayInt.cpp //  // 2015-05-11 //

// enters integer data, finds sum, average, sorts, finds value, erase, show ...

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <algorithm> // re. sort(..), find(..)
using namespace std;

int const MAX_SIZE = 4; // using a small size here for easier testing ...

int getValidInt( const char* prompt )
{
    for( ; ; ) // an example of a C/C++ forever loop ... until 'return'
    {
        cout << prompt << flush;
        int testInt;
        if( cin >> testInt && cin.get() == '\n' )  // Note 'and if number entered is followed immediately' ... by the '\n' //
            return testInt;

        // else ...
        cin.clear(); // clear cin error flag(s) ...
        cin.sync(); // 'flush' cin stream ...
        cout << "Invalid input! Integers only please ...\n" ;
    }
}

bool more()// defaults to 'true'/'yes' ... unless 'n' or 'N' entered
{
    cout << "More (y/n) ? " << flush;
    int reply = cin.get();
    cin.sync(); // 'flush' cin stream ...
    if( reply == 'n' || reply == 'N' ) return false;
    // else ...
    return true;
}

double sumAry( const int* ary, int size )
{
    double sum = 0.0;
    for( int i = size-1; i >= 0; --i )
        sum += ary[i];
    return sum;
}

void showAry( const int ary[], int size )
{
    for( int i = 0; i < size; ++i ) cout << ary[i] << " ";
}

/*
int findIndex( const int ary[], int size, int value )
{
    for( int i = 0; i < size; ++i )
        if( ary[i] == value ) return i;
    // else if reach here ...
    return -1;
}

void eraseIndex( int ary[], int& size, int index )
{
    if( index < 0 || index >= size )
        { cout << "ERROR! Index out of range\n"; return; }
    for( int i = index; i < size-1; ++i )
        ary[i] = ary[i+1]; // copy each element above, down one index, so erased
    // now update size by ref...
    --size;
}
*/

void erasePointer( int ary[], int& size, int* p )
{
    if( p < ary || p >= ary+size )
        { cout << "ERROR! Pointer out of range\n"; return; }
   
    for( int* q = ary+size-1; p < q; ++p )
        *p = *(p+1); // copy each element above, down one index, so erased
/*
for( int i = p - ary; i < size-1; ++i )
ary[i] = ary[i+1];
*/
// now update size by ref...
    --size;
}


int main()
{
    int my_ary[ MAX_SIZE ]; // create array to hold upto MAX_SIZE int's
    int size = 0;

    while( more() ) // make sure cin stream is 'empty' before calling more()
    {
        int tmpInt = getValidInt( "Enter next integer to sum: " );
        my_ary[ size ] = tmpInt;
        ++ size;
        if( size == MAX_SIZE )
        {
            cout << "You have reached the maximum " << MAX_SIZE
                 << " number of elements.\n";
            break;
        }
    }
   
    double sum = sumAry( my_ary, size );
    cout << "\nFor " << size << " numbers entered, sum was " << sum
         << " and array average was " << sum/size << endl;
         
    cout << "\nshowAry: "; showAry( my_ary, size );
   
    int last = my_ary[ size-1 ]; // note: 'i' is always at least 1 ... or more ...
   
    sort( my_ary, my_ary+size );
    cout << "\n\nAfter sorting ...";
    cout << "\nshowAry: "; showAry( my_ary, size );
   
    int* p = find( my_ary, my_ary+size, last );  // search from begin to (1 before) 'end'

    //int index = findIndex( my_ary, i, last );
    //eraseIndex( my_ary, i, index );
    if( p != my_ary+size ) // i.e. if p != 'end' ('end' points to 1 past last element)
    {
        erasePointer( my_ary, size, p ); // note size is updated if p was erased //

        cout << "\n\nAfter erasing " << last << " ...";
        cout << "\nshowAry: "; showAry( my_ary, size );
    }
    else cout << last << " NOT found in array.\n";
             
    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


5. Then a vector of integers ...
Code: [Select]
// vectorInt_C++11.cpp //  // 2016-10-03 //

// enters integer data, finds sum, average, sorts, finds value, erase, show ...

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm> // re. sort(..), find(..)

//using namespace std;


int getValidInt( const char* prompt )
{
    for( ; ; ) // an example of a C/C++ forever loop ... until 'return'
    {
        std::cout << prompt << std::flush;
        int testInt;
        if( std::cin >> testInt && std::cin.get() == '\n' )
            return testInt;
        // else ...
        std::cin.clear(); // clear cin error flag(s) ...
        std::cin.sync(); // 'flush' cin stream
        std::cout << "Invalid input! Integers only please ...\n" ;
    }
}

bool more()// defaults to 'true'/'yes' ... unless 'n' or 'N' entered
{
    std::cout << "More (y/n) ? " << std::flush;
    int reply = std::cin.get();
    std::cin.sync(); // 'flush' cin stream ...
    if( reply == 'n' || reply == 'N' ) return false;
    // else ...
    return true;
}

double sumVec( const std::vector< int >& v )
{
    double sum = 0;
    for( const auto& e : v )
        sum += e;
    return sum;
}

void showVec( const std::vector< int >& v )
{
    for( const auto& e : v )
         std::cout << e << " ";
}

std::ostream& operator << ( std::ostream& os, const std::vector< int >& v )
{
    for( const auto& e : v ) os << e << " ";
    return os;
}



int main()
{
    std::vector< int > my_vec; // create an empty vector to hold integers ...
    while( more() )
    {
        auto tmpInt = getValidInt( "Enter next integer to sum: " );
        my_vec.push_back( tmpInt );
    }
   
    double sum = sumVec( my_vec );
   
    if( my_vec.size() )
        std::cout << "\nFor " << my_vec.size() << " numbers entered, sum was " << sum
                  << " and vector average was " << sum/my_vec.size() << std::endl;

    std::cout << "\nshowVec: "; showVec( my_vec );

    if( my_vec.size() )
    {
        auto last = *( -- end( my_vec ) );
        // or, ok here: int last = my_vec[ my_vec.size()-1 ]; //

        std::cout << "\n\nAfter sorting ...";
        std::sort( begin( my_vec ), end( my_vec ) );
        std::cout << '\n' << my_vec;

        auto it = std::find( begin( my_vec ), end( my_vec ), last );
        if( it != end( my_vec ) )
        {
            my_vec.erase( it );

            std::cout << "\n\nAfter erasing " << last << " ...";
            std::cout << '\n' << my_vec << std::endl;
        }
        else std::cout << last << " NOT found in 'my_vec' ...\n";
    }

    std::cout << "\nPress 'Enter' to continue/exit ... " << std::flush;
    std::cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


6. And finally a list of integers ...
Code: [Select]
// listInt_C++11.cpp //  // 2015-08-26 //

// enters integer data, finds sum, average, sorts, finds value, erase, show ...

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <list>
#include <algorithm> // re. find(..)

//using namespace std;

int getValidInt( const char* prompt )
{
    for( ; ; ) // an example of a C/C++ forever loop ... until 'return'
    {
        std::cout << prompt << std::flush;
        int testInt;
        if( std::cin >> testInt && std::cin.get() == '\n' )
            return testInt;
        // else ...
        std::cin.clear(); // clear std::cin error flag(s) ...
        std::cin.sync(); // 'std::flush' std::cin stream
        std::cout << "Invalid input! Integers only please ...\n" ;
    }
}

bool more() // defaults to 'true'/'yes' ... unless 'n' or 'N' entered
{
    std::cout << "More (y/n) ? " << std::flush;
    int reply = std::cin.get();
    std::cin.sync(); // 'std::flush' std::cin stream ...
    if( reply == 'n' || reply == 'N' ) return false;
    // else ...
    return true;
}

double sumList( const std::list< int >& lst )
{
    double sum = 0;
    for( const auto& e : lst ) sum += e;
    return sum;
}

void showList( const std::list< int >& lst )
{
    for( const auto& e : lst ) std::cout << e << ' ';
}

std::ostream& operator << ( std::ostream& os, const std::list< int >& lst )
{
    for( const auto& e : lst ) os << e << ' ';
    return os;
}



int main()
{
    std::list < int > my_lst; // create empty std::list to hold integers ...
   
    while( more() ) // make sure std::cin stream is 'empty' before calling more()
    {
        auto tmpInt = getValidInt( "Enter next integer to sum: " );
        my_lst.push_back( tmpInt );
    }
   
    auto sum = sumList( my_lst );
    if( my_lst.size() )
        std::cout << "\nFor " << my_lst.size() << " numbers entered, sum was " << sum
             << " and std::list average was " << sum/my_lst.size() << std::endl;
         
    std::cout << "\nshowList: "; showList( my_lst );
   
    if( my_lst.size() )
    {
        auto last = * -- end( my_lst ); // * means to take value at pointer //

        std::cout << "\n\nAfter sorting ...";
        my_lst.sort();
        std::cout << '\n' << my_lst;

        auto it = find( begin( my_lst ), end( my_lst ), last );
        if( it != end( my_lst ) )
        {
            my_lst.erase( it );

            std::cout << "\n\nAfter erasing " << last << " ...";
            std::cout << '\n' << my_lst;
        }
        else std::cout << last << " NOT found in 'my_lst' ...\n";
    }
   
    std::cout << "\nPress 'Enter' to continue/exit ... " << std::flush;
    std::cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


This next ... is a nice little student problem, to read from file, several names and blood pressures,
and then to display results and diagnosis ...

This 'problem' leads naturally to OOP (Object Oriented Programming) in C++ ...
i.e. the use of struct and/or class where one keeps the data and the functions to process that data ... together ...
i.e. encapsulation ...


Code: [Select]
// bp_classWithOverloadedInOut.cpp //  // revised 2015-05-11 //

// http://developers-heaven.net/forum/index.php/topic,46.0.html

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

using namespace std;

// data file is structured like this ...
/*
Smith Jane 111/76
Jones Rob 98/70
Costello Judy-Ann 144/90
Frank-Anderson Bibby-Bonnie 190/30
Sue Peggy 10/5
James-Thomas Andrew 190/111
*/
const string MY_FILE = "BP.txt";

const string UNKNOWN = "*** Unrecognized diagnosis ***\n"
                       "*** Please check validity of data entered ***";

class BP
{
public:
    string get_diagnosis() const // Note: need 'const' since returning 'literal'
    {
        if( sys < 120/2 || dia < 80/2 ) // ?? //
            return UNKNOWN;
        if( sys > 120*2 || dia > 80*2 ) // ?? //
            return UNKNOWN;
           
        if( sys >= 160 || dia > 100 )
            return "*** Check age re. possible Stage 2 Hypertension ***";
        if( sys >= 140 || dia >= 90 )
            return "*** Check age re. possible Stage 1 Hypertension ***";
        if( sys >= 120 || dia >= 80 )
            return "*** Check age re. possible Pre-Hypertension ***";
           
        // else ...
        return "Normal";
    }
private:
    string lname;
    string fname;
    int sys;
    int dia;
   
    // define overloaded << for output of BP objects ...
    friend ostream& operator << ( ostream& os, const BP& p )
    {
        return os << setw(40) << left << setfill( '.' )
                  << p.lname + ", " + p.fname + ' ' << setfill( ' ')
                  << " blood pressure was : " << right << setw(3) << p.sys << '/'
                  << p.dia << '\n' << p.get_diagnosis();
    }

    // define overloaded >> for input of BP objects ...
    friend istream& operator >> ( istream& is, BP& p )
    {
        char skip;
        string scrap; // <-- IF you comment out this line ... and ...
        is >> p.lname >> p.fname >> p.sys >> skip >> p.dia;
        getline( is, scrap ); // <--  and also comment out this line ... the problem is resolved. //
        return is;
    }
} ; // <-- don't forget semi-colon here to signify the class ends here



int main()
{
    ifstream fin( MY_FILE.c_str() ); // C++ string gets converted to C string

    if( fin )
    {
        BP tmp;
        while( fin >> tmp ) // friend function handles getting data into private members
        {
            cout << tmp << '\n' << endl; // friend function handles output of private data
        }
        fin.close();
    }

    cout << "Press 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


But NOTE!!!   There exists a subtle PROBLEM in reading the last line in the file:  "BP.txt" 

IF ...

you had an 'end_of_line', i.e. an '\n'  mark there,
(with Windows operating systems, this is carriage return and linefeed),
it would have read ok, but minus that ... A PROBLEM exists ... i.e. last line IS NOT read ok !!!

How to handle this ???

Ah-hah !!!

Simply read the whole file line firstly, using getline( ... )
then parse that line as you wish ... probably using a stringstream object to ease the parsing.

See following suggested fixed-up-code that handles this ok:

Code: [Select]
    // define overloaded >> for input of BP objects ...
    friend istream& operator >> ( istream& is, BP& p )
    {
        string line;
        getline( is, line );
        istringstream iss( line ); // construct iss from line ...
        char skip;
        iss >> p.lname >> p.fname >> p.sys >> skip >> p.dia;
        return is;
    }
« Last Edit: September 06, 2018, 03:13:00 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #1 on: February 13, 2011, 02:02:50 AM »
Here is an other version of the class BP example ... a version that takes in data via user keyboard (and NOT from an existing data file),
(and a way to code for it that attempts to minimize changes needed to the above code.)

Code: [Select]
// bp_class_input_via_keyboard.cpp //  // revised 2015-08-12 //

// http://developers-heaven.net/forum/index.php/topic,46.0.html

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


using namespace std;

const string HEADER = "This program takes in names and blood presures.\n"
                      "Then it prints out a preliminary diagnosis for that data ...";

const string PROMPT = "All on one line, enter last name(s), first name(s), systolic/diastolic: \n";

const string UNKNOWN = "*** Unrecognized diagnosis ***\n"
                       "*** Please check validity of data entered ***";

// left trim ... erase leading whote space //
void ltrim( string& s, const string& ws = " \t" )
{
    size_t pos = s.find_first_not_of( ws );
    if( pos != string::npos) s.erase( 0, pos ); // erase leading ws //
    else s.clear(); // was all ws //
}

class BP
{
public:
    // default ctor...
    BP() : sys(0), dia(0) {};
   
    string get_diagnosis() const // Note: need 'const' since returning 'literal'
    {
        if( sys < 120/2 || dia < 80/2 ) // ?? //
            return UNKNOWN;
        if( sys > 120*2 || dia > 80*2 ) // ?? //
            return UNKNOWN;
           
        if( sys >= 160 || dia > 100 )
            return "*** Check age re. possible Stage 2 Hypertension ***";
        if( sys >= 140 || dia >= 90 )
            return "*** Check age re. possible Stage 1 Hypertension ***";
        if( sys >= 120 || dia >= 80 )
            return "*** Check age re. possible Pre-Hypertension ***";
           
        // else ...
        return "Normal";
    }
private:
    string lname;
    string fname;
    int sys;
    int dia;
   
    // define overloaded << for output of BP objects ...
    friend ostream& operator << ( ostream& os, const BP& p )
    {
        return os << setw(40) << left << setfill( '.' )
                  << p.lname + ", " + p.fname + ' ' << setfill( ' ')
                  << " blood pressure was : " << right << setw(3) << p.sys << '/'
                  << p.dia << '\n' << p.get_diagnosis();
    }

    // define overloaded >> for input of BP objects ...
    friend istream& operator >> ( istream& is, BP& p )
    {
        for( ; ; )
        {
            string line;
            getline( is, line );
            istringstream iss( line ); // construct iss from line ...
            getline( iss, p.lname, ',' );
            getline( iss, p.fname, ',' );
            ltrim( p.fname ); // to strip off any leading ws ...
            ltrim( p.lname ); // to dis-allow 'empty entry' for last name //
            if( !p.lname.size() || !p.fname.size() )
            {
                cout << "Must enter last name(s), (comma) first name(s), (comma) ... followed by BP ...\n";
                continue;
            }
           
            char skip;
            iss >> p.sys >> skip >> p.dia;
            if( p.sys > 0 && p.dia > 0 ) // to confirm that (non zer0) int values were entered for both //
                break;
               
            // else if reach here //
            cout << "Must enter numbers for systolic/diastolic ...\n";
        }
        return is;
    }
} ; // <-- don't forget semi-colon here to signify the class ends here


bool more()
{
    cout << "More (y/n) ? " << flush;
    string tmp;
    getline( cin, tmp );
    if( tmp.size() && (tmp[0] == 'n' || tmp[0] == 'N') ) return false;
    // else ... if reach here ...
    return true;
}




int main()
{
    cout << HEADER << "\n\n";
    do
    {
        cout << PROMPT;
        BP tmp;
        cin >> tmp; // friend function handles getting data into private member
        cout << '\n';
        cout << tmp << '\n' << endl; // friend function handles output of private data
    }
    while( more() );

    cout << "Press 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


Update: some C++11 ready versions of the above:

Code: [Select]
// vectorInt_C++11.cpp //  // 2015-08-26 //

// enters integer data, finds sum, average, sorts, finds value, erase, show ...

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm> // re. sort(..), find(..)

//using namespace std;


int getValidInt( const char* prompt )
{
    for( ; ; ) // an example of a C/C++ forever loop ... until 'return'
    {
        std::cout << prompt << std::flush;
        int testInt;
        if( std::cin >> testInt && std::cin.get() == '\n' )
            return testInt;
        // else ...
        std::cin.clear(); // clear cin error flag(s) ...
        std::cin.sync(); // 'flush' cin stream
        std::cout << "Invalid input! Integers only please ...\n" ;
    }
}

bool more()// defaults to 'true'/'yes' ... unless 'n' or 'N' entered
{
    std::cout << "More (y/n) ? " << std::flush;
    int reply = std::cin.get();
    std::cin.sync(); // 'flush' cin stream ...
    if( reply == 'n' || reply == 'N' ) return false;
    // else ...
    return true;
}

double sumVec( const std::vector< int >& v )
{
    double sum = 0;
    for( const auto& e : v )
        sum += e;
    return sum;
}

void showVec( const std::vector< int >& v )
{
    for( auto& e : v )
         std::cout << e << " ";
}

std::ostream& operator << ( std::ostream& os, const std::vector< int >& v )
{
    for( auto& e : v ) os << e << " ";
    return os;
}



int main()
{
    std::vector< int > my_vec; // create an empty vector to hold integers ...
    while( more() )
    {
        auto tmpInt = getValidInt( "Enter next integer to sum: " );
        my_vec.push_back( tmpInt );
    }
   
    double sum = sumVec( my_vec );
   
    if( my_vec.size() )
        std::cout << "\nFor " << my_vec.size() << " numbers entered, sum was " << sum
                  << " and vector average was " << sum/my_vec.size() << std::endl;

    std::cout << "\nshowVec: "; showVec( my_vec );

    if( my_vec.size() )
    {
        auto last = * -- end( my_vec );
        // or, ok here: int last = my_vec[ my_vec.size()-1 ]; //

        std::cout << "\n\nAfter sorting ...";
        std::sort( begin( my_vec ), end( my_vec ) );
        std::cout << '\n' << my_vec;

        auto it = std::find( begin( my_vec ), end( my_vec ), last );
        if( it != end( my_vec ) )
        {
            my_vec.erase( it );

            std::cout << "\n\nAfter erasing " << last << " ...";
            std::cout << '\n' << my_vec << std::endl;
        }
        else std::cout << last << " NOT found in 'my_vec' ...\n";
    }

    std::cout << "\nPress 'Enter' to continue/exit ... " << std::flush;
    std::cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}

Code: [Select]
// listInt_C++11.cpp //  // 2015-08-26 //

// enters integer data, finds sum, average, sorts, finds value, erase, show ...

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <list>
#include <algorithm> // re. find(..)

//using namespace std;

int getValidInt( const char* prompt )
{
    for( ; ; ) // an example of a C/C++ forever loop ... until 'return'
    {
        std::cout << prompt << std::flush;
        int testInt;
        if( std::cin >> testInt && std::cin.get() == '\n' )
            return testInt;
        // else ...
        std::cin.clear(); // clear std::cin error flag(s) ...
        std::cin.sync(); // 'std::flush' std::cin stream
        std::cout << "Invalid input! Integers only please ...\n" ;
    }
}

bool more() // defaults to 'true'/'yes' ... unless 'n' or 'N' entered
{
    std::cout << "More (y/n) ? " << std::flush;
    int reply = std::cin.get();
    std::cin.sync(); // 'std::flush' std::cin stream ...
    if( reply == 'n' || reply == 'N' ) return false;
    // else ...
    return true;
}

double sumList( const std::list< int >& lst )
{
    double sum = 0;
    for( const auto& e : lst ) sum += e;
    return sum;
}

void showList( const std::list< int >& lst )
{
    for( const auto& e : lst ) std::cout << e << ' ';
}

std::ostream& operator << ( std::ostream& os, const std::list< int >& lst )
{
    for( const auto& e : lst ) os << e << ' ';
    return os;
}



int main()
{
    std::list < int > my_lst; // create empty std::list to hold integers ...
   
    while( more() ) // make sure std::cin stream is 'empty' before calling more()
    {
        auto tmpInt = getValidInt( "Enter next integer to sum: " );
        my_lst.push_back( tmpInt );
    }
   
    auto sum = sumList( my_lst );
    if( my_lst.size() )
        std::cout << "\nFor " << my_lst.size() << " numbers entered, sum was " << sum
             << " and std::list average was " << sum/my_lst.size() << std::endl;
         
    std::cout << "\nshowList: "; showList( my_lst );
   
    if( my_lst.size() )
    {
        auto last = * -- end( my_lst );

        std::cout << "\n\nAfter sorting ...";
        my_lst.sort();
        std::cout << '\n' << my_lst;

        auto it = find( begin( my_lst ), end( my_lst ), last );
        if( it != end( my_lst ) )
        {
            my_lst.erase( it );

            std::cout << "\n\nAfter erasing " << last << " ...";
            std::cout << '\n' << my_lst;
        }
        else std::cout << last << " NOT found in 'my_lst' ...\n";
    }
   
    std::cout << "\nPress 'Enter' to continue/exit ... " << std::flush;
    std::cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


Now here is an often seen beginning student problem ... programming a bank account type program to handle balance, deposits and withdrawals ...

The following program only handles integer input and display.  It illustrates passing and returning values by reference ... and also returning a function value.

Code: [Select]
// bankAccount.cpp //  // 2017-05-24 //

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>

using namespace std;

int getValidInt( const char* prompt )
{
    for( ;; ) // an example of a C/C++ forever loop ... until 'return'
    {
        cout << prompt << flush;
        int testInt;
        cin >> testInt;
        if( cin.good() && cin.get() == '\n' )
            return testInt;
        // else ...
        cin.clear(); // clear cin error flag(s) ...
        cin.sync();
        cout << "Invalid input! Integers only please ...\n" ;
    }
}

bool more()// defaults to 'true'/'yes' ... unless 'n' or 'N' entered
{
    cout << "More (y/n) ? " << flush;
    int reply = cin.get();
    cin.sync(); // 'flush' cin stream
    if( reply == 'n' || reply == 'N' ) return false;
    // else ...
    return true;
}

int transactions( int& deposits, int& withdrawals )
{
    int net = 0;
    cout << "Enter a negative value to indicate a withdrawal.\n";
    for( ; ; )
    {
        int amount = getValidInt( "Enter dollars for this transaction (0 to exit)    : " );
        if( amount > 0 ) ++ deposits;
        else if( amount < 0 ) ++ withdrawals;
        else return net;
        net += amount;
    }
}

void showResults( int balance, int deposits, int withdrawals, int net_change )
{
    cout << "Opening balance       : " << balance << endl
         << "Number of Deposits    : " << deposits << endl
         << "Number of withdrawals : " << withdrawals << endl
         << "Closing balance       : " << (balance + net_change) << endl;
}



int main()
{
    do
    {
        int balance = getValidInt( "Please enter your new starting balance (dollars)  : " );
        int deposits = 0, withdrawals = 0;       
        int net_change = transactions( deposits, withdrawals );
        showResults( balance, deposits, withdrawals, net_change );
    }
    while( more() ); // make sure cin stream is 'empty' before calling 'more()' ...
}


Another common beginning student problem (to go with the C version of this problem) ...

Code: [Select]
// incomeTax.cpp //  // 2017-05-24 //

// http://developers-heaven.net/forum/index.php/topic,46.0.html

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

const int  STD_DEDUCT = 11000;  // in dollars
const int   NO_TAX_ON = 11000;  // in dollars
const int   STEP_UP_2 = 22000;  // tax step size in dollars
const double TAX_RATE = 0.11;   // beginning tax rate of taxable income
const double MAX_FRAC = 0.33;   // of taxable income


template < typename T >
string toStrCommasAdded( T val )
{
    stringstream ss;
    ss << val;

    string tmp, decimal;
    ss >> tmp;

    char sign = ' '; // use space for pos sign //
    if( tmp[0] == '-' )
    {
        sign = '-';
        tmp.erase( 0, 1 ); // erase neg sign from tmp string //
    }

    size_t pos;
    if( (pos = tmp.find('.')) != string::npos )
    {
        decimal = tmp.substr( pos ); // include decimal point //
        tmp.erase( pos );
    }


    int len = tmp.size();
    int len2 = len + (len-1)/3;

    // construct right size and filled with commas //
    string tmp2( len2, ',' );
    int comma = 0;
    while( len2 )
    {
        --len, --len2, ++comma;

        if( comma == 4 )
        {
            comma = 1;
            //tmp2[len2] = ',';
            --len2;
        }
        tmp2[len2] = tmp[len];
    }

    return sign + tmp2 + decimal;
}

int getValidInt( const char* prompt )
{
    for( ; ; ) // an example of a C/C++ forever loop ... until 'return'
    {
        cout << prompt;
        int testInt;
        if( cin >> testInt && cin.get() == '\n' )
            return testInt;
        // else ...
        cin.clear(); // clear cin error flag(s) ...
        cin.sync();
        cout << "Invalid input! Integers only please ...\n" ;
    }
}

bool more() // defaults to 'true'/'yes' ... unless 'n' or 'N' entered
{
    cout << "More (y/n) ? ";
    int reply = cin.get();
    cin.sync(); // 'flush' cin stream ...
    if( reply == 'n' || reply == 'N' ) return false;
    // else ...
    return true;
}

int getTotDeductions()
{
    return getValidInt( "Enter the total sum of all allowable deductions: " );
}

double incomeTax()
{
    int grossIncome = getValidInt( "Enter gross income in dollars: " );
    int deduction = getTotDeductions();

    if( deduction < STD_DEDUCT )  deduction = STD_DEDUCT;

    int netIncome;
    if( deduction >= grossIncome ) netIncome = 0;
    else netIncome = grossIncome - deduction;

    int taxIncome = netIncome - NO_TAX_ON;
    if( taxIncome < 0 ) taxIncome = 0;
    double rate = TAX_RATE;
    double taxIncomeTmp = taxIncome;
   
    double tax = 0.0;
   
    while( taxIncomeTmp >= STEP_UP_2  &&  tax < taxIncome*MAX_FRAC
                                      &&  rate < MAX_FRAC )
    {
        tax += rate*STEP_UP_2;
        //cout << setprecision(2) << fixed << setw(17) << rate*STEP_UP_2 << '\n';
        rate *= (1+TAX_RATE);
        taxIncomeTmp -= STEP_UP_2;
    }
    if( taxIncomeTmp > 0 ) tax += rate*taxIncomeTmp;
    if( tax > taxIncome*MAX_FRAC ) tax = taxIncome*MAX_FRAC;


    cout << "Your deduction      : " << toStrCommasAdded(deduction) << endl
         << "Your net income     : " << toStrCommasAdded(netIncome) << endl
         << "Your taxable income : " << toStrCommasAdded(taxIncome) << endl;
    cout << setprecision(6) << fixed
         << "Your tax rate       : " << setprecision(6)
         << ( taxIncome > 0 ? tax/taxIncome : 0 ) << endl;

    return  tax;
}



int main()
{
    do
    {
        double tax = incomeTax();
        int itax = tax;
        int cents = int((tax - itax)*100 + .5);
        cout << "Your income tax payable this year is: "
             << toStrCommasAdded(itax);
        if( cents ) cout << '.' << cents;
        else cout<< ".00";
        cout << endl;
    }
    while( more() ); // make sure cin stream is 'empty' before calling more()
}
« Last Edit: May 24, 2017, 03:41:16 PM by David »

Offline admin

  • Administrator
  • Sr. Member
  • *****
  • Posts: 296
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #2 on: February 15, 2011, 12:32:59 PM »
Thanks David, nice topic.

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #3 on: February 23, 2011, 05:20:15 AM »
Here is a recent student problem that may illustrate parsing a line of text.  It uses the custom header file trim_split_cpp_void.h (that follows this program) to convert a line of text like "two thousand and eleven"

and output the corresponding integer ...

2011

Code: [Select]
// wordNumToInt.cpp //  // 2017-05-24 //

// NOTE: input validation is incomplete, but see comments in program for clues

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <string>
#include <list>
#include <cctype> // re. tolower
using namespace std;

// using the included 'void split' function to split string into list of words
#include "trim_split_cpp_void.h" // this include file also needs above <string>, <list> and namespace std


const string HEADER =
    "\tThis program takes in strings like \"two thousand and eleven\" \n"
    "\tand then outputs the corresponding integer value of 2011 \n\n"
    "\tPlease note: the VALID OUTPUT RANGE is from 0 to 999,999,999 \n";
   

// using this global variable ...
bool globalStrIsValid; // to assist in the input validation

struct table
{
    string word;
    int num;
} ;

const table TBL[] =
{
    {"million", 1000000}, {"thousand", 1000}, {"hundred", 100},
    {"ninety", 90}, {"eighty", 80}, {"seventy", 70}, {"sixty", 60},
    {"fifty", 50}, {"forty", 40}, {"thirty", 30}, {"twenty", 20},
    {"nineteen", 19}, {"eighteen", 18}, {"seventeen", 17}, {"sixteen", 16},
    {"fifteen", 15}, {"fourteen", 14}, {"thirteen", 13}, {"twelve", 12},
    {"eleven", 11}, {"ten", 10}, {"nine", 9}, {"eight", 8}, {"seven", 7},
    {"six", 6}, {"five", 5}, {"four", 4}, {"three", 3}, {"two", 2},
    {"one", 1}, {"a", 1},{"zero", 0}
};
const int SIZE_TBL = sizeof TBL / sizeof TBL[0];

bool more() // defaults to 'true'/'yes' ... unless 'n' or 'N' entered
{
    cout << "More (y/n) ? " << flush;
    string reply;
    getline( cin, reply );
    if( reply == "n" || reply == "N" ) return false;
    // else ...
    return true;
}

string myToLower( const string& s )
{
    string lower;
    lower.resize( s.size() );
    for( int i = s.size()-1; i >= 0; --i ) lower[i] = tolower( s[i] );
    return lower;
}


// these next 3 functions are used by the 'convert' function that follows ...
int getIndex( const string& s )
{
    for( int i = 0; i < SIZE_TBL; ++i )
        if( s == TBL[i].word ) return i;
    // else ...
    globalStrIsValid = false;
    return -1; // NOT found ...
}

int getValue( const string& s )
{
    int index = getIndex( s );
    if( index != -1 ) return TBL[ index ].num;
    // else ...
    return -1; // invalid request ...       
}

bool valid203040__90( int i )
{
    if( i % 10 == 0 && i/10 >= 2 && i/10 <= 9 ) return true;
    //else ...
    return false;
}


int convert( const string& s );
// first splits the string into a list of words using the included split function
// then creates a new list with every word 'and' in the original string erased
// then processes ... and finds millions, thousands, hundreds, and 0..99 values
// then returns sum of all the above 'int' values ...



int main()
{
    cout << HEADER << endl;
    do
    {
        cout << "Please enter a valid number string to convert ..." << endl;
        string s;
        getline( cin, s );
        globalStrIsValid = true;
        int num = convert( myToLower( s ));
        if( globalStrIsValid )
            cout << "You entered: " << s << endl
                 << "Converted to an int is: " << num << endl << endl;
        else cout << "\nInvalid input!" << endl << endl;                ;
    }
    while( more() ); // make sure cin stream is 'empty' before calling 'more()'
}


int convert( const string& s )
{   
    list < string > lst2, lst;
    split( lst, s, " \t-," ); // get all 'words' into the list lst ...
    list < string >::iterator i, j, k, m;
    //cout << "The new list 'lst2' WITHOUT 'and' is:\n";   
    for( i = lst.begin(); i != lst.end(); ++i )
        if( *i != "and" ) { lst2.push_back( *i ); /* cout << *i << endl; */ }         

    // process further to get ...
    //      millions  value in range 1..999 million
    //      thousands value in range 1..999 thousand
    //      hundreds  value in range   1..9 hundred
    //      remaining value in range  0..99 (if the foregoing values exist)
   
    int val = 0;
    int offset = 0;
    int size = lst2.size();
   
    if( !size )
    {
        cout << "Please enter some valid number ...";
        globalStrIsValid = false;
        return -1;
    }   
   
    // now find millions value if it exists ...
    for( i = lst2.begin(); offset < size; ++i, ++offset )
    {
        if( *i == "million" )
        {
            if( offset == 4 ) // valid *i: 1..9, *j: 100, *k: 20..90, *m: 1..9
            {
                m = --i;
                k = --i;
                j = --i;
                --i;
                val += getValue( *i )* getValue( *j ) + getValue( *k ) + getValue( *m );
            }           
            else if( offset == 3 ) // valid *i: 1..9, *j: 100, k: 1..20 or 30,40..90
            {
                k = --i;
                j = --i;
                --i;
                val += getValue( *i )* getValue( *j ) + getValue( *k );
            }
            else if( offset == 2 )
            {
                k = --i;
                --i;
                if( *k == "hundred" )
                {
                    if( getValue( *i ) > 9 )
                    {
                        globalStrIsValid = false;
                        cout << "Only 1..9 hundred allowed";
                        return -1;
                    }
                    val += getValue( *i ) * 100;
                }
                else // valid *i: 20,30,40..90, *k: 1..9
                    val += getValue( *i ) + getValue( *k );
            }
            else if( offset == 1 ) // valid *i: 1..20 or 30,40..90
            {
                --i;
                val += getValue( *i );   
            }
            else { /* cout << "Invalid input!\n"; */ globalStrIsValid = false; return -1; }
           
            val *= 1000000;
            // now erase first offset+1 number of elements from list
            int parts = 0;
            for( i = lst2.begin(); parts <= offset; ++parts )
                lst2.erase( i++ );
        }
    }

    int val_1000 = 0;
    offset = 0;
    size = lst2.size();
    //cout << "lst2.size() now is: " << size << endl;
   
    // now find thousands value 1..999 if it exists ...
    for( i = lst2.begin(); offset < size; ++i, ++offset )
    {
        if( *i == "thousand" )
        {
            if( offset == 4 ) // valid *i: 1..9, *j: 100, *k: 20..90, *m: 1..9
            {
                m = --i;
                k = --i;
                j = --i;
                --i;
                val_1000 += getValue( *i )* getValue( *j ) + getValue( *k ) + getValue( *m );
            }           
            else if( offset == 3 ) // valid *i: 1..9, *j: 100, k: 1..20 or 30,40..90
            {
                k = --i;
                j = --i;
                --i;
                val_1000 += getValue( *i )* getValue( *j ) + getValue( *k );
            }
            else if( offset == 2 )
            {
                k = --i;
                --i;
                if( *k == "hundred" )
                {
                    if( getValue( *i ) > 9 )
                    {
                        globalStrIsValid = false;
                        cout << "Only 1..9 hundred allowed";
                        return -1;
                    }
                    val_1000 += getValue( *i ) * 100;
                }
                else // valid *i: 20,30,40..90, *k: 1..9
                    val_1000 += getValue( *i ) + getValue( *k );
            }
            else if( offset == 1 ) // valid *i: 1..20 or 30,40..90
            {
                --i;
                val_1000 += getValue( *i );   
            }
            else { cout << "Invalid input!\n"; globalStrIsValid = false; return -1; }
           
            val_1000 *= 1000;
            // now erase first offset+1 number of elements from list
            int parts = 0;
            for( i = lst2.begin(); parts <= offset; ++parts )
                lst2.erase( i++ );
        }
    }
   
    int val_100 = 0;
    offset = 0;
    size = lst2.size();
    //cout << "lst2.size() now is: " << size << endl;
   
    // now find hundreds value 1..9 if it exists ...
    for( i = lst2.begin(); offset < size; ++i, ++offset )
    {
        if( *i == "hundred" )
        {
            if( offset == 1 )
            {
                k = --i;
                if( getValue( *k ) > 9 )
                {
                    globalStrIsValid = false;
                    cout << "Only 1..9 hundred allowed";
                    return -1;
                }               
                val_100 += getValue( *k );   
            }
            else
            { /* cout << "Invalid input!\n"; */
                globalStrIsValid = false;
                cout << "Only 1..9 hundred allowed ";
                return -1;
            }
           
            val_100 *= 100;
            // now erase first offset+1 number of elements from list
            int parts = 0;
            for( i = lst2.begin(); parts <= offset; ++parts )
                lst2.erase( i++ );
        }
    }
   
    int val_0_99 = 0;
    size = lst2.size();
    //cout << "lst2.size() now is: " << size << endl;

    // now find the value 0..99 (if a number for that range still exists to extract)
    if( size )
    {
        j = i = lst2.begin();
        if( size == 1 ) // valid *i: 0..20 or 30,40..90
            val_0_99 += getValue( *i );
        else if( size == 2 ) // valid *i: 20,30,40..90, valid *j: 1..9.
        {
            ++j;
            if( getValue( *j ) > 9 )
            {
                globalStrIsValid = false;
                cout << "Only 1..9 allowed after " << *i;
                return -1;
            }

            if( !valid203040__90( getValue( *i )))
            {
                globalStrIsValid = false;
                cout << "Only 20, 30, 40..90 allowed before " << *j;
                return -1;
            }
                           
            val_0_99 += getValue( *i ) + getValue( *j );
            //if( val_0_99 < 21 ) { globalStrIsValid = false; return -1; }
        }
        else { /* cout << "Invalid input!\n"; */ globalStrIsValid = false; return -1; }
    }
   
    return val + val_1000 + val_100 + val_0_99;
}
« Last Edit: May 24, 2017, 05:14:33 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #4 on: February 23, 2011, 05:28:31 AM »
Now ... the header file needed above ...

Code: [Select]
// trim_split_cpp_void.h  // this version 2011-02-20 //

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#ifndef dwSPLIT_CPP_VOID_H
#define dwSPLIT_CPP_VOID_H


// needs all these ...
/*
#include <string>
#include <list>
using namespace std;
*/

#ifndef trim
#define trim strip
#define ltrim lstrip
#define rtrim rstrip
#endif

// trim leading and trailing whitespaces from 's' ... and return by 'ref.'
void strip( string& s, const string t = " \t" ) // default whitespace: "\t "
{
    size_t p1 = s.find_first_not_of( t ); // get index of 'first char' ...
    if( string::npos != p1  ) // ok ... not all ws or empty ... so can safely
    {
        s.erase( 0, p1);
        size_t p2 = s.find_last_not_of( t ); // get index of 'last char' ...
        s.erase( p2+1 );
    }
    else // ... all whitespaces or empty
        s.clear();
}

// trim trailing whitespaces only ...
void rstrip( string& s, const string t = " \t" )
{
    size_t p2 = s.find_last_not_of( t );
    if( string::npos != p2 )
        s.erase( p2+1 );
    else
        s.clear();
}

// trim leading whitespaces only ...
void lstrip( string& s, const string t = " \t" )
{
    size_t p1 = s.find_first_not_of( t );
    if( string::npos != p1 )
        s.erase( 0, p1 );
    else
        s.clear();
}

void split( list<string>& lst, const string& s, const string delimits = " \t" )
{
    size_t p1, p2 = 0;
    for( ; ; ) // loop forever ... until break
    {
        p1 = s.find_first_not_of( delimits, p2 ); // Note: p2 is 0 on first loop
        if( string::npos == p1 ) break; // i.e. if empty or all delimits

        p2 = s.find_first_of( delimits, p1+1 );
        if( string::npos != p2 ) // i.e. if still more ... p2 is not past end
            lst.push_back( s.substr( p1, p2-p1 ) );
        else
        {
            lst.push_back( s.substr( p1 ) );
            break;
        }
    }
}

#endif


Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #5 on: February 23, 2011, 05:32:37 AM »
And a version of the above header file that returns a copy of the new list created in the function ... (just in case you may need a split function like that).

Note: these header files also include trim (strip) functions for trimming whitespace from strings on the right side, or left side or both sides.

Code: [Select]
// trim_split_cpp.h // this version 2011-02-20 //

// http://developers-heaven.net/forum/index.php/topic,46.0.html

// before this, need to have included <string>, <list> and using namespace std

#ifndef dwSPLIT_CPP_H
#define dwSPLIT_CPP_H

#ifndef trim
#define trim strip
#define ltrim lstrip
#define rtrim rstrip
#endif

// trim leading and trailing whitespaces from returned copy of 's'...
string strip( const string& s, const string t = " \t" )
{
    size_t p1 = s.find_first_not_of( t );
    if( string::npos != p1  ) // ok ... not all ws or empty ... so can safely
    {
        size_t p2 = s.find_last_not_of( t ); // get index of 'last char' ...
        return s.substr( p1, p2+1-p1 );
    }
    // else ... all whitespaces or empty ... so return an empty string
    return "";
}

// trim leading whitespaces only ...
string lstrip( const string& s, const string t = " \t" )
{
    size_t p1 = s.find_first_not_of( t );
    if( string::npos != p1 )
        return s.substr( p1 );
    // else ...
    return "";
}

// trim trailing whitespaces only ...
string rstrip( const string& s, const string t = " \t" )
{
    size_t p2 = s.find_last_not_of( t );
    if( string::npos != p2 )
        return s.substr( 0, p2+1 );
    // else ...
    return "";
}

list < string > split( const string& s, const string delimits = " \t" )
{
    list < string > tmp;
    size_t p1, p2 = 0;
    for( ; ; ) // loop forever ... until break
    {
        p1 = s.find_first_not_of( delimits, p2 ); // Note: p2 is 0 on first loop
        if( string::npos == p1 ) break; // i.e. if empty or all delimits

        p2 = s.find_first_of( delimits, p1+1 );
        if( string::npos != p2 ) // i.e. if still more ... p2 is not past end
            tmp.push_back( s.substr( p1, p2-p1 ) );
        else
        {
            tmp.push_back( s.substr( p1 ) );
            break;
        }
    }
    return tmp;
}

#endif

You might also like to see ...

Six Fast Steps to Programming in C
http://developers-heaven.net/forum/index.php/topic,2022.0.html

Free coding help for beginners in C or C++
http://developers-heaven.net/forum/index.php/topic,2575.0.html

CvecOfInt.h, CvecOfString.h, Cvec.h, Cvec_func's.h (now with FUNCTION POINTERS)
http://developers-heaven.net/forum/index.php/topic,2580.0.html

ClistOfInt.h, ClistOfString.h, Clist.h, Clist_func's.h using FUNCTION POINTERS
http://developers-heaven.net/forum/index.php/topic,2582.0.html


And ...

Cvec of struct
employeeRec's_msortCvec_func's.h.c
http://developers-heaven.net/forum/index.php/topic,2581.0.html

And now a C++ STL vector version of the Cvec of struct program ...
employeeRec's_vector.cpp
http://developers-heaven.net/forum/index.php/topic,2581.msg2875.html#msg2875

Clist of struct
employeeRec's_msortClist_func's.h.c
http://developers-heaven.net/forum/index.php/topic,2583.0.html

And now a C++ STL list version of the Clist of struct program ...
employeeRec's_list.cpp
http://developers-heaven.net/forum/index.php/topic,2583.msg2890.html#msg2890
« Last Edit: August 06, 2011, 10:51:36 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #6 on: August 02, 2011, 03:35:35 AM »
Addendum:

A C++ version to go with the C version of the simulation of a road with different speeds for different sections of the road ...

Code: [Select]
// vector_of_struct_with_list.cpp // a demo/test program // 2011-08-01 //

/*
   A simulation of a 'road' ... using a STL vector to hold each road section
   
   -> each Rec (record/struct) in the vector holds the ...
      -> new speed limit and also ...
      -> a STL list of points ... for that speed and section of the road.
     
   -> the last Rec holds the final speed and the final point(s) in the 'road'
   
   -> In a loop until done, the program asks/gets from the user ...
      -> each new speed  ... and then, for this new section with that speed,
      -> a list of points
     
   -> After 'road' data is all entered, the program calculates and displays
      -> the distance travelled
      -> the time taken
      -> the average speed travelled for the distance and time

   -> Note 1: this program assumes that 'the speed limit' equals
              ... the average speed travelled during each new section
              ... and sub section
   -> Note 2: when a section ends, the average speed used for the last subsection
              is the speed limit of the next section, (if a next section exits)
*/

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <list>
#include <vector>

using namespace std;

struct Point
{
    int x;
    int y;

    friend ostream& operator << ( ostream& os, const Point& p )
    {
        os << "(" << p.x << ", " << p.y << ")";
        return os;
    };
} ;

// show all points in list ...
ostream& operator << ( ostream& os, const list< Point >& ml )
{
    if( ml.size() )
    {
        list< Point >::const_iterator it;
        for( it = ml.begin(); it != ml.end(); ++it )
            os << *it << endl;
        os << "List size = " << ml.size() << endl;
    }
    else os << "The list is empty ... "  << endl;
   
    return os;
}


// and now ... getting ready for the vector of Rec's  ...
struct Rec
{
    int speed;
    list <Point> points;
} ;


// fuctions used by main ...
int getValidInt( const string& prompt );
bool more( const string& prompt );
float getDist( Point span[] );
int cal_and_show_stats ( const vector< Rec >& );




int main() /////////////////////////////////////////////////////////////////////
{
    vector< Rec > v;
   
    do // for each 'section' ...
    {
        Rec r;
        r.speed = getValidInt( "Enter next speed: " );
        cout << endl;
        do // now get all points at this speed in this section ...
        {
            Point p; // 'p' used to hold x and y of each new point ...
            p.x = getValidInt( "Enter next x: " );
            p.y= getValidInt( "Enter next y: " );
            r.points.push_back( p ); // Ok ... add this point ...
        }   
        while( more( "\nMore points" ) );
       
        v.push_back( r ); // ok ... add this 'section' ...
    } // make sure cin stream is 'empty' before call more()
    while( more( "\nMore sections" ) );
   
   
    cout << "\nShowing vector ..." << endl;
    for( int i = 0; i < (int)v.size(); ++i )
    {
        cout << "Points for section " << i+1
             << " with speed " << v[i].speed << endl
             << v[i].points << endl;
    }
   
    int spans = cal_and_show_stats( v );
    cout << "Number of sections = " << v.size()
         <<  ", number of spans = " << spans << endl;
   
                     
    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
   
} //////////////////////////////////////////////////////////////////////////////



int getValidInt( const string& prompt )
{
    for( ; ; ) // an example of a C/C++ forever loop ... until 'return'
    {
        cout << prompt << flush;
        int testInt;
        cin >> testInt;
        if( cin.good() )
        {
            cin.sync();
            return testInt;
        }
        // else ...
        cout << "Invalid input! Integers only please ..." << endl;
    }
}

/* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
bool more( const string& prompt )
{
    cout << prompt << " (y/n) ? " << flush;
    int reply = cin.get();
    cin.sync();
    if( reply == 'n' || reply == 'N' ) return 0;
    // else ...
    return 1;
}

float getDist( Point span[] ) // return sqrt( deltaX*deltaX + deltaY*deltaY );
{
    return sqrt( (span[0].x-span[1].x)*(span[0].x-span[1].x)
               + (span[0].y-span[1].y)*(span[0].y-span[1].y)  );
}

int cal_and_show_stats( const vector< Rec >& v ) // and return count of spans ...
{
    float dd, d = 0, t = 0;
    int spans = 0;
    if( v.size() > 1  ||  (v.size() && v[0].points.size() > 1) )
    {
        Point span[2]; // Note: a 'span' is an array of 2 points ...
        list< Point >::const_iterator it = v[0].points.begin();
       
        span[0].x = it->x; // get x of 1st point in span ...
        span[0].y = it->y; // get y of 1st point in span ...

        for( int i = 0 ; i < (int)v.size() ;  )
        {
            if( ++it != v[i].points.end() )
            {
                span[1].x = it->x;      // get x of 2nd point in span ...
                span[1].y = it->y;      // get y of 2nd point in span ...
                dd  = getDist( span );  // get distance of this span ...
                d += dd;                // add to total distance ...
                t += dd/v[i].speed;     // find/add time taken ... to total
                ++ spans;
            }
            else
            {
                if( ++i == (int)v.size() )  break;

                it = v[i].points.begin();
                span[1].x = it->x;
                span[1].y = it->y;
                dd  = getDist( span );
                d += dd;
                t += dd/v[i].speed;
                ++ spans;
            }

            cout << "Total distance = " << d << " and time = " << t
                 << "and average speed = " << d/t  << endl;

            span[0].x = span[1].x; // update ... 1st point in next span
            span[0].y = span[1].y;
        }
    }
   
    cout << "\nFinals:\n"
         << "Total distance = " << d << " and time = " << t
         << "and average speed = " << d/t  << endl;
           
    return spans;
}

Here is a link to the C version ...
http://developers-heaven.net/forum/index.php/topic,2022.msg2900.html#msg2900

« Last Edit: September 25, 2011, 01:10:54 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #7 on: August 02, 2011, 04:17:28 AM »
A solution to a very interesting student problem to find a record in a list of records ...  using ... 'none' to 'all' ... of multiple search pararmeters ...

Code: [Select]
// list_of_struct.cpp // // 2011-08-02 //

// an interesting student problem to find a record in a list of records ...
// using ... 'none' to 'all' ... of multiple search pararmeters

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <list>
#include <cctype> // re. toupper
using namespace std;

const char* FILE_NAME = "student.dat";
string& toAllUpper( string& s );

struct Student
{
    string  lname;  // last name
    int     id,
            dob;    // yyyymmdd
    char    gender, // 'M' or 'F'
            status; // 'F' or 'S' or 'J' or 'G'
   
    Student( string n="", int i=0, int d=0, char g='X', char s='X' ) :
             lname(toAllUpper(n)), id(i), dob(d), gender(toupper(g)),
             status(toupper(s)) {}
};

int getReply( const string& msg );

ostream& operator<< ( ostream& os, const Student& s );
istream& operator>> ( istream& is, Student& s );
ostream& operator << ( ostream& os,  const list < Student >& s );

bool chInStr( char c, const string& s );
bool hasChNotInStr( const string& t, const string& s );
bool matchList( const Student& m, const Student& t, const string& matchStr );

void showMatching( const list < Student >& s );
void saveToFile( const list <Student>& myList );
void fillFromFile( ifstream& fin, list <Student>& myList );



int main() ///////////////////////// BEGIN MAIN ////////////////////////////////
{
    list < Student > my_list; // create an empty list to hold Students ...
    ifstream fin( FILE_NAME );
    if( fin ) fillFromFile( fin, my_list );
    else
    {
        do
        {
            Student tmp;
            cin >> tmp;
            cin.sync();
            my_list.push_back( tmp );
        }   // make sure cin stream is 'empty' before calling 'more' //
        while( getReply("More (y/n) ? ") != 'N' );
        saveToFile( my_list );
    }
   
    cout << my_list << endl;
   
    do
    {
        showMatching( my_list );
    }
    while( getReply("More (y/n) ? ") != 'N' );
   
    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
   
} //////////////////////////////////// END MAIN /////////////////////////////////


string& toAllUpper( string& s )
{
    for( int i = s.size()-1; i >= 0; --i ) s[i] = toupper(s[i]);
    return s;
}

int getReply( const string& msg )
{
    cout << msg << flush;
    int reply = cin.get();
    cin.sync(); // 'flush' cin stream ...
    return toupper( reply );
}

ostream& operator<< ( ostream& os, const Student& s )
{
    return os << s.lname << " " << s.id << " " << s.dob << " "
              << s.gender << " " << s.status;
}

istream& operator>> ( istream& is, Student& s )
{
    do
    {
    TOP:
        cout << "Enter id number        : " << flush;
        is >> s.id;
        if( is.fail() ) goto ERROR;
        is.sync();

        cout << "Enter dob (yyyymmdd)   : " << flush;
        is >> s.dob;
        if( is.fail() ) goto ERROR;
        is.sync();

        cout << "Enter gender (M/F)     : " << flush;
        is >> s.gender; s.gender = toupper( s.gender );
        is.sync();
        cout << "Enter status (F/S/J/G) : " << flush;
        is >> s.status; s.status = toupper( s.status );
        is.sync();
        cout << "Enter last name        : " << flush;
        getline( is, s.lname ); toAllUpper( s.lname );
        continue; // jump to test at end of while loop right now ...

    ERROR:
        cout << "Enter integers only ...\n";
        is.clear();
        is.sync();
        goto TOP;

    } while( getReply("Is this entry ok (y/n) ? ") != 'Y' );

    return is;
}

ostream& operator << ( ostream& os,  const list < Student >& s )
{
    // need const_iterator since const list ...
    list < Student >::const_iterator i;
    for( i = s.begin(); i != s.end(); ++i ) os << *i << endl;
    return os;
}


bool chInStr( char c, const string& s )
{
    return s.find( c ) != string::npos;
}

bool hasChNotInStr( const string& t, const string& s )
{
    for( int i = t.size()-1; i >= 0; --i )
        if( s.find( t[i] ) == string::npos ) return true;
    // else ...
    return false;
}

bool matchList( const Student& m, const Student& t, const string& matchStr )
{
    if( chInStr( 'N', matchStr )) if( m.lname != t.lname ) return false;
    if( chInStr( 'I', matchStr )) if( m.id != t.id) return false;
    if( chInStr( 'D', matchStr )) if( m.dob!= t.dob ) return false;
    if( chInStr( 'G', matchStr )) if( m.gender != t.gender ) return false;
    if( chInStr( 'S', matchStr )) if( m.status != t.status ) return false;
    // else ...i
    return true;
}

// match string is like this "nidgs" to match on all ...
void showMatching( const list < Student >& s )
{
    string matchOn, valid = "NIDGS";
    for( ;; )
    {
        cout << "Enter 'match criteria string' ... "
             << "i.e. all, some or none of 'nidgs' : "
             << flush;
        getline( cin, matchOn ); toAllUpper( matchOn );

        if( matchOn == "ALL" ) { matchOn = valid; break; }
        else if( matchOn == "NONE" ) { matchOn = ""; break; }
        else if( !hasChNotInStr( matchOn, valid ) ) break;
       
        // else ...
        cout << matchOn << " is not valid here ...\n" << endl;
    }
   

    Student find;
    if( chInStr( 'N', matchOn ))
    {
        cout << "Enter last name to find: " << flush;
        getline( cin, find.lname ); toAllUpper( find.lname );
    }
    if( chInStr( 'I', matchOn ))
    {
        for( ;; )
        {
            cout << "Enter id to find: " << flush;
            cin >> find.id;
            if( cin.good() ) { cin.sync(); break; }
            // else
            cin.clear(); cin.sync();
            cout << "Only integers valid here ..." << endl;
        }
    }
    if( chInStr( 'D', matchOn ))
    {
        for( ;; )
        {
            cout << "Enter dob to find: " << flush;
            cin >> find.dob;
            if( cin.good() ) { cin.sync(); break; }
            // else
            cin.clear(); cin.sync();
            cout << "Only integers valid here ..." << endl;
        }
    }
    if( chInStr( 'G', matchOn ))
    {
        cout << "Enter gender to find: " << flush;
        cin >> find.gender; find.gender = toupper( find.gender );
        cin.sync();
    }
    if( chInStr( 'S', matchOn ))
    {
        cout << "Enter status to find: " << flush;
        cin >> find.status; find.status = toupper( find.status );
        cin.sync();
    }

    bool aMatch = false;
    list < Student >::const_iterator i; // use const_iterator since const list
    for( i = s.begin(); i != s.end(); ++i )
    {
        if( matchList( *i, find, matchOn ))
        {
            aMatch = true;
            cout << *i << endl;
        }
    }
    if( !aMatch ) cout << "No matches ...\n";
    cout << endl;
}

void saveToFile( const list <Student>& myList )
{
    ofstream fout( FILE_NAME );
    list < Student >::const_iterator i;
    for( i = myList.begin(); i != myList.end(); ++i )
        fout << *i << endl;
    fout.close();
}

void fillFromFile( ifstream& fin, list <Student>& myList )
{
    string line;
    while( getline( fin, line ) )
    {
        istringstream iss(line);
        Student tmp;
        iss >> tmp.lname >> tmp.id >> tmp.dob >> tmp.gender >> tmp.status;
        myList.push_back( tmp );
    }
    fin.close();
}


An example of data text file produced/used ...

File name: student.dat
Code: [Select]
JOE 1 19900101 M S
SAM 2 19910101 M F
JIL 3 19900101 F S
SUE 4 19910101 F F
TAM 5 19811203 F G
JUN 6 19890101 F J
TOM 7 19900101 M J

You may like to see a C version of the above at this link:
http://developers-heaven.net/forum/index.php/topic,2022.msg2903.html#msg2903
« Last Edit: September 14, 2011, 01:02:21 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #8 on: September 24, 2011, 08:02:18 PM »
Backing up a little ... and doing some simple data file (data record) processing with C++ ...

The following 3 examples will be using this following data file, saved with the file name: studentData.txt ...  To see some C emulations of these C++ programs, see this next link ...
http://developers-heaven.net/forum/index.php/topic,2022.msg2920.html#msg2920

They demo using C++ getline to get a whole line and then using C++ stringstream to show a simple way to parse a line.

Code: [Select]
Smith, Jane
97 83 97 87 66 76 37 85 97 93
Jones, Bob (Robert)
98 91 96 98 62 65 86 68 65 9
Costello, Judy Ann
98 90 96 99 72 85 55 9 75 99

This 1st example shows how to use a C++ STL list of structs ... with each struct containing a name field and an other field to hold a list of int's ...
The 2nd example demo's using a class, instead of a struct, to handle the student data records of name and marks (includes sort) ...
The 3rd example demo's the slight changes made/needed to edit the 2nd program to use the STL vector container (instead of the STL list container) ...

1.
Code: [Select]
// readShowListOfStructStudent.cpp

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <iomanip> // re. setw
#include <fstream>
#include <sstream> // re. istringstream
#include <string>
#include <list> // but could use vector, if replace all 'list' below to 'vector'

using namespace std;

struct Student
{
    string name; // to hold the name of a Student...
    list< int > marks; // to hold a list of integer marks for a Student object
} ; // <-- don't forget semi-colon here to signify the struct ends here ...

const string MY_FILE = "studentData.txt";


int main()
{
    ifstream fin( MY_FILE.c_str() ); // C++ string gets converted to C string
    list< Student > myStuds;
    string line1, line2;

    // while still more students in file, get next student 2 lines of data ...
    while( getline(fin, line1) && getline(fin, line2) )
    {
        Student tmp; // construct an empty tmp Student
       
        // first get this student's name
        tmp.name = line1;
       
        // then get this student's marks ...
        istringstream iss( line2 ); // construct this iss object ...
        int mark;
        // get marks ... into this student's list of marks ...
        while( iss >> mark)
            tmp.marks.push_back( mark );
       
        myStuds.push_back( tmp ); // append this student data to list myStuds
    }
    fin.close();
   
    // ok ... now show file content's to the screen ...
    cout << "Here is the student data that was in the file "
         << MY_FILE << " ...\n\n";

    list< Student >::const_iterator si; // student iter...
    list< int >::const_iterator mi; // mark iter...
   
    for( si = myStuds.begin(); si != myStuds.end(); ++ si )
    {
        int sum = 0;
        cout << si->name << endl; // show this student name ...
        // now show all marks for this student ...
        for( mi = si->marks.begin(); mi != si->marks.end(); ++ mi )
        {
            cout << setw(4) << *mi; // show this mark to right of 4 char field
            sum += *mi;
        }
        cout << ", Sum = " << sum << ", Average = "
             << double(sum)/si->marks.size() << endl;
    }
   
    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}

2.
Code: [Select]
// readShowListOfclassStudent.cpp

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <iomanip> // re. setw
#include <fstream>
#include <sstream> // re. istringstream
#include <string>
#include <list> // but could use 'vector', if replace all 'list' below to 'vector'

using namespace std;

const string MY_FILE = "studentData.txt";


class Student
{
    friend ostream& operator << ( ostream& os, const Student& s );
    friend istream& operator >> ( istream& is, list< Student >& s );
public:
    Student() {} // default constructor ...
    int marks_size() const { return marks.size(); }
    int sum_marks() const ;
    bool operator < (const Student& s) const { return name < s.name; } //re sort
    void sort_marks() { marks.sort(); } // for_list
    //void sort_marks( sort(marks.begin(), marks.end()); } // for_vector
private:
    string name; // to hold the name of a Student...
    list< int > marks; // to hold a list of integer marks for a Student object
} ; // <-- don't forget semi-colon here to signify the class ends here ...

int Student::sum_marks() const // definition of member function sum_marks()
{
    int sum = 0;
    list< int >::const_iterator it;
    for( it = marks.begin(); it != marks.end(); ++ it )
        sum += *it;
    return sum;
}

// definition of friend functions that have free access to private data ...

// overloaded operator << for Student object is defined here ...
// note: Student record passed in by const reference, so no changes/no copy made
ostream& operator << ( ostream& os, const Student& s )
{
    os << s.name << endl; // output name on first line, then ...
    list< int >::const_iterator it;
    for( it = s.marks.begin(); it != s.marks.end(); ++ it )
        os << setw(4) << *it; // output marks right justified in 4 char field
    return os;
}

// note: list passed in by reference ( so calling list gets updated ) ...
istream& operator >> ( istream& is, list< Student >& s )
{
    string line1, line2;
    // while still more students in stream is, get next student 2 lines of data
    while( getline(is, line1) && getline(is, line2) )
    {
        Student tmp; // construct an empty tmp Student

        // first get this student's name
        tmp.name = line1;

        // then get this student's marks ...
        istringstream iss( line2 ); // construct this iss object ...
        int mark;
        // get marks ... into this student's list of marks ...
        while( iss >> mark)
            tmp.marks.push_back( mark );

        s.push_back( tmp ); // append this student data to Student list s
    }
    return is;
}



int main()
{
    list< Student > myStuds; // create an empty student list ...
    ifstream fin( MY_FILE.c_str() ); // C++ string gets converted to C string

    if( fin )
    {   // get myStuds data from file ... uses overloaded operator >> to fill
        // Student list 'myStuds' ... (see friend function defined above)
        fin >> myStuds;
        fin.close();
       
        // ok ... now show file content's to the screen ...
        cout << "Here is the student data that was in the file "
             << MY_FILE << " ...\n\n";
        list< Student >::iterator it;
        for( it = myStuds.begin(); it != myStuds.end(); ++ it )
        {
            double sum = it->sum_marks();
            cout << *it // show all this student's data ...
                 << ", Sum = " << sum
                 << ", Average = " <<  sum / it->marks_size() << endl;
        }
       
        cout << "\nAfter calling myStuds.sort() ... "
             << "and then sorting narks for each student ...\n\n";
        myStuds.sort(); // for_list
        //sort( myStuds.begin(), myStuds.end() ); // for_vector
        for( it = myStuds.begin(); it != myStuds.end(); ++ it )
        {
            it->sort_marks(); // sort this student's marks ...
            double sum = it->sum_marks();
            cout << *it // show all this student's data ...
                 << ", Sum = " << sum
                 << ", Average = " <<  sum / it->marks_size() << endl;
        }

    }
    else cout << "There was a problem opening file " << MY_FILE << endl;

    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}

3.
Code: [Select]
// readShowVectorOfClassStudent.cpp

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <iomanip> // re. setw
#include <fstream>
#include <sstream> // re. istringstream
#include <string>
#include <vector>
#include <algorithm> // for  sort( v.begin(), v.end() )

using namespace std;

const string MY_FILE = "studentData.txt";


class Student
{
    friend ostream& operator << ( ostream& os, const Student& s );
    friend istream& operator >> ( istream& is, vector< Student >& s );
public:
    Student() {} // default constructor ...
    int marks_size() const { return marks.size(); }
    int sum_marks() const ;
    bool operator < (const Student& s) const { return name < s.name; } //re sort
    //void sort_marks() { marks.sort(); } // for_list
    void sort_marks() { sort(marks.begin(), marks.end()); } // for_vector
private:
    string name; // to hold the name of a Student...
    vector< int > marks; // to hold a vector of integer marks for a Student object
} ; // <-- don't forget semi-colon here to signify the class ends here ...

int Student::sum_marks() const // definition of member function sum_marks()
{
    int sum = 0;
    vector< int >::const_iterator it;
    for( it = marks.begin(); it != marks.end(); ++ it )
        sum += *it;
    return sum;
}

// definition of friend functions that have free access to private data ...

// overloaded operator << for Student object is defined here ...
// note: Student record passed in by const reference, so no changes/no copy made
ostream& operator << ( ostream& os, const Student& s )
{
    os << s.name << endl; // output name on first line, then ...
    vector< int >::const_iterator it;
    for( it = s.marks.begin(); it != s.marks.end(); ++ it )
        os << setw(4) << *it; // output marks right justified in 4 char field
    return os;
}

// note: vector passed in by reference ( so calling vector gets updated ) ...
istream& operator >> ( istream& is, vector< Student >& s )
{
    string line1, line2;
    // while still more students in stream is, get next student 2 lines of data
    while( getline(is, line1) && getline(is, line2) )
    {
        Student tmp; // construct an empty tmp Student

        // first get this student's name
        tmp.name = line1;

        // then get this student's marks ...
        istringstream iss( line2 ); // construct this iss object ...
        int mark;
        // get marks ... into this student's vector of marks ...
        while( iss >> mark)
            tmp.marks.push_back( mark );

        s.push_back( tmp ); // append this student data to Student vector s
    }
    return is;
}



int main()
{
    vector< Student > myStuds; // create an empty student vector ...
    ifstream fin( MY_FILE.c_str() ); // C++ string gets converted to C string

    if( fin )
    {   // get myStuds data from file ... uses overloaded operator >> to fill
        // Student vector 'myStuds' ... (see friend function defined above)
        fin >> myStuds;
        fin.close();
       
        // ok ... now show file content's to the screen ...
        cout << "Here is the student data that was in the file "
             << MY_FILE << " ...\n\n";
        vector< Student >::iterator it;
        for( it = myStuds.begin(); it != myStuds.end(); ++ it )
        {
            double sum = it->sum_marks();
            cout << *it // show all this student's data ...
                 << ", Sum = " << sum
                 << ", Average = " <<  sum / it->marks_size() << endl;
        }
       
        cout << "\nAfter calling sort(myStuds.begin(), myStuds.end()) ...\n"
             << "and then sorting marks for each student ...\n\n";
        //myStuds.sort(); // for_list
        sort( myStuds.begin(), myStuds.end() ); // for_vector
        for( it = myStuds.begin(); it != myStuds.end(); ++ it )
        {
            it->sort_marks();
            double sum = it->sum_marks();
            cout << *it // show all this student's data ...
                 << ", Sum = " << sum
                 << ", Average = " <<  sum / it->marks_size() << endl;
        }

    }
    else cout << "There was a problem opening file " << MY_FILE << endl;

    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}

4.  This 4th ... is in case you need to see/use arrays ... (instead of STL vector or list) ... also demo's using sort algorithim for arrays ...
Code: [Select]
// readShowArrayOfStructStudent.cpp //

// reads file "studentData.txt" into an array of struct Student, shows, sorts...
// also ... cal/show average of highest marks  (i.e. ignore lowest 2 marks)

const char* FNAME = "studentData.txt"; // or, use your own data file and name


const int MAX_STUDS_SIZE = 100; // adjust here, so able to hold expected size
const int MAX_GRADES_SIZE = 20; // adjust here, so able to hold expected size
const int IGNORE_LOW = 2;       // number of lowest marks to ignore ...

#include <iostream>
#include <iomanip> // re. setw ...
#include <fstream>
#include <sstream> // re. stringstream
#include <string>

#include <algorithm> // re. sort

using namespace std;

struct Student
{
    string name;
    int grades[MAX_GRADES_SIZE];
    int grades_size;
};

// returns size of array actually loaded up to max_students ...
int load( Student ary[], int max_students, int MAX_GRADES_SIZE );

// display array of Student data to console screen ...
void cal_and_show( Student ary[], int size, int ignore_low = 0 ); // default 0

// compare_names function to sort an array of Student in ASCENDING order ...
bool compare_names( const Student& a, const Student& b )
{
    return a.name < b.name; // re. sort
}

// compare_marks function to sort an array of integer marks in DESCENDING order
bool compare_marks( const int a, const int b )
{
    return a > b; // re. sort
}



int main()
{
    Student students[MAX_STUDS_SIZE]; // reserve space for array of Student records

    cout << setprecision(2) << fixed; // round and show 2 deciaml place ...
   
    int size = load( students, MAX_STUDS_SIZE, MAX_GRADES_SIZE ); // get file data into array

    cal_and_show( students, size ); // show Student data on console screen ...
   
    cout << "\nAfter sort ...\n\n";
    sort( &students[0], &students[size], compare_names ); // note passed in addresses
    for( int i = 0; i < size; ++ i )
        sort( &students[i].grades[0],
             &students[i].grades[students[i].grades_size], compare_marks );
   
    cal_and_show( students, size, IGNORE_LOW ); // ignore lowest 2 marks ...

    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep window open until 'Enter' key is pressed ...
}


int load( Student ary[], int max_students, int max_grades )
{
    ifstream fin( FNAME );
    string line1, line2;
    int i = 0;
    while( i < max_students && getline(fin, line1) && getline(fin, line2) )
    {
        ary[i].name = line1; // get name into array for this ith index ...
       
        istringstream iss( line2 ); // construct iss object from string line2
        int j = 0, mark;
        while( j < max_grades && iss >> mark ) // get marks for this ith Student
            ary[i].grades[j++] = mark; // note: j is incremented AFTER assignment
           
        ary[i].grades_size = j; // j will be a value in range 0..max_grades
       
        ++i;
    }
    return i;
}

void cal_and_show( Student ary[], int ary_size, int ignore_low )
{
    int overall_sum = 0, tot_num_marks = 0;
   
    for( int i = 0; i < ary_size; ++i )
    {
        int j, sum = 0, top = ary[i].grades_size - ignore_low;
        cout << ary[i].name << '\n';
        for( j = 0; j < top; ++j )
        {
            cout << setw(4) << ary[i].grades[j];
            sum += ary[i].grades[j];
        }
        tot_num_marks += j;
        overall_sum += sum;
        cout << ", average of " << (ignore_low == 0 ? "all " : "top ")
             << j << " marks is " << double(sum)/j << '\n';
    }
    cout << "Overall average of " << (ignore_low == 0 ? "all " : "top ")
         << tot_num_marks << " marks is " << double(overall_sum)/tot_num_marks
         << endl;
}


And now a little different version of data file structure ... each student data is all on one line ... as per this following file ... (containing some data errors) ...
Note: the file is saved with the file name: studentData2.txt

Code: [Select]
Smith, Jane 97 83 97 87 66 76 37 85 97 93
Jones, Bob (Robert) 98 91 96 98 62 65 86 68 65 9
 98 91 96 98 62 65 86 68 65 9

   
Brown, Amy Anna 99 98 76 88 92 75 96 98 95 99
Joseph, James (Jimmy)

1.
Code: [Select]
// readShowListOfStructStudent_1_dataLine.cpp

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <iomanip> // re. setw
#include <fstream>
#include <sstream> // re. istringstream
#include <string>
#include <list> // but could use vector, if replace all 'list' below to 'vector'

using namespace std;

struct Student
{
    string name; // to hold the name of a Student...
    list < int > marks; // to hold a list of integer marks for a Student object
} ; // <-- don't forget semi-colon here to signify the struct ends here ...

const string MY_FILE = "studentData2.txt";


int main()
{
    ifstream fin( MY_FILE.c_str() ); // C++ string gets converted to C string
    list< Student > myStuds;
    string line;

    // while still more students in file, get next student line of data ...
    while( getline(fin, line) )
    {
        bool namePresent = false;
        Student tmpStud; // construct an empty tmp Student
        istringstream issLine( line ); // construct issLine
        string word;
        while( issLine >> word )
        {
            int mark;
            istringstream issWord( word );
            if( !(issWord >> mark) ) // first get this student's name
            {
                namePresent = true;
                tmpStud.name += word + ' ';
            }
            else // then get marks ...
            {
                tmpStud.marks.push_back( mark );
            }
        }
       
        if( namePresent)
            tmpStud.name.erase( tmpStud.name.size()-1 ); // erase added space at end
        myStuds.push_back( tmpStud ); // append this student data to list myStuds
    }
    fin.close();
   
    // ok ... now show file content's to the screen ...
    cout << "Here is the student data that was in the file "
         << MY_FILE << " ...\n\n";

    list< Student >::const_iterator si; // student iter...
    list< int >::const_iterator mi; // mark iter...
   
    for( si = myStuds.begin(); si != myStuds.end(); ++ si )
    {
        int sum = 0;
        cout << "'" << si->name << "'" << endl; // show this student name ...
        // now show all marks for this student ...
        for( mi = si->marks.begin(); mi != si->marks.end(); ++ mi )
        {
            cout << setw(4) << *mi; // show this mark to right of 4 char field
            sum += *mi;
        }
        cout << ", Sum = " << sum << ", Average = "
             << ( si->marks.size() ? double(sum)/si->marks.size() : 0 )
             << endl;
    }
   
    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}

See another way to read this file ... (version 2) ... onthe next page ...
« Last Edit: October 30, 2011, 02:57:35 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #9 on: September 28, 2011, 04:47:33 AM »
 ... continued from above page

2. (version 2 of the above program)
Code: [Select]
// readShowListOfStructStudent_1_dataLine_ver2.cpp

// http://developers-heaven.net/forum/index.php/topic,46.0.html

#include <iostream>
#include <iomanip> // re. setw
#include <fstream>
#include <sstream> // re. istringstream
#include <string>
#include <list> // but could use vector, if replace all 'list' below to 'vector'
#include <cctype> // re. isdigit

using namespace std;

struct Student
{
    string name; // to hold the name of a Student...
    list < int > marks; // to hold a list of integer marks for a Student object
} ; // <-- don't forget semi-colon here to signify the struct ends here ...

const string MY_FILE = "studentData2.txt";
// data file is structured like this ...
/*
Smith, Jane 97 83 97 87 66 76 37 85 97 93
Jones, Bob (Robert) 98 91 96 98 62 65 86 68 65 9
Brown, Amy Anna 99 98 76 88 92 75 96 98 95 99
*/


int main()
{
    ifstream fin( MY_FILE.c_str() ); // C++ string gets converted to C string
    list< Student > myStuds;
    string line;

    // while still more students in file, get next student line of data ...
    while( getline(fin, line) )
    {
        // first get a new string with number part of string ...
        int i = 0, len = line.size();
        while( i < len && !isdigit(line[i]) ) ++i;
        string nums = line.substr( i ); // substr begins at i and goes to end
       
        Student tmpStud; // construct an empty tmp Student
       
        // now get this student's name ...
        if( i > 0 )
        {
            line.erase( --i ); // erase all char's after name ...
            tmpStud.name = line;
        }
       
        // now get this student's marks ...
        int mark;
        istringstream issMarks( nums ); // construct issMarks ...
        while( issMarks >> mark ) tmpStud.marks.push_back( mark );
       
        myStuds.push_back( tmpStud ); // append this student data to list myStuds
    }
    fin.close();
   
    // ok ... now show file content's to the screen ...
    cout << "Here is the student data that was in the file "
         << MY_FILE << " ...\n\n";

    list< Student >::const_iterator si; // student iter...
    list< int >::const_iterator mi; // mark iter...
   
    for( si = myStuds.begin(); si != myStuds.end(); ++ si )
    {
        int sum = 0;
        cout << "'" << si->name << "'" << endl; // show this student name ...
        // now show all marks for this student ...
        for( mi = si->marks.begin(); mi != si->marks.end(); ++ mi )
        {
            cout << setw(4) << *mi; // show this mark to right of 4 char field
            sum += *mi;
        }
        cout << ", Sum = " << sum << ", Average = "
             << ( si->marks.size() ? double(sum)/si->marks.size() : 0 )
             << endl;
    }
   
    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get(); // keep 'Window' open until 'Enter' key is pressed ...
}


For the next series of four programs, you may like to use this data file that I saved with the name: bsort.txt

Code: [Select]
5 5 4 4 4 1 1 1 1 1 2 2 3 7 0 0 0 7 5 2 99 -3 -1 -1
The first two programs use a simple bubble sort of int's ...
The last two demo the use of the STL list sort  ... and then the algorithm sort for the STL vector ...

1.
Code: [Select]
// numFreqInFile_bsort.cpp

#include <iostream>
#include <iomanip> // re. setw
#include <fstream>

using namespace std;

const int MAX_ARY_SIZE = 100;

int readfile( ifstream& fin, int ary[], int max_size );
int sort( int ary[], int ary_size, int unique[], int freq[] );


int main()
{
    cout << "*** Welcome to NUMBER FREQUENCY program ***\n";

    cout << "Enter a file name: " << flush;
    string name;
    cin >> name;
    cin.sync(); // 'flush' cin stream ...
   
    ifstream fin( name.c_str() );
    if( !fin ) // if the stream fails, the program will alert the user
    {
        cerr << "Failed to read from " << name
             << " Press 'Enter' tp exit ... " << flush;
        cin.get();
        return -1;
    }

    int ary[MAX_ARY_SIZE];
    int size = readfile( fin, ary, MAX_ARY_SIZE );
   
    cout << "Unsorted ... \n";
    for( int i = 0; i < size; ++i )
        cout << ary[i] << " ";
    cout << endl << endl;
   
    int unique[MAX_ARY_SIZE], freq[MAX_ARY_SIZE] = {0};
    int unique_size = sort( ary, size, unique, freq );

    cout << "Sorted ... \n";
    for( int i = 0; i < size; ++i )
        cout << ary[i] << " ";
    cout << endl << endl;
   
    for( int i = 0; i < unique_size; ++i )
        cout << "value: " << setw(4) << unique[i]
             << ",    frequency: " << setw(4) << freq[i] << endl;
       
    cout << "\nPress 'Enter' to exit ... " << flush;
    cin.get();
}

/**
This function will read the file, place all the numbers inside of the input array
and will return the size of the ary.
*/
int readfile( ifstream& fin, int ary[], int max_size )
{
    int i = 0;
    while( i < max_size && fin >> ary[i] ) ++ i;
    return i;
}
/**
Simple implementation of a bubble sort with added features..
**/
int sort( int ary[], int size, int unique[], int freq[] )
{
    bool swap;
    int ary_size = size; // get a copy of size ...
    do
    {
        swap = false;
        for( int i = 1; i < size; ++i )
        {
            if( ary[i-1] < ary[i] ) // swap ...
            {
                int tmp = ary[i];
                ary[i] = ary[i-1];
                ary[i-1] = tmp;
                swap = true;
            }
        }
        --size;
    }while( swap );
   
    // after sorting get unique and freq...
    if( !ary_size ) return 0;
   
    int j = 0;
    unique[j] = ary[0];
    freq[j] = 1;
    for( int i = 1; i < ary_size; ++i )
    {
        if( unique[j] == ary[i]  ) ++ freq[j];
        else
        {
            unique[++j] = ary[i];
            ++ freq[j];
        }
    }
    return j+1; // count of unique int's ...
}

2.
Code: [Select]
// numFreqInFile_bsort2.cpp

#include <iostream>
#include <iomanip> // re. setw
#include <fstream>

using namespace std;

const int MAX_ARY_SIZE = 100;

int readfile( ifstream& fin, int ary[], int max_size );
void sort( int ary[], int ary_size );


int main()
{
    cout << "*** Welcome to NUMBER FREQUENCY program ***\n";

    cout << "Enter a file name: " << flush;
    string name;
    cin >> name;
    cin.sync(); // 'flush' cin stream ...
   
    ifstream fin( name.c_str() );
    if( !fin )
    {
        cerr << "Failed to read from " << name
             << " ... Press 'Enter' tp exit ... " << flush;
        cin.get();
        return -1;
    }

    int ary[MAX_ARY_SIZE];
    int size = readfile( fin, ary, MAX_ARY_SIZE );
   
    cout << "Unsorted ... \n";
    for( int i = 0; i < size; ++i )
        cout << ary[i] << " ";
    cout << endl;
   
    sort( ary, size );

    cout << "Sorted ... \n";
    for( int i = 0; i < size; ++i )
        cout << ary[i] << " ";

    cout << "\nShow values and frequency ...\n";
    for( int i = 0; i < size; ++i )
    {
        cout << "value: " << setw(4) << ary[i];
        int j = i+1, freq = 1;
        for( ; j < size; ++j )
        {
            if( ary[i] == ary[j] ) ++freq;
            else break;
        }
        i = j-1; // -1 since incremented in outer loop ...
        cout << ",    frequency: " << setw(4) << freq << endl;
    }
   
    cout << "\nPress 'Enter' to exit ... " << flush;
    cin.get();
}

int readfile( ifstream& fin, int ary[], int max_size )
{
    int i = 0;
    while( i < max_size && fin >> ary[i] ) ++ i;
    return i;
}

void sort( int ary[], int size )
{
    bool swap;
    do
    {
        swap = false;
        for( int i = 1; i < size; ++i )
        {
            if( ary[i-1] < ary[i] ) // swap ...
            {
                int tmp = ary[i];
                ary[i] = ary[i-1];
                ary[i-1] = tmp;
                swap = true;
            }
        }
        --size;
    }while( swap );
}

3.
Code: [Select]
// numFreqInFile_list.cpp

#include <iostream>
#include <iomanip> // re. setw
#include <fstream>
#include <list>

using namespace std;


void readfile( ifstream&, list< int >& );

bool my_compare( int a, int b ) // re. sorted in descending order ...
{
    return b < a;
}


int main()
{
    cout << "*** Welcome to NUMBER FREQUENCY program ***\n";

    cout << "Enter a file name: " << flush;
    string name;
    cin >> name;
    cin.sync(); // 'flush' cin stream ...
   
    ifstream fin( name.c_str() );
    if( !fin )
    {
        cerr << "Failed to read from " << name
             << " ... Press 'Enter' tp exit ... " << flush;
        cin.get();
        return -1;
    }

    list< int > myList;
    readfile( fin, myList );
   
    cout << "Unsorted ... \n";
    list< int >::iterator it, jt;
    for(  it = myList.begin(); it != myList.end(); ++it )
        cout << *it << " ";
    cout << endl;
   
    myList.sort( my_compare );

    cout << "Sorted ... \n";
    for(  it = myList.begin(); it != myList.end(); ++it )
        cout << *it << " ";
       
    cout << "\nShow values and frequency ...\n";
    for(  it = myList.begin(); it != myList.end(); ++it )
    {
        cout << "value: " << setw(4) << *it;
        int freq = 1;
        jt = it;
        ++jt;
        for( ; jt != myList.end(); ++jt )
        {
            if( *it == *jt ) ++freq;
            else break;
        }
        it = --jt; // -1 since incremented in outer loop ...
        cout << ",    frequency: " << setw(4) << freq << endl;
    }
   
    cout << "\nPress 'Enter' to exit ... " << flush;
    cin.get();
}


void readfile( ifstream& fin, list< int >& a)
{
    int i;
    while( fin >> i ) a.push_back( i );
}

4.
Code: [Select]
// numFreqInFile_vector.cpp

#include <iostream>
#include <iomanip> // re. setw
#include <fstream>
#include <vector>
#include <algorithm> // re. vector sort

using namespace std;


void readfile( ifstream& fin, vector< int >& a)
{
    int i;
    while( fin >> i ) a.push_back( i );
}

bool my_compare( int a, int b ) // re. sorting in descending order ...
{
    return b < a;
}


int main()
{
    cout << "*** Welcome to NUMBER FREQUENCY program ***\n";

    cout << "Enter a file name: " << flush;
    string name;
    cin >> name;
    cin.sync(); // 'flush' cin stream ...
   
    ifstream fin( name.c_str() );
    if( !fin )
    {
        cerr << "Failed to read from " << name
             << " ... Press 'Enter' tp exit ... " << flush;
        cin.get();
        return -1;
    }

    vector< int > myList;
    readfile( fin, myList );
   
    cout << "Unsorted ... \n";
    vector< int >::iterator it, jt;
    for(  it = myList.begin(); it != myList.end(); ++it )
        cout << *it << " ";
    cout << endl;
   
    sort( myList.begin(), myList.end(), my_compare );

    cout << "Sorted ... \n";
    for(  it = myList.begin(); it != myList.end(); ++it )
        cout << *it << " ";
       
    cout << "\nShow values and frequency ...\n";
    for(  it = myList.begin(); it != myList.end(); ++it )
    {
        cout << "value: " << setw(4) << *it;
        int freq = 1;
        jt = it;
        ++jt;
        for( ; jt != myList.end(); ++jt )
        {
            if( *it == *jt ) ++freq;
            else break;
        }
        it = --jt; // -1 since incremented in outer loop ...
        cout << ",    frequency: " << setw(4) << freq << endl;
    }
   
    cout << "\nPress 'Enter' to exit ... " << flush;
    cin.get();
}
« Last Edit: October 19, 2011, 04:46:49 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #10 on: October 31, 2011, 05:23:58 AM »
This next series of several programs demo steps and varied approaches a student might take in obtaining a solution to the following file reading problem ...

1. Firstly, how to extract the words from a long string of words ...  i.e. how to read back from file a long string of words that have a space then a comma after each word ... (except the last word has no comma or space after it).

2. and then to get these words into a container, like the STL vector, or if the student is requested to use an array, how one might do this using a growing dynamic array ...

3. and then how one might sort that container of words ...

So ... starting with a simple approach, let's just first extract the words from the file, word by word, and after 'trimming' ... display them ...

1.
Code: [Select]
// getWordsFromLongStringInFile.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip> // re setw

using namespace std;



int main()
{
    ofstream fout( "Proverbs3.txt" );
    if( fout )
    {
        fout << "My ,son ,forget ,not ,my ,law ,but ,let ,thine ,heart ,"
                "keep ,my ,commandments ,For ,length ,of ,days ,and ,long ,life ,"
                "and ,peace ,shall ,they ,add ,to ,thee ,Let ,not ,mercy ,"
                "and ,truth ,forsake ,thee ,bind ,them ,about ,thy ,neck ,write ,"
                "them ,upon ,the ,table ,of ,thine ,heart ,So ,shalt ,thou ,"
                "find ,favour ,and ,good ,understanding ,in ,the ,sight ,of ,God ,"
                "and ,man ,Trust ,in ,the ,LORD ,with ,all ,thine ,heart ,"
                "and ,lean ,not ,unto ,thine ,own ,understanding ,In ,all ,thy ,"
                "ways ,acknowledge ,him ,and ,he ,shall ,direct ,thy ,paths ,Be ,"
                "not ,wise ,in ,thine ,own ,eyes ,fear ,the ,LORD ,and ,"
                "depart ,from ,evil ,It ,shall ,be ,health ,to ,thy ,navel ,"
                "and ,marrow ,to ,thy ,bones ,Honour ,the ,LORD ,with ,thy ,"
                "substance ,and ,with ,the ,firstfruits ,of ,all ,thine ,increase ,So ,"
                "shall ,thy ,barns ,be ,filled ,with ,plenty ,and ,thy ,presses ,"
                "shall ,burst ,out ,with ,new ,wine ,My ,son ,despise ,not ,"
                "the ,chastening ,of ,the ,LORD ,neither ,be ,weary ,of ,his ,"
                "correction ,For ,whom ,the ,LORD ,loveth ,he ,correcteth ,even ,as ,"
                "a ,father ,the ,son ,in ,whom ,he ,delighteth ,Happy ,is ,"
                "the ,man ,that ,findeth ,wisdom ,and ,the ,man ,that ,getteth ,"
                "understanding ,For ,the ,merchandise ,of ,it ,is ,better ,than ,the ,"
                "merchandise ,of ,silver ,and ,the ,gain ,thereof ,than ,fine ,gold ,"
                "She ,is ,more ,precious ,than ,rubies ,and ,all ,the ,things ,"
                "thou ,canst ,desire ,are ,not ,to ,be ,compared ,unto ,her ,"
                "Length ,of ,days ,is ,in ,her ,right ,hand ,and ,in ,"
                "her ,left ,hand ,riches ,and ,honour ,Her ,ways ,are ,ways ,"
                "of ,pleasantness ,and ,all ,her ,paths ,are ,peace ,She ,is ,"
                "a ,tree ,of ,life ,to ,them ,that ,lay ,hold ,upon ,"
                "her ,and ,happy ,is ,every ,one ,that ,retaineth ,her ,The ,"
                "LORD ,by ,wisdom ,hath ,founded ,the ,earth ,by ,understanding ,hath ,"
                "he ,established ,the ,heavens ,By ,his ,knowledge ,the ,depths ,are ,"
                "broken ,up ,and ,the ,clouds ,drop ,down ,the ,dew ,My ,"
                "son ,let ,not ,them ,depart ,from ,thine ,eyes ,keep ,sound ,"
                "wisdom ,and ,discretion ,So ,shall ,they ,be ,life ,unto ,thy ,"
                "soul ,and ,grace ,to ,thy ,neck ,Then ,shalt ,thou ,walk ,"
                "in ,thy ,way ,safely ,and ,thy ,foot ,shall ,not ,stumble ,"
                "When ,thou ,liest ,down ,thou ,shalt ,not ,be ,afraid ,yea ,"
                "thou ,shalt ,lie ,down ,and ,thy ,sleep ,shall ,be ,sweet ,"
                "Be ,not ,afraid ,of ,sudden ,fear ,neither ,of ,the ,desolation ,"
                "of ,the ,wicked ,when ,it ,cometh ,For ,the ,LORD ,shall ,"
                "be ,thy ,confidence ,and ,shall ,keep ,thy ,foot ,from ,being ,"
                "taken ,Withhold ,not ,good ,from ,them ,to ,whom ,it ,is ,"
                "due ,when ,it ,is ,in ,the ,power ,of ,thine ,hand ,"
                "to ,do ,it ,Say ,not ,unto ,thy ,neighbour ,Go ,and ,"
                "come ,again ,and ,to ,morrow ,I ,will ,give ,when ,thou ,"
                "hast ,it ,by ,thee ,Devise ,not ,evil ,against ,thy ,neighbour ,"
                "seeing ,he ,dwelleth ,securely ,by ,thee ,Strive ,not ,with ,a ,"
                "man ,without ,cause ,if ,he ,have ,done ,thee ,no ,harm ,"
                "Envy ,thou ,not ,the ,oppressor ,and ,choose ,none ,of ,his ,"
                "ways ,For ,the ,froward ,is ,abomination ,to ,the ,LORD ,but ,"
                "his ,secret ,is ,with ,the ,righteous ,The ,curse ,of ,the ,"
                "LORD ,is ,in ,the ,house ,of ,the ,wicked ,but ,he ,"
                "blesseth ,the ,habitation ,of ,the ,just ,Surely ,he ,scorneth ,the ,"
                "scorners ,but ,he ,giveth ,grace ,unto ,the ,lowly ,The ,wise ,"
                "shall ,inherit ,glory ,but ,shame ,shall ,be ,the ,promotion ,of ,"
                "fools";
        fout.close();
    }

    ifstream fin( "Proverbs3.txt" );
    if( fin )
    {
        cout << left; // set to left justify in field of width 'x' set by setw(x)
        string word;
        int count = 0;
        while( getline(fin, word, ',') )
        {
            unsigned pos = word.find_first_of( ' ' );
            if( pos != string::npos ) word.erase( pos );
            cout << setw(16)<< "'" + word + "'";
            ++count;

        }
        fin.close();
        cout << "\nThere were " << count << " words in the file ...\n";
    }
   
    cout <<  "\nPress 'Enter' to continue ... " << flush;
    cin.get();
}


2. get words into a STL vector container..
Code: [Select]
// getWordsFromLongStringInFileIntoVector.cpp

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

using namespace std;



int main()
{
    // create file ...
    ofstream fout( "Proverbs3.txt" );
    if( fout )
    {
        fout << "My ,son ,forget ,not ,my ,law ,but ,let ,thine ,heart ,"
                "keep ,my ,commandments ,For ,length ,of ,days ,and ,long ,life ,"
                "and ,peace ,shall ,they ,add ,to ,thee ,Let ,not ,mercy ,"
                "and ,truth ,forsake ,thee ,bind ,them ,about ,thy ,neck ,write ,"
                "them ,upon ,the ,table ,of ,thine ,heart ,So ,shalt ,thou ,"
                "find ,favour ,and ,good ,understanding ,in ,the ,sight ,of ,God ,"
                "and ,man ,Trust ,in ,the ,LORD ,with ,all ,thine ,heart ,"
                "and ,lean ,not ,unto ,thine ,own ,understanding ,In ,all ,thy ,"
                "ways ,acknowledge ,him ,and ,he ,shall ,direct ,thy ,paths ,Be ,"
                "not ,wise ,in ,thine ,own ,eyes ,fear ,the ,LORD ,and ,"
                "depart ,from ,evil ,It ,shall ,be ,health ,to ,thy ,navel ,"
                "and ,marrow ,to ,thy ,bones ,Honour ,the ,LORD ,with ,thy ,"
                "substance ,and ,with ,the ,firstfruits ,of ,all ,thine ,increase ,So ,"
                "shall ,thy ,barns ,be ,filled ,with ,plenty ,and ,thy ,presses ,"
                "shall ,burst ,out ,with ,new ,wine ,My ,son ,despise ,not ,"
                "the ,chastening ,of ,the ,LORD ,neither ,be ,weary ,of ,his ,"
                "correction ,For ,whom ,the ,LORD ,loveth ,he ,correcteth ,even ,as ,"
                "a ,father ,the ,son ,in ,whom ,he ,delighteth ,Happy ,is ,"
                "the ,man ,that ,findeth ,wisdom ,and ,the ,man ,that ,getteth ,"
                "understanding ,For ,the ,merchandise ,of ,it ,is ,better ,than ,the ,"
                "merchandise ,of ,silver ,and ,the ,gain ,thereof ,than ,fine ,gold ,"
                "She ,is ,more ,precious ,than ,rubies ,and ,all ,the ,things ,"
                "thou ,canst ,desire ,are ,not ,to ,be ,compared ,unto ,her ,"
                "Length ,of ,days ,is ,in ,her ,right ,hand ,and ,in ,"
                "her ,left ,hand ,riches ,and ,honour ,Her ,ways ,are ,ways ,"
                "of ,pleasantness ,and ,all ,her ,paths ,are ,peace ,She ,is ,"
                "a ,tree ,of ,life ,to ,them ,that ,lay ,hold ,upon ,"
                "her ,and ,happy ,is ,every ,one ,that ,retaineth ,her ,The ,"
                "LORD ,by ,wisdom ,hath ,founded ,the ,earth ,by ,understanding ,hath ,"
                "he ,established ,the ,heavens ,By ,his ,knowledge ,the ,depths ,are ,"
                "broken ,up ,and ,the ,clouds ,drop ,down ,the ,dew ,My ,"
                "son ,let ,not ,them ,depart ,from ,thine ,eyes ,keep ,sound ,"
                "wisdom ,and ,discretion ,So ,shall ,they ,be ,life ,unto ,thy ,"
                "soul ,and ,grace ,to ,thy ,neck ,Then ,shalt ,thou ,walk ,"
                "in ,thy ,way ,safely ,and ,thy ,foot ,shall ,not ,stumble ,"
                "When ,thou ,liest ,down ,thou ,shalt ,not ,be ,afraid ,yea ,"
                "thou ,shalt ,lie ,down ,and ,thy ,sleep ,shall ,be ,sweet ,"
                "Be ,not ,afraid ,of ,sudden ,fear ,neither ,of ,the ,desolation ,"
                "of ,the ,wicked ,when ,it ,cometh ,For ,the ,LORD ,shall ,"
                "be ,thy ,confidence ,and ,shall ,keep ,thy ,foot ,from ,being ,"
                "taken ,Withhold ,not ,good ,from ,them ,to ,whom ,it ,is ,"
                "due ,when ,it ,is ,in ,the ,power ,of ,thine ,hand ,"
                "to ,do ,it ,Say ,not ,unto ,thy ,neighbour ,Go ,and ,"
                "come ,again ,and ,to ,morrow ,I ,will ,give ,when ,thou ,"
                "hast ,it ,by ,thee ,Devise ,not ,evil ,against ,thy ,neighbour ,"
                "seeing ,he ,dwelleth ,securely ,by ,thee ,Strive ,not ,with ,a ,"
                "man ,without ,cause ,if ,he ,have ,done ,thee ,no ,harm ,"
                "Envy ,thou ,not ,the ,oppressor ,and ,choose ,none ,of ,his ,"
                "ways ,For ,the ,froward ,is ,abomination ,to ,the ,LORD ,but ,"
                "his ,secret ,is ,with ,the ,righteous ,The ,curse ,of ,the ,"
                "LORD ,is ,in ,the ,house ,of ,the ,wicked ,but ,he ,"
                "blesseth ,the ,habitation ,of ,the ,just ,Surely ,he ,scorneth ,the ,"
                "scorners ,but ,he ,giveth ,grace ,unto ,the ,lowly ,The ,wise ,"
                "shall ,inherit ,glory ,but ,shame ,shall ,be ,the ,promotion ,of ,"
                "fools";
        fout.close();
    }

    ifstream fin( "Proverbs3.txt" );
    if( fin )
    {
        string word;
        vector< string > v;
        while( getline(fin, word, ',') )
        {
            unsigned pos = word.find_first_of( ' ' );
            if( pos != string::npos ) word.erase( pos );
            v.push_back( word );

        }
        fin.close();
       
        cout << left; // set to left justify in field width 'x' set by setw(x)
        for( unsigned i = 0; i < v.size(); ++i )
            cout << setw(16) << "'" + v[i] +"'" ;
           
        cout << "\nv.size() = " << v.size()
             << ", v.capacity() = " << v.capacity() << endl;
    }
   
    cout <<  "\nPress 'Enter' to continue ... " << flush;
    cin.get();
}
« Last Edit: November 01, 2011, 02:35:56 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #11 on: October 31, 2011, 05:31:58 AM »
3. get words into vector and sort ...(#include <algorithm> // re. sort) ...

Code: [Select]
// getWordsFromLongStringInFileIntoVectorSorted.

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <iomanip> // re setw
#include <algorithm> // re sort

using namespace std;



int main()
{
    // create file ...
    ofstream fout( "Proverbs3.txt" );
    if( fout )
    {
        fout << "My ,son ,forget ,not ,my ,law ,but ,let ,thine ,heart ,"
                "keep ,my ,commandments ,For ,length ,of ,days ,and ,long ,life ,"
                "and ,peace ,shall ,they ,add ,to ,thee ,Let ,not ,mercy ,"
                "and ,truth ,forsake ,thee ,bind ,them ,about ,thy ,neck ,write ,"
                "them ,upon ,the ,table ,of ,thine ,heart ,So ,shalt ,thou ,"
                "find ,favour ,and ,good ,understanding ,in ,the ,sight ,of ,God ,"
                "and ,man ,Trust ,in ,the ,LORD ,with ,all ,thine ,heart ,"
                "and ,lean ,not ,unto ,thine ,own ,understanding ,In ,all ,thy ,"
                "ways ,acknowledge ,him ,and ,he ,shall ,direct ,thy ,paths ,Be ,"
                "not ,wise ,in ,thine ,own ,eyes ,fear ,the ,LORD ,and ,"
                "depart ,from ,evil ,It ,shall ,be ,health ,to ,thy ,navel ,"
                "and ,marrow ,to ,thy ,bones ,Honour ,the ,LORD ,with ,thy ,"
                "substance ,and ,with ,the ,firstfruits ,of ,all ,thine ,increase ,So ,"
                "shall ,thy ,barns ,be ,filled ,with ,plenty ,and ,thy ,presses ,"
                "shall ,burst ,out ,with ,new ,wine ,My ,son ,despise ,not ,"
                "the ,chastening ,of ,the ,LORD ,neither ,be ,weary ,of ,his ,"
                "correction ,For ,whom ,the ,LORD ,loveth ,he ,correcteth ,even ,as ,"
                "a ,father ,the ,son ,in ,whom ,he ,delighteth ,Happy ,is ,"
                "the ,man ,that ,findeth ,wisdom ,and ,the ,man ,that ,getteth ,"
                "understanding ,For ,the ,merchandise ,of ,it ,is ,better ,than ,the ,"
                "merchandise ,of ,silver ,and ,the ,gain ,thereof ,than ,fine ,gold ,"
                "She ,is ,more ,precious ,than ,rubies ,and ,all ,the ,things ,"
                "thou ,canst ,desire ,are ,not ,to ,be ,compared ,unto ,her ,"
                "Length ,of ,days ,is ,in ,her ,right ,hand ,and ,in ,"
                "her ,left ,hand ,riches ,and ,honour ,Her ,ways ,are ,ways ,"
                "of ,pleasantness ,and ,all ,her ,paths ,are ,peace ,She ,is ,"
                "a ,tree ,of ,life ,to ,them ,that ,lay ,hold ,upon ,"
                "her ,and ,happy ,is ,every ,one ,that ,retaineth ,her ,The ,"
                "LORD ,by ,wisdom ,hath ,founded ,the ,earth ,by ,understanding ,hath ,"
                "he ,established ,the ,heavens ,By ,his ,knowledge ,the ,depths ,are ,"
                "broken ,up ,and ,the ,clouds ,drop ,down ,the ,dew ,My ,"
                "son ,let ,not ,them ,depart ,from ,thine ,eyes ,keep ,sound ,"
                "wisdom ,and ,discretion ,So ,shall ,they ,be ,life ,unto ,thy ,"
                "soul ,and ,grace ,to ,thy ,neck ,Then ,shalt ,thou ,walk ,"
                "in ,thy ,way ,safely ,and ,thy ,foot ,shall ,not ,stumble ,"
                "When ,thou ,liest ,down ,thou ,shalt ,not ,be ,afraid ,yea ,"
                "thou ,shalt ,lie ,down ,and ,thy ,sleep ,shall ,be ,sweet ,"
                "Be ,not ,afraid ,of ,sudden ,fear ,neither ,of ,the ,desolation ,"
                "of ,the ,wicked ,when ,it ,cometh ,For ,the ,LORD ,shall ,"
                "be ,thy ,confidence ,and ,shall ,keep ,thy ,foot ,from ,being ,"
                "taken ,Withhold ,not ,good ,from ,them ,to ,whom ,it ,is ,"
                "due ,when ,it ,is ,in ,the ,power ,of ,thine ,hand ,"
                "to ,do ,it ,Say ,not ,unto ,thy ,neighbour ,Go ,and ,"
                "come ,again ,and ,to ,morrow ,I ,will ,give ,when ,thou ,"
                "hast ,it ,by ,thee ,Devise ,not ,evil ,against ,thy ,neighbour ,"
                "seeing ,he ,dwelleth ,securely ,by ,thee ,Strive ,not ,with ,a ,"
                "man ,without ,cause ,if ,he ,have ,done ,thee ,no ,harm ,"
                "Envy ,thou ,not ,the ,oppressor ,and ,choose ,none ,of ,his ,"
                "ways ,For ,the ,froward ,is ,abomination ,to ,the ,LORD ,but ,"
                "his ,secret ,is ,with ,the ,righteous ,The ,curse ,of ,the ,"
                "LORD ,is ,in ,the ,house ,of ,the ,wicked ,but ,he ,"
                "blesseth ,the ,habitation ,of ,the ,just ,Surely ,he ,scorneth ,the ,"
                "scorners ,but ,he ,giveth ,grace ,unto ,the ,lowly ,The ,wise ,"
                "shall ,inherit ,glory ,but ,shame ,shall ,be ,the ,promotion ,of ,"
                "fools";
        fout.close();
    }

    ifstream fin( "Proverbs3.txt" );
    if( fin )
    {
        string word;
        vector< string > v;
        while( getline(fin, word, ',') )
        {
            unsigned pos = word.find_first_of( ' ' );
            if( pos != string::npos ) word.erase( pos );
            v.push_back( word );
        }

        cout << "Press 'Enter' to see " << v.size()
             << " words from long file string ... " << flush;
        cin.get();

        cout << left;
        vector< string >::const_iterator it;
        for( it = v.begin(); it != v.end(); ++it ) cout << setw(16) << "'"+*it+"'";

        cout << "\n\nPress 'Enter' to see " << v.size() << " words sorted. "
             << "(Note: v.capacity() is now " << v.capacity() << ") ... "<< flush;
        cin.get();

        sort( v.begin(), v.end() );
        for( it = v.begin(); it != v.end(); ++it ) cout << setw(16) << "'"+*it+"'";

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


4. get words into your own coded dynamic array ... but using the sort for arrays supplied by 'including algorithm' ...
Code: [Select]
// getWordsFromLongStringInFileIntoArraySorted.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip> // re setw
#include <algorithm> // re sort

using namespace std;



int main()
{
    // create file ...
    ofstream fout( "Proverbs3.txt" );
    if( fout )
    {
        fout << "My ,son ,forget ,not ,my ,law ,but ,let ,thine ,heart ,"
                "keep ,my ,commandments ,For ,length ,of ,days ,and ,long ,life ,"
                "and ,peace ,shall ,they ,add ,to ,thee ,Let ,not ,mercy ,"
                "and ,truth ,forsake ,thee ,bind ,them ,about ,thy ,neck ,write ,"
                "them ,upon ,the ,table ,of ,thine ,heart ,So ,shalt ,thou ,"
                "find ,favour ,and ,good ,understanding ,in ,the ,sight ,of ,God ,"
                "and ,man ,Trust ,in ,the ,LORD ,with ,all ,thine ,heart ,"
                "and ,lean ,not ,unto ,thine ,own ,understanding ,In ,all ,thy ,"
                "ways ,acknowledge ,him ,and ,he ,shall ,direct ,thy ,paths ,Be ,"
                "not ,wise ,in ,thine ,own ,eyes ,fear ,the ,LORD ,and ,"
                "depart ,from ,evil ,It ,shall ,be ,health ,to ,thy ,navel ,"
                "and ,marrow ,to ,thy ,bones ,Honour ,the ,LORD ,with ,thy ,"
                "substance ,and ,with ,the ,firstfruits ,of ,all ,thine ,increase ,So ,"
                "shall ,thy ,barns ,be ,filled ,with ,plenty ,and ,thy ,presses ,"
                "shall ,burst ,out ,with ,new ,wine ,My ,son ,despise ,not ,"
                "the ,chastening ,of ,the ,LORD ,neither ,be ,weary ,of ,his ,"
                "correction ,For ,whom ,the ,LORD ,loveth ,he ,correcteth ,even ,as ,"
                "a ,father ,the ,son ,in ,whom ,he ,delighteth ,Happy ,is ,"
                "the ,man ,that ,findeth ,wisdom ,and ,the ,man ,that ,getteth ,"
                "understanding ,For ,the ,merchandise ,of ,it ,is ,better ,than ,the ,"
                "merchandise ,of ,silver ,and ,the ,gain ,thereof ,than ,fine ,gold ,"
                "She ,is ,more ,precious ,than ,rubies ,and ,all ,the ,things ,"
                "thou ,canst ,desire ,are ,not ,to ,be ,compared ,unto ,her ,"
                "Length ,of ,days ,is ,in ,her ,right ,hand ,and ,in ,"
                "her ,left ,hand ,riches ,and ,honour ,Her ,ways ,are ,ways ,"
                "of ,pleasantness ,and ,all ,her ,paths ,are ,peace ,She ,is ,"
                "a ,tree ,of ,life ,to ,them ,that ,lay ,hold ,upon ,"
                "her ,and ,happy ,is ,every ,one ,that ,retaineth ,her ,The ,"
                "LORD ,by ,wisdom ,hath ,founded ,the ,earth ,by ,understanding ,hath ,"
                "he ,established ,the ,heavens ,By ,his ,knowledge ,the ,depths ,are ,"
                "broken ,up ,and ,the ,clouds ,drop ,down ,the ,dew ,My ,"
                "son ,let ,not ,them ,depart ,from ,thine ,eyes ,keep ,sound ,"
                "wisdom ,and ,discretion ,So ,shall ,they ,be ,life ,unto ,thy ,"
                "soul ,and ,grace ,to ,thy ,neck ,Then ,shalt ,thou ,walk ,"
                "in ,thy ,way ,safely ,and ,thy ,foot ,shall ,not ,stumble ,"
                "When ,thou ,liest ,down ,thou ,shalt ,not ,be ,afraid ,yea ,"
                "thou ,shalt ,lie ,down ,and ,thy ,sleep ,shall ,be ,sweet ,"
                "Be ,not ,afraid ,of ,sudden ,fear ,neither ,of ,the ,desolation ,"
                "of ,the ,wicked ,when ,it ,cometh ,For ,the ,LORD ,shall ,"
                "be ,thy ,confidence ,and ,shall ,keep ,thy ,foot ,from ,being ,"
                "taken ,Withhold ,not ,good ,from ,them ,to ,whom ,it ,is ,"
                "due ,when ,it ,is ,in ,the ,power ,of ,thine ,hand ,"
                "to ,do ,it ,Say ,not ,unto ,thy ,neighbour ,Go ,and ,"
                "come ,again ,and ,to ,morrow ,I ,will ,give ,when ,thou ,"
                "hast ,it ,by ,thee ,Devise ,not ,evil ,against ,thy ,neighbour ,"
                "seeing ,he ,dwelleth ,securely ,by ,thee ,Strive ,not ,with ,a ,"
                "man ,without ,cause ,if ,he ,have ,done ,thee ,no ,harm ,"
                "Envy ,thou ,not ,the ,oppressor ,and ,choose ,none ,of ,his ,"
                "ways ,For ,the ,froward ,is ,abomination ,to ,the ,LORD ,but ,"
                "his ,secret ,is ,with ,the ,righteous ,The ,curse ,of ,the ,"
                "LORD ,is ,in ,the ,house ,of ,the ,wicked ,but ,he ,"
                "blesseth ,the ,habitation ,of ,the ,just ,Surely ,he ,scorneth ,the ,"
                "scorners ,but ,he ,giveth ,grace ,unto ,the ,lowly ,The ,wise ,"
                "shall ,inherit ,glory ,but ,shame ,shall ,be ,the ,promotion ,of ,"
                "fools";
        fout.close();
    }

    // get ready for array of strings ...
    string* ary = 0;
    string word;
    int size = 0, cap = 0, begin_cap = 1; // but could set much larger here

    ifstream fin( "Proverbs3.txt" );
    if( fin )
    {
        while( getline(fin, word, ',') ) // great next word from file ...
        {
            // firstly ... trim off trailing space(s)
            unsigned pos = word.find_first_of( ' ' );
            if( pos != string::npos ) word.erase( pos );

            // now ... get new memory to hold enlarged block of array elements
            if( size == cap )
            {
                if( cap != 0 ) cap += cap; // double capacity
                else cap = begin_cap; // set beginning capacity on first pass

                string* nary = new string[cap]; // get memory for new enlarged array

                for( int i = 0; i < size; ++i ) nary[i] = ary[i]; // copy old to new
                delete [] ary; // now can free old array memory ...

                ary = nary; // now can update array address to new memory location
            }

            ary[size] = word; // now can put this 'word' into next place in array
            ++size; // increment counter
        }
        fin.close();
   
        cout << "Press 'Enter' to see " << size
             << " words from long file string.\n"
             << "(Note that the capacity now is " << cap << ") ... "<< flush;
        cin.get();

        cout << left; // set to left justify in field of width 'x' set by setw(x)

        for( int i = 0; i < size; ++i ) cout << setw(16) << "'" + ary[i] + "'";

        cout << "\n\nPress 'Enter' to see " << size
             << " words sorted ...\n"
             << "(Note that the capacity now is " << cap << ") ... "<< flush;
        cin.get();

        sort( ary, ary+size ); // pass in start address and address to one past end
        for( int i = 0; i < size; ++i ) cout << setw(16) << "'" + ary[i] + "'";

        delete [] ary; // free all dynamic memory for array of strings
        ary = 0;
        size = cap = 0;
    }
   
    cout <<  "\n\nPress 'Enter' to continue ... " << flush;
    cin.get();
}
« Last Edit: November 01, 2011, 02:38:23 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #12 on: October 31, 2011, 05:41:51 AM »
5. gets words into an array and sort with your own coded bubblesort ...

Code: [Select]
// getWordsFromLongStringInFileIntoArray_bubbleSort.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip> // re setw

using namespace std;

// optimized some ... since bubble sort is so slow anyways ...
void bubblesort( string ary[], int size );


int main()
{
    // create file ...
    ofstream fout( "Proverbs3.txt" );
    if( fout )
    {
        fout << "My ,son ,forget ,not ,my ,law ,but ,let ,thine ,heart ,"
                "keep ,my ,commandments ,For ,length ,of ,days ,and ,long ,life ,"
                "and ,peace ,shall ,they ,add ,to ,thee ,Let ,not ,mercy ,"
                "and ,truth ,forsake ,thee ,bind ,them ,about ,thy ,neck ,write ,"
                "them ,upon ,the ,table ,of ,thine ,heart ,So ,shalt ,thou ,"
                "find ,favour ,and ,good ,understanding ,in ,the ,sight ,of ,God ,"
                "and ,man ,Trust ,in ,the ,LORD ,with ,all ,thine ,heart ,"
                "and ,lean ,not ,unto ,thine ,own ,understanding ,In ,all ,thy ,"
                "ways ,acknowledge ,him ,and ,he ,shall ,direct ,thy ,paths ,Be ,"
                "not ,wise ,in ,thine ,own ,eyes ,fear ,the ,LORD ,and ,"
                "depart ,from ,evil ,It ,shall ,be ,health ,to ,thy ,navel ,"
                "and ,marrow ,to ,thy ,bones ,Honour ,the ,LORD ,with ,thy ,"
                "substance ,and ,with ,the ,firstfruits ,of ,all ,thine ,increase ,So ,"
                "shall ,thy ,barns ,be ,filled ,with ,plenty ,and ,thy ,presses ,"
                "shall ,burst ,out ,with ,new ,wine ,My ,son ,despise ,not ,"
                "the ,chastening ,of ,the ,LORD ,neither ,be ,weary ,of ,his ,"
                "correction ,For ,whom ,the ,LORD ,loveth ,he ,correcteth ,even ,as ,"
                "a ,father ,the ,son ,in ,whom ,he ,delighteth ,Happy ,is ,"
                "the ,man ,that ,findeth ,wisdom ,and ,the ,man ,that ,getteth ,"
                "understanding ,For ,the ,merchandise ,of ,it ,is ,better ,than ,the ,"
                "merchandise ,of ,silver ,and ,the ,gain ,thereof ,than ,fine ,gold ,"
                "She ,is ,more ,precious ,than ,rubies ,and ,all ,the ,things ,"
                "thou ,canst ,desire ,are ,not ,to ,be ,compared ,unto ,her ,"
                "Length ,of ,days ,is ,in ,her ,right ,hand ,and ,in ,"
                "her ,left ,hand ,riches ,and ,honour ,Her ,ways ,are ,ways ,"
                "of ,pleasantness ,and ,all ,her ,paths ,are ,peace ,She ,is ,"
                "a ,tree ,of ,life ,to ,them ,that ,lay ,hold ,upon ,"
                "her ,and ,happy ,is ,every ,one ,that ,retaineth ,her ,The ,"
                "LORD ,by ,wisdom ,hath ,founded ,the ,earth ,by ,understanding ,hath ,"
                "he ,established ,the ,heavens ,By ,his ,knowledge ,the ,depths ,are ,"
                "broken ,up ,and ,the ,clouds ,drop ,down ,the ,dew ,My ,"
                "son ,let ,not ,them ,depart ,from ,thine ,eyes ,keep ,sound ,"
                "wisdom ,and ,discretion ,So ,shall ,they ,be ,life ,unto ,thy ,"
                "soul ,and ,grace ,to ,thy ,neck ,Then ,shalt ,thou ,walk ,"
                "in ,thy ,way ,safely ,and ,thy ,foot ,shall ,not ,stumble ,"
                "When ,thou ,liest ,down ,thou ,shalt ,not ,be ,afraid ,yea ,"
                "thou ,shalt ,lie ,down ,and ,thy ,sleep ,shall ,be ,sweet ,"
                "Be ,not ,afraid ,of ,sudden ,fear ,neither ,of ,the ,desolation ,"
                "of ,the ,wicked ,when ,it ,cometh ,For ,the ,LORD ,shall ,"
                "be ,thy ,confidence ,and ,shall ,keep ,thy ,foot ,from ,being ,"
                "taken ,Withhold ,not ,good ,from ,them ,to ,whom ,it ,is ,"
                "due ,when ,it ,is ,in ,the ,power ,of ,thine ,hand ,"
                "to ,do ,it ,Say ,not ,unto ,thy ,neighbour ,Go ,and ,"
                "come ,again ,and ,to ,morrow ,I ,will ,give ,when ,thou ,"
                "hast ,it ,by ,thee ,Devise ,not ,evil ,against ,thy ,neighbour ,"
                "seeing ,he ,dwelleth ,securely ,by ,thee ,Strive ,not ,with ,a ,"
                "man ,without ,cause ,if ,he ,have ,done ,thee ,no ,harm ,"
                "Envy ,thou ,not ,the ,oppressor ,and ,choose ,none ,of ,his ,"
                "ways ,For ,the ,froward ,is ,abomination ,to ,the ,LORD ,but ,"
                "his ,secret ,is ,with ,the ,righteous ,The ,curse ,of ,the ,"
                "LORD ,is ,in ,the ,house ,of ,the ,wicked ,but ,he ,"
                "blesseth ,the ,habitation ,of ,the ,just ,Surely ,he ,scorneth ,the ,"
                "scorners ,but ,he ,giveth ,grace ,unto ,the ,lowly ,The ,wise ,"
                "shall ,inherit ,glory ,but ,shame ,shall ,be ,the ,promotion ,of ,"
                "fools";
        fout.close();
    }

    // get ready for array of strings ...
    string* ary = 0;
    string word;
    int size = 0, cap = 0, begin_cap = 1; // but could set much larger here
   
    ifstream fin( "Proverbs3.txt" );
    if( fin )
    {
        while( getline(fin, word, ',') ) // great next word from file ...
        {
            // firstly ... trim off trailing space(s)
            unsigned pos = word.find_first_of( ' ' );
            if( pos != string::npos ) word.erase( pos );

            // now ... get new memory to hold enlarged block of array elements
            if( size == cap )
            {
                if( cap != 0 ) cap += cap; // double capacity
                else cap = begin_cap; // set beginning capacity on first pass

                string* nary = new string[cap]; // get memory for new enlarged array

                for( int i = 0; i < size; ++i ) nary[i] = ary[i]; // copy old to new
                delete [] ary; // now can free old array memory ...

                ary = nary; // now can update array address to new memory location
            }

            ary[size] = word; // now can put this 'word' into next place in array
            ++size; // increment counter
        }
        fin.close();

        cout << "Press 'Enter' to see " << size
             << " words from long file string.\n"
             << "(Note that the capacity now is " << cap << ") ... "<< flush;
        cin.get();

        cout << left; // set to left justify in field of width 'x' set by setw(x)

        for( int i = 0; i < size; ++i ) cout << setw(16) << "'" + ary[i] + "'";

        cout << "\n\nPress 'Enter' to see " << size
             << " words sorted ...\n"
             << "(Note that the capacity now is " << cap << ") ... "<< flush;
        cin.get();

        bubblesort( ary, size );
        for( int i = 0; i < size; ++i ) cout << setw(16) << "'" + ary[i] + "'";

        delete [] ary; // free all dynamic memory for array of strings
        ary = 0;
        size = cap = 0;
    }
   
    cout <<  "\n\nPress 'Enter' to continue ... " << flush;
    cin.get();
}

void bubblesort( string ary[], int size )
{
    bool swap;
    string tmp;
    do
    {
        swap = false; // if array is sorted ... then DONE after the next pass
        // only have to check, each loop, up to to size-1 places
        for( int j = 1; j < size; ++j )
        {
            if( ary[j-1] > ary[j] ) // swap values at j-1 with value at j
            {
                tmp = ary[j-1];
                ary[j-1] = ary[j];
                ary[j] = tmp;
                swap = true;
            }
        }
        --size;
    }while( swap );
}


6. gets words into an array of pointers to string and sort with your own coded bubblesort ... (using array of pointers to speed up swaps ... can just swap pointers)
Code: [Select]
// getWordsFromLongStringInFileIntoArray_bubbleSort_pointers.cpp

#include <iostream>
#include <fstream>
#include <string>
#include <iomanip> // re setw

using namespace std;

// optimized (some more by just swapping pointers)...
// since bubble sort is so slow anyways ...
void bubblesort( string* ary[], int size );


int main()
{
    // create file ...
    ofstream fout( "Proverbs3.txt" );
    if( fout )
    {
        fout << "My ,son ,forget ,not ,my ,law ,but ,let ,thine ,heart ,"
                "keep ,my ,commandments ,For ,length ,of ,days ,and ,long ,life ,"
                "and ,peace ,shall ,they ,add ,to ,thee ,Let ,not ,mercy ,"
                "and ,truth ,forsake ,thee ,bind ,them ,about ,thy ,neck ,write ,"
                "them ,upon ,the ,table ,of ,thine ,heart ,So ,shalt ,thou ,"
                "find ,favour ,and ,good ,understanding ,in ,the ,sight ,of ,God ,"
                "and ,man ,Trust ,in ,the ,LORD ,with ,all ,thine ,heart ,"
                "and ,lean ,not ,unto ,thine ,own ,understanding ,In ,all ,thy ,"
                "ways ,acknowledge ,him ,and ,he ,shall ,direct ,thy ,paths ,Be ,"
                "not ,wise ,in ,thine ,own ,eyes ,fear ,the ,LORD ,and ,"
                "depart ,from ,evil ,It ,shall ,be ,health ,to ,thy ,navel ,"
                "and ,marrow ,to ,thy ,bones ,Honour ,the ,LORD ,with ,thy ,"
                "substance ,and ,with ,the ,firstfruits ,of ,all ,thine ,increase ,So ,"
                "shall ,thy ,barns ,be ,filled ,with ,plenty ,and ,thy ,presses ,"
                "shall ,burst ,out ,with ,new ,wine ,My ,son ,despise ,not ,"
                "the ,chastening ,of ,the ,LORD ,neither ,be ,weary ,of ,his ,"
                "correction ,For ,whom ,the ,LORD ,loveth ,he ,correcteth ,even ,as ,"
                "a ,father ,the ,son ,in ,whom ,he ,delighteth ,Happy ,is ,"
                "the ,man ,that ,findeth ,wisdom ,and ,the ,man ,that ,getteth ,"
                "understanding ,For ,the ,merchandise ,of ,it ,is ,better ,than ,the ,"
                "merchandise ,of ,silver ,and ,the ,gain ,thereof ,than ,fine ,gold ,"
                "She ,is ,more ,precious ,than ,rubies ,and ,all ,the ,things ,"
                "thou ,canst ,desire ,are ,not ,to ,be ,compared ,unto ,her ,"
                "Length ,of ,days ,is ,in ,her ,right ,hand ,and ,in ,"
                "her ,left ,hand ,riches ,and ,honour ,Her ,ways ,are ,ways ,"
                "of ,pleasantness ,and ,all ,her ,paths ,are ,peace ,She ,is ,"
                "a ,tree ,of ,life ,to ,them ,that ,lay ,hold ,upon ,"
                "her ,and ,happy ,is ,every ,one ,that ,retaineth ,her ,The ,"
                "LORD ,by ,wisdom ,hath ,founded ,the ,earth ,by ,understanding ,hath ,"
                "he ,established ,the ,heavens ,By ,his ,knowledge ,the ,depths ,are ,"
                "broken ,up ,and ,the ,clouds ,drop ,down ,the ,dew ,My ,"
                "son ,let ,not ,them ,depart ,from ,thine ,eyes ,keep ,sound ,"
                "wisdom ,and ,discretion ,So ,shall ,they ,be ,life ,unto ,thy ,"
                "soul ,and ,grace ,to ,thy ,neck ,Then ,shalt ,thou ,walk ,"
                "in ,thy ,way ,safely ,and ,thy ,foot ,shall ,not ,stumble ,"
                "When ,thou ,liest ,down ,thou ,shalt ,not ,be ,afraid ,yea ,"
                "thou ,shalt ,lie ,down ,and ,thy ,sleep ,shall ,be ,sweet ,"
                "Be ,not ,afraid ,of ,sudden ,fear ,neither ,of ,the ,desolation ,"
                "of ,the ,wicked ,when ,it ,cometh ,For ,the ,LORD ,shall ,"
                "be ,thy ,confidence ,and ,shall ,keep ,thy ,foot ,from ,being ,"
                "taken ,Withhold ,not ,good ,from ,them ,to ,whom ,it ,is ,"
                "due ,when ,it ,is ,in ,the ,power ,of ,thine ,hand ,"
                "to ,do ,it ,Say ,not ,unto ,thy ,neighbour ,Go ,and ,"
                "come ,again ,and ,to ,morrow ,I ,will ,give ,when ,thou ,"
                "hast ,it ,by ,thee ,Devise ,not ,evil ,against ,thy ,neighbour ,"
                "seeing ,he ,dwelleth ,securely ,by ,thee ,Strive ,not ,with ,a ,"
                "man ,without ,cause ,if ,he ,have ,done ,thee ,no ,harm ,"
                "Envy ,thou ,not ,the ,oppressor ,and ,choose ,none ,of ,his ,"
                "ways ,For ,the ,froward ,is ,abomination ,to ,the ,LORD ,but ,"
                "his ,secret ,is ,with ,the ,righteous ,The ,curse ,of ,the ,"
                "LORD ,is ,in ,the ,house ,of ,the ,wicked ,but ,he ,"
                "blesseth ,the ,habitation ,of ,the ,just ,Surely ,he ,scorneth ,the ,"
                "scorners ,but ,he ,giveth ,grace ,unto ,the ,lowly ,The ,wise ,"
                "shall ,inherit ,glory ,but ,shame ,shall ,be ,the ,promotion ,of ,"
                "fools";
        fout.close();
    }

    // get ready for array of pointers to string ...
    string** ary = 0;
    string word;
    int size = 0, cap = 0, begin_cap = 1; // but could set much larger here

    ifstream fin( "Proverbs3.txt" );
    if( fin )
    {
        while( getline(fin, word, ',') ) // great next word from file ...
        {
            // firstly ... trim off trailing space(s)
            unsigned pos = word.find_first_of( ' ' );
            if( pos != string::npos ) word.erase( pos );

            // now ... get new memory to hold enlarged block of array elements
            if( size == cap )
            {
                if( cap != 0 ) cap += cap; // double capacity
                else cap = begin_cap; // set beginning capacity on first pass

                string** nary = new string*[cap]; // get memory for new enlarged array

                for( int i = 0; i < size; ++i ) nary[i] = ary[i]; // copy old to new
                delete [] ary; // now can free old array memory ...

                ary = nary; // now can update array address to new memory location
            }

            string* tmp = new string; // get address and memory for a new string
            *tmp = word; // get (new copy of) 'this word' at that address ...
            ary[size] = tmp; // 'pointer to this new copy' goes next place in ary
            ++size; // increment counter
        }
        fin.close();
   
        cout << "Press 'Enter' to see " << size
             << " words from long file string.\n"
             << "(Note that the capacity now is " << cap << ") ... "<< flush;
        cin.get();

        cout << left; // set to left justify in field of width 'x' set by setw(x)

        for( int i = 0; i < size; ++i ) cout << setw(16) << "'" + *ary[i] + "'";

        cout << "\n\nPress 'Enter' to see " << size
             << " words sorted ...\n"
             << "(Note that the capacity now is " << cap << ") ... "<< flush;
        cin.get();

        bubblesort( ary, size );
        for( int i = 0; i < size; ++i ) cout << setw(16) << "'" + *ary[i] + "'";

        for( int i = size-1; i >= 0; --i ) delete ary[i]; // free each new string
        delete [] ary; // free all dynamic memory for array of pointers to string
        ary = 0;
        size = cap = 0;
    }
   
    cout <<  "\n\nPress 'Enter' to continue ... " << flush;
    cin.get();
}


void bubblesort( string* ary[], int size )
{
    bool swap;
    string* tmp;
    do
    {
        swap = false; // if array is sorted ... then DONE after the next pass
        // only have to check, each loop, up to to size-1 places
        for( int j = 1; j < size; ++j )
        {
            if( *ary[j-1] > *ary[j] ) // then swap pointer at j-1 with pointer at j
            {
                tmp = ary[j-1];
                ary[j-1] = ary[j];
                ary[j] = tmp;
                swap = true;
            }
        }
        --size;
    }while( swap );
}
« Last Edit: November 01, 2011, 02:41:25 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #13 on: November 03, 2011, 04:27:24 AM »
Here is an interesting 'simulation' problem and some steps towards a possible solution ...

1. a first step ...
Code: [Select]
// classParking3.cpp // here ... just a first step towards a solution ... //

/*
    * a possible solution to an interesting little 'PARKING' problem ...

    * as cars arrive they take up next available space from 3 spaces s1,s2,s3
    * cars in space s1 or s2 leave only from front of queue (garage) ...
     (so if there, if needed, you must rotate the departing car to front
      of queue, before 'departing it')
    * cars in s3 (street) leave directly (other cars behind moved up)
    * if car departs from s1 or s2, and a car exists in s3 ...
      front car in s3 is moved up ... (other cars in s3 'moved up' then also)

    * notify when car arrives and in which space it 'arrived'
    * notify when car departs and from which space it 'departed' ... AND ALSO
      the 'total moves' ...

    * when a car first moves into its first 'garage' that move is NOT counted
    * when a car departs from 'where-ever' that departing move IS counted

    * to keep this simple to start, use only 5 parking spots in each of s1,s2,s3
*/


#include <iostream>
#include <string>
#include <list>

using namespace std;

struct Car
{
    string plate;
    int moves;
   
    Car( string p = "", int m = 0 ) : plate(p), moves(m) {}

    bool operator == ( Car& c )
    {
        return plate == c.plate;
    }

    bool operator != ( Car& c )
    {
        return plate != c.plate;
    }

} ;

struct Garage
{
    list< Car > park_q;
    string park_name;

    bool is_here( Car& c )
    {
        list< Car>::iterator it;
        for( it = park_q.begin(); it != park_q.end(); ++it )
        {
            if( it->plate == c.plate ) return true;
        }
        return false;
    }
   
    bool arrive( Car c )
    {
        if( park_q.size() < 5 )
        {
            park_q.push_front( c );
            cout << c.plate << " arrived in " << park_name << endl;
            return true;
        }
        else return false;
    }
   
    bool depart( Car c )
    {
        if( park_q.size() > 0 && is_here( c ) )
        {
            Car end_car;
            list< Car >::iterator it = park_q.end(), i;
            it = park_q.end();
            if( (end_car = *(--it)) == c )
            {
                // all move ++ when end moves out ...
                for(  i= park_q.begin(); i != park_q.end(); ++i ) ++i->moves;
            }
            else
            {
                while( end_car != c  )
                {
                    for( i = park_q.begin(); i != park_q.end(); ++i ) ++i->moves;
                    /*
                    cout << "End car = " << end_car.plate
                         << " moves = " << end_car.moves << endl;
                    */
                    end_car.moves = (--i)->moves;
                    park_q.push_front( end_car );
                    park_q.pop_back();
                    it = park_q.end();
                    end_car = *(--it);
                }
               
                // all move ++ when end moves out ...
                for( i = park_q.begin(); i != park_q.end(); ++i ) ++i->moves;

                it = park_q.end();
                --it;
            }
            int moves = it->moves;
            park_q.pop_back();

            cout << c.plate << " departed from " << park_name
                 << " after " << moves << " move(s)." << endl;
            return true;
        }
        return false;
    }
};



int main()
{
    Garage g1, g2, g3;
    g1.park_name = "Garage1";
    g2.park_name = "Garage2";
    g3.park_name = "STREET";
   
    Car c1( "car_1" );
    Car c2( "car_2" );
    Car c3( "car_3" );
    Car c4( "car_4" );
    Car c5( "car_5" );
    Car c6( "car_6" );
    Car c7( "car_7" );
    Car c8( "car_8" );
   
    g1.arrive( c1 );
    g1.arrive( c2 );
    g1.arrive( c3 );
    g1.arrive( c4 );
    g1.arrive( c5 );
   
    g1.depart( c1 );
    g1.depart( c2 );
    g1.depart( c3 );
   
    g1.arrive( c6 );
    g1.arrive( c7 );
    g1.arrive( c8 );
   
    g1.depart( c8 );
    g1.depart( c7 );
    g1.depart( c6 );
    g1.depart( c5 );
    g1.depart( c4 );
   
    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get();
}


2. Still using a 'list' container ... note to go to the next 'deque' and 3rd version ... just search/replace 'list' here with 'deque' ...
Code: [Select]
// classParking3_step2.cpp // // a 2nd step towards a solution ... //

/*
    * a possible solution to an interesting little 'PARKING' problem ...

    * as cars arrive they take up next available space from 3 spaces s1,s2,s3
    * cars in space s1 or s2 leave only from front of queue (garage) ...
     (so if there, if needed, you must rotate the departing car to front
      of queue, before 'departing it')
    * cars in s3 (street) leave directly (other cars behind moved up)
    * if car departs from s1 or s2, and a car exists in s3 ...
      front car in s3 is moved up ... (other cars in s3 'moved up' then also)

    * notify when car arrives and in which space it 'arrived'
    * notify when car departs and from which space it 'departed' ... AND ALSO
      the 'total moves' ...

    * when a car first moves into its first 'garage' that move is NOT counted
    * when a car departs from 'where-ever' that departing move IS counted

    * to keep this simple to start, use only 5 parking spots in each of s1,s2,s3
*/


#include <iostream>
#include <string>
#include <list>

using namespace std;

class Car
{
public:
    string plate;
    int moves;
   
    Car( string p = "", int m = 0 ) : plate(p), moves(m) {}

    bool operator == ( const Car& c ) const
    {
        return plate == c.plate;
    }

    bool operator != ( const Car& c ) const
    {
        return plate != c.plate;
    }
} ;

class Garage
{
public:
    list< Car > park_q;
    string park_name;

    bool is_here( const Car& c )
    {
        list< Car>::iterator it;
        for( it = park_q.begin(); it != park_q.end(); ++it )
        {
            if( it->plate == c.plate ) return true;
        }
        return false;
    }
   
    bool arrive( const Car& c )
    {
        if( park_q.size() < 5 )
        {
            park_q.push_front( c );
            cout << c.plate << " arrived in " << park_name << endl;
            return true;
        }
        else return false;
    }
   
    bool depart( const Car& c )
    {
        if( park_q.size() > 0 && is_here( c ) )
        {
            Car end_car;
            list< Car >::iterator it = park_q.end(), i;
            if( (end_car = *(--it)) == c )
            {
                // all move ++ when end moves out ...
                for(  i= park_q.begin(); i != park_q.end(); ++i ) ++i->moves;
            }
            else
            {
                while( end_car != c  )
                {
                    for( i = park_q.begin(); i != park_q.end(); ++i ) ++i->moves;
                    /*
                    cout << "End car = " << end_car.plate
                         << " moves = " << end_car.moves << endl;
                    */
                    end_car.moves = (--i)->moves;
                    park_q.push_front( end_car );
                    park_q.pop_back();
                    it = park_q.end();
                    end_car = *(--it);
                }
               
                // all move ++ when end moves out ...
                for( i = park_q.begin(); i != park_q.end(); ++i ) ++i->moves;

                it = park_q.end();
                --it;
            }
           
            cout << it->plate << " departed from " << park_name
                 << " after " << (it->moves) << " move"
                 << ((it->moves == 1) ? "." : "s.") << endl;

            park_q.pop_back();
            return true;
        }
        return false;
    }
   
    bool depart_street( const Car& c )
    {
        if( park_q.size() > 0 && is_here( c ) )
        {
            list< Car >::iterator it = park_q.begin();
            int pos = 0;
            while( it->plate != c.plate ) ++it, ++pos;

            cout << c.plate << " departed from " << park_name
                 << " after " << (it->moves + 1) << " move"
                 << ((it->moves + 1 == 1) ? "." : "s.") << endl;
                 
            park_q.erase( it );
           
            // now all, upto pos, ++moves  ...
            for( it = park_q.begin(); pos > 0 ; ++it ) ++it->moves, --pos;

            return true;
        }
        else return false;
    }
} ;

void car_depart( Garage g[], const Car& c )
{
  if( !g[1].depart( c ) )
    {
        if( !g[2].depart( c ) )
        {
            if( !g[3].depart_street( c ) )
                cout << c.plate << " is NOT HERE!" << endl;
        }
        else if( g[3].park_q.size() )
        {
            list< Car >::iterator i;
            // all cars move ...
            for( i = g[3].park_q.begin(); i != g[3].park_q.end(); ++i ) ++i->moves;
            g[2].park_q.push_front( *(--i) );
            g[3].park_q.pop_back();
        }
    }
    else if( g[3].park_q.size() )
    {
        list< Car >::iterator i;
        // all cars move ...
        for( i = g[3].park_q.begin(); i != g[3].park_q.end(); ++i ) ++i->moves;
        g[1].park_q.push_front( *(--i) );
        g[3].park_q.pop_back();
    }
}

bool car_arrive( Garage g[], const Car& c )
{
    if( !g[1].arrive( c ) )
    {
        if( !g[2].arrive( c ) )
        {
            if( !g[3].arrive( c ) )
            {
                cout << "For " << c.plate
                     << ", there is NO MORE PARKING SPACE!" << endl;
                return false;
            }
        }
    }
    return true;
}

void pause( string msg = "\nPress 'Enter' to continue ... " )
{
    cout << msg << flush;
    string line;
    getline( cin, line );
}


int main()
{
    Garage g[4]; // [0] not used ...
    g[1].park_name = "Garage1";
    g[2].park_name = "Garage2";
    g[3].park_name = "STREET";
   
    cout << "get cars with plates car_01..car_19 ...\n";
    Car c[20]; // [0] not used ...
    string plate_id = "car_0";
    string plate_id1 = "car_1";
    for( int i = 1; i <= 19; ++i )
    {
        if( i <= 9 ) c[i].plate = plate_id + char('0' + i);
        else c[i].plate = plate_id1 + char('0' + i-10);
    }
    pause();

    cout << "\nfill up parking to overflowing ...\n";
    for( int i = 1; i <= 17; ++i )
    {
        if( !car_arrive(g, c[i]) ) break;
    }
    pause();

    cout << "\nexit car_01, car_06  ... make room for 2 from street ...\n";
    car_depart( g, c[1] );
    car_depart( g, c[6] );
    pause();
   
    cout << "\nget car_18, car_19 ...\n";
    car_arrive( g, c[18] );
    car_arrive( g, c[19] );
    pause();

    cout << "\nexit car_02, car_07 ... make room for 2 from street ...\n";
    car_depart( g, c[2] );
    car_depart( g, c[7] );
    pause();

   
    cout << "\ntesting ... exit car_19 to car_01 ...\n";
    for( int i = 19; i >= 1; --i )
    {
        car_depart( g, c[i] );
    }

    pause( "\nPress 'Enter' to continue/exit ... " );
}


3. A possible 'deque' solution to this interesting 'PARKING' problem ...
Code: [Select]
// classParking3_deque.cpp // // a possible? solution using deque //

/*
    * a possible? solution to an interesting little 'PARKING' problem ...

    * as cars arrive they take up next available space from 3 spaces s1,s2,s3
    * cars in space s1 or s2 leave only from front of queue (garage) ...
     (so if there, if needed, you must rotate the departing car to front
      of queue, before 'departing it')
    * cars in s3 (street) leave directly (other cars behind moved up)
    * if car departs from s1 or s2, and a car exists in s3 ...
      front car in s3 is moved up ... (other cars in s3 'moved up' then also)
   
    * notify when car arrives and in which space it 'arrived'
    * notify when car departs and from which space it 'departed' ... AND ALSO
      the 'total moves' ...
     
    * when a car first moves into its first 'garage' that move is NOT counted
    * when a car departs from 'where-ever' that departing move IS counted
   
    * to keep this simple to start, use only 5 parking spots in each of s1,s2,s3
*/

#include <iostream>
#include <string>
#include <deque>

using namespace std;

const unsigned MAX_SPOTS = 5;

class Car
{
public:
    string plate;
    int moves;
   
    Car( string p = "", int m = 0 ) : plate(p), moves(m) {}

    bool operator == ( const Car& c ) const
    {
        return plate == c.plate;
    }

    bool operator != ( const Car& c ) const
    {
        return plate != c.plate;
    }
} ;

class Garage
{
public:
    deque< Car > park_q;
    string park_name;

    bool is_here( const Car& c )
    {
        deque< Car>::iterator it;
        for( it = park_q.begin(); it != park_q.end(); ++it )
        {
            if( it->plate == c.plate ) return true;
        }
        return false;
    }
   
    bool arrive( const Car& c )
    {
        if( park_q.size() < MAX_SPOTS )
        {
            park_q.push_front( c );
            cout << c.plate << " arrived in " << park_name << endl;
            return true;
        }
        else return false;
    }
   
    bool depart( const Car& c )
    {
        if( park_q.size() > 0 && is_here( c ) )
        {
            Car end_car;
            deque< Car >::iterator it = park_q.end(), i;
            if( (end_car = *(--it)) == c )
            {
                // all move ++ when end moves out ...
                for(  i= park_q.begin(); i != park_q.end(); ++i ) ++i->moves;
            }
            else
            {
                while( end_car != c  )
                {
                    for( i = park_q.begin(); i != park_q.end(); ++i ) ++i->moves;
                    /*
                    cout << "End car = " << end_car.plate
                         << " moves = " << end_car.moves << endl;
                    */
                    end_car.moves = (--i)->moves;
                    park_q.push_front( end_car );
                    park_q.pop_back();
                    it = park_q.end();
                    end_car = *(--it);
                }
               
                // all move ++ when end moves out ...
                for( i = park_q.begin(); i != park_q.end(); ++i ) ++i->moves;

                it = park_q.end();
                --it;
            }
           
            cout << it->plate << " departed from " << park_name
                 << " after " << (it->moves) << " move"
                 << ((it->moves == 1) ? "." : "s.") << endl;

            park_q.pop_back();
            return true;
        }
        return false;
    }
   
    bool depart_street( const Car& c )
    {
        if( park_q.size() > 0 && is_here( c ) )
        {
            deque< Car >::iterator it = park_q.begin();
            int pos = 0;
            while( it->plate != c.plate ) ++it, ++pos;

            cout << c.plate << " departed from " << park_name
                 << " after " << (it->moves + 1) << " move"
                 << ((it->moves + 1 == 1) ? "." : "s.") << endl;
                 
            park_q.erase( it );
           
            // now all, upto pos, ++moves  ...
            for( it = park_q.begin(); pos > 0 ; ++it ) ++it->moves, --pos;

            return true;
        }
        else return false;
    }
} ;


// these next 'non-class-member-functions' are used in main ...

void car_depart( Garage g[], const Car& c )
{
  if( !g[1].depart( c ) )
    {
        if( !g[2].depart( c ) )
        {
            if( !g[3].depart_street( c ) )
                cout << c.plate << " is NOT HERE!" << endl;
        }
        else if( g[3].park_q.size() ) // move car into g[2] from street g[3]
        {
            deque< Car >::iterator i;
            // all cars move ...
            for( i = g[3].park_q.begin(); i != g[3].park_q.end(); ++i ) ++i->moves;
            g[2].park_q.push_front( *(--i) );
            g[3].park_q.pop_back();
        }
    }
    else if( g[3].park_q.size() ) // move car into g[1] from street g[3]
    {
        deque< Car >::iterator i;
        // all cars move ...
        for( i = g[3].park_q.begin(); i != g[3].park_q.end(); ++i ) ++i->moves;
        g[1].park_q.push_front( *(--i) );
        g[3].park_q.pop_back();
    }
}

bool car_arrive( Garage g[], const Car& c )
{
    if( !g[1].arrive( c ) )
    {
        if( !g[2].arrive( c ) )
        {
            if( !g[3].arrive( c ) )
            {
                cout << "For " << c.plate
                     << ", there is NO MORE PARKING SPACE!" << endl;
                return false;
            }
        }
    }
    return true;
}

void pause( string msg = "\nPress 'Enter' to continue ... " )
{
    cout << msg << flush;
    string line;
    getline( cin, line );
}


int main()
{
    cout << "create parking spots 'Garage1', 'Garage2', 'STREET '...\n";
    Garage g[4]; // [0] not used ...
    g[1].park_name = "Garage1";
    g[2].park_name = "Garage2";
    g[3].park_name = "STREET";
   
    cout << "create cars with plates car_01..car_19 ...\n";
    Car c[20]; // [0] not used ...
    string plate_id = "car_0";
    string plate_id1 = "car_1";
    for( int i = 1; i <= 19; ++i )
    {
        if( i <= 9 ) c[i].plate = plate_id + char('0' + i);
        else c[i].plate = plate_id1 + char('0' + i-10);
    }
    pause();

    cout << "\nfill up parking to overflowing ...\n";
    for( int i = 1; i <= 17; ++i )
    {
        if( !car_arrive(g, c[i]) ) break;
    }
    pause();

    cout << "\ndepart car_01, car_06  ... make room for 2 from street ...\n";
    car_depart( g, c[1] );
    car_depart( g, c[6] );
    pause();
   
    cout << "\narrive car_18, car_19 ...\n";
    car_arrive( g, c[18] );
    car_arrive( g, c[19] );
    pause();

    cout << "\ndepart car_02, car_07 ... make room for 2 from street ...\n";
    car_depart( g, c[2] );
    car_depart( g, c[7] );
    pause();

   
    cout << "\ntesting ... exit car_19 to car_01 ...\n";
    for( int i = 19; i >= 1; --i )
    {
        car_depart( g, c[i] );
    }

    pause( "\nPress 'Enter' to continue/exit ... " );
}
« Last Edit: November 09, 2011, 05:29:52 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 644
    • View Profile
Re: Six Fast Steps to Programming in C++
« Reply #14 on: November 14, 2011, 10:22:17 PM »
Now here is an interesting little student type problem ... (that illustrates using/and coding your own list and a list insertion sort) ... in C++

1. first as a struct ...

Code: [Select]
// linkedListUnoDuo_struct.cpp //

/*
    Create two linked lists each having any number of elements ...
    uno is the (pointer to the head of the) FIRST list
    duo is the ... SECOND list

    The data in the lists will consist of a LastName and GPA (e.g. Smith 3.99)
    The lists are to be sorted BY GPA as you create them (insertSortedByGPA)
    Print out each sorted list after you create them ...
   
    Then delete all nodes from 'uno' whose GPA is above 3.0 ...
    and delete all nodes from 'duo' whose GPA is under 2.5
    Print out both of these modified lists

    Merge the REMAINING lists from both lists into one list 'uno'
    THIS 'uno' list should be created sorted by NAME (not by GPA, as above)
    Finally ... print out this 'uno' list
           
*/

#include <iostream>
#include <fstream> // re. ostream object
#include <iomanip> // re. setw, setprecision, fixed,
#include <sstream> // re. istringstream object
#include <string>

using namespace std;

struct Node
{
    string name;
    double gpa;
    Node *next;
} ;

// demo overloaded << to print out a whole list beginning at Node n ...
ostream& operator << ( ostream& os, Node* n )
{
    for( ; n!= NULL; n = n->next )
        os << setw(16) << n->name << setw(6) << n->gpa << endl;
    return os;
};

bool getdata( string& name, double &gpa ); // returns values by reference ...
void show( Node* cur ); // alternate print out whole list beginning at Node cur
void insertSortedByGPA( Node*& pHead, Node* pNewNode ); // pHead updated by ref.
void insertSortedByName( Node*& pHead, Node* pNewNode );
void isortByName( Node*& pHead );
void clear( Node*& pHead ); // free new memory inclusive at pHead on, pHead set to NULL by ref.
void chopBack( Node*& pHead, double gpa ); // list passed in ... in sorted order
void chopFront( Node*& pHead, double gpa );// list passed in ... in sorted order



int main() // .................................................... // begin main
{
    cout << "Getting uno data in sorted order (Enter an empty name to exit loop) ...\n";
    Node* uno = NULL;
    /*
    const int MAX = 10;
    for( int i = 0; i < MAX; ++i )
    {
        Node* cur = new Node;
        cur->next = NULL;
getdata( cur->name, cur->gpa );
insertSortedByGPA( uno, cur );
    }*/
    for( ; ; )
    {
        Node* cur = new Node;
        cur->next = NULL;
if( !getdata(cur->name, cur->gpa) )
        {
            cout << "Loop aborted ...\n";
            delete cur;
            break; // leave loop now ...
        }
        // else ...
        insertSortedByGPA( uno, cur );
    }
   
    cout << setprecision(2) << fixed; // show 2 decimal places ...
   
    cout << "\n   uno ...\n"; // show data ...
    show( uno );
   
       
    cout << "\nGetting duo data in sorted order (Enter an empty name to exit loop) ...\n";
    Node* duo = NULL;
    for( ; ; )
    {
        Node* cur = new Node;
        cur->next = NULL;
if( !getdata(cur->name, cur->gpa) )
        {
            cout << "Loop aborted ...\n";
            delete cur;
            break; // leave loop now ...
}
        // else ...
        insertSortedByGPA( duo, cur );
    }
   
    cout << "\n   duo ...\n";
    cout << duo;

   
    chopBack( uno, 3.0 );
    cout << "\nUNO List with all GPA's above 3.0 deleted ..." << endl;
cout << setw(16) << "Student Name" << setw(6) << "GPA" << endl;
    show( uno );

    chopFront( duo, 2.5 );
    cout << "\nDUO List with all GPA's under 2.5 deleted ..." << endl;
cout << setw(16) << "Student Name" << setw(6) << "GPA" << endl;
    cout << duo;

/*
    // an alternate way to handle the 'last step' ...
   
    // merge lists ... by appending list 'duo' to the end of list 'uno' ...
    // first find last node in uno ...
    Node* prior = uno;
    Node* cur = uno;
    while( cur != NULL )
    {
        prior = cur;
        cur = cur->next;
    }
    if( prior != NULL ) prior->next = duo;
    else uno = duo; // since 'uno' was empty ...

    cout << "\nShowing merged lists (unsorted) ..." << endl;
cout << setw(16) << "Student Name" << setw(6) << "GPA" << endl;
    cout << uno;
   
    cout << "\nShowing merged lists (sorted) ..." << endl;
cout << setw(16) << "Student Name" << setw(6) << "GPA" << endl;
isortByName( uno );
    cout << uno;
*/

    Node* newHead = NULL; // merging two lists, sorted by name ...
    while( uno != NULL )
    {
        Node* tmp = uno->next; // keep copy of 'next' address ...
        insertSortedByName( newHead, uno );
        uno = tmp; // move up to next node in 'uno' ...
    }
    while( duo != NULL ) // now ... merge in 'duo' in name sorted order ...
    {
        Node* tmp = duo->next;
        insertSortedByName( newHead, duo );
        duo = tmp;
    }
   
    uno = newHead; // update ADDRESS of new head for uno ...
   
    cout << "\nShowing merged list sorted by name ... \n";
    cout << setw(16) << "Student Name" << setw(6) << "GPA" << endl;
    cout << uno;
   
    clear( uno ); // to keep good habit of preventing 'memory leaks' ...
       
    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get();
   
} // ............................................................... // end main



bool getdata( string& name, double &gpa ) // name and gpa passed back by ref.
{
    cout << "Enter students name: " << flush;
    getline( cin, name );
    if( name == "" ) return false;
   
    cout << "Enter GPA: " << flush;
    string tmp;
    getline( cin, tmp );
    istringstream iss( tmp ); // construct iss from string tmp ...
    iss >> gpa; // get double value into gpa ...
    return true;
}

void show( Node* cur )
{
    for( ; cur != NULL ; cur = cur->next )
        cout << setw(16) << cur->name << setw(6) << cur->gpa << endl;
}

void insertSortedByGPA( Node*& pHead, Node* pNewNode ) // pHead updated by ref.
{
    // First ... handle most likely cases where new node is NOT first element
    if( pHead != NULL && pNewNode->gpa >= pHead->gpa )
    {
        // If here ... search the list for the right location
        Node* q = pHead; // Get a working copy of pHead in q
        // Start comparing with element AFTER 'q' ... i.e. the 'next in'
        while( q->next != NULL && q->next->gpa <= pNewNode->gpa )
            q = q->next; // Traverse the list ...

        // Ok, insert after 'q' by 're-nexting' the pointers ...
        // ( Includes inserting at end position ... where q->next is NULL )

        // for A->B to become A->N->B ...
        pNewNode->next = q->next; // first insert/link ... N->B
        q->next = pNewNode; // and now link ... A->N
    }
    else // becomes the first element ...
    {
        pNewNode->next = pHead; // old pHead becomes 2nd in list
        pHead = pNewNode; // and this new node becomes the head of the list
    }
}

void insertSortedByName( Node*& pHead, Node* pNewNode ) // pHead updated by ref.
{
    // First ... handle most likely cases where new node is NOT first element
    if( pHead != NULL && pNewNode->name >= pHead->name )
    {
        // If here ... search the list for the right location
        Node* q = pHead; // Get a working copy of pHead in q
        // Start comparing with element AFTER 'q' ... i.e. the 'next in'
        while( q->next != NULL && q->next->name <= pNewNode->name )
            q = q->next; // Traverse the list ...

        // Ok, insert after 'q' by 're-nexting' the pointers ...
        // ( Includes inserting at end position ... where q->next is NULL )

        // for A->B to become A->N->B ...
        pNewNode->next = q->next; // first insert/link ... N->B
        q->next = pNewNode; // and now link ... A->N
    }
    else // becomes the first element ...
    {
        pNewNode->next = pHead; // old pHead becomes 2nd in list
        pHead = pNewNode; // and this new node becomes the head of the list
    }
}

void isortByName( Node*& pHead ) // pHead updated by reference ...
{
    Node* newHead = NULL, *cur = pHead, *tmp;
    while( cur != NULL )
    {
        tmp = cur->next; // get a copy of the next address ...
        insertSortedByName( newHead, cur );
        cur = tmp; // update cur to the next address
    }
    pHead = newHead; // update pHead with head of new insert-sorted list...
}

void clear( Node*& pHead ) // pHead updated by reference ...
{
    while( pHead != NULL )
    {
        Node* tmp = pHead;
        pHead = pHead->next;
        delete tmp;
    }
}

void chopBack( Node*& pHead, double gpa ) // pHead updated by reference ...
{
    Node *cur = pHead, *prior = pHead;
    while( cur != NULL && cur->gpa <= gpa )
    {
        prior = cur;
        cur = cur->next;
    }
    // cout << "\n   prior->gpa = " << prior->gpa << endl; // for debugging ...
    if( cur != pHead )
    {
        clear( prior->next );
    }
    else clear( pHead );

}
void chopFront( Node*& pHead, double gpa ) // pHead updated by reference ...
{
    Node *cur = pHead, *prior = pHead;
    while( cur != NULL && cur->gpa < gpa )
    {
        prior = cur;
        cur = cur->next;
    }
    // cout << "\n   prior->gpa = " << prior->gpa << endl; // for debugging ...
    if( cur != pHead )
    {
        prior->next = NULL;
        clear( pHead );
        pHead = cur;
    }
}

2. here, essentially the same as above, but using a class ... with all public ...

Code: [Select]
// linkedListUnoDuo_class.cpp //

/*
    Create two linked lists each having any number of elements ...
    uno is the (pointer to the head of the) FIRST list
    duo is the ... SECOND list

    The data in the lists will consist of a LastName and GPA (e.g. Smith 3.99)
    The lists are to be sorted BY GPA as you create them (insertSortedByGPA)
    Print out each sorted list after you create them ...
   
    Then delete all nodes from 'uno' whose GPA is above 3.0 ...
    and delete all nodes from 'duo' whose GPA is under 2.5
    Print out both of these modified lists

    Merge the REMAINING lists from both lists into one list 'uno'
    THIS 'uno' list should be created sorted by NAME (not by GPA, as above)
    Finally ... print out this 'uno' list
           
*/

#include <iostream>
#include <fstream> // re. ostream object
#include <iomanip> // re. setw, setprecision, fixed,
#include <sstream> // re. istringstream object
#include <string>

using namespace std;

class Node
{
    friend ostream& operator << ( ostream& os, Node* n )
    {
        for( ; n!= NULL; n = n->next )
            os << setw(16) << n->name << setw(6) << n->gpa << endl;
        return os;
    };
public:
    Node(string nName="", double nGPA=0) : name(nName), gpa(nGPA), next(NULL) {}
    string name;
    double gpa;
    Node *next;
} ;


bool getData( string& name, double &gpa ); // returns values by reference ...
void insertSortedByGPA( Node*& pHead, Node* pNewNode ); // pHead updated by ref.
void insertSortedByName( Node*& pHead, Node* pNewNode );
void isortByName( Node*& pHead );
void chopBack( Node*& pHead, double gpa ); // list passed in ... in sorted order
void chopFront( Node*& pHead, double gpa );// list passed in ... in sorted order
void clear( Node*& pHead );



int main() // .................................................... // begin main
{
    cout << "Getting uno data in sorted order (Enter an empty name to exit loop) ...\n";
    Node* uno = NULL;
    /*
    const int MAX = 10;
    for( int i = 0; i < MAX; ++i )
    {
        Node* cur = new Node;
        cur->next = NULL;
getData( cur->name, cur->gpa );
insertSortedByGPA( uno, cur );
    }*/
    for( ; ; )
    {
        Node* cur = new Node;
        cur->next = NULL;
if( !getData(cur->name, cur->gpa) )
        {
            cout << "Loop aborted ...\n";
            delete cur;
            break; // leave loop now ...
        }
        // else ...
        insertSortedByGPA( uno, cur );
    }
   
    cout << setprecision(2) << fixed; // show 2 decimal places ...
   
    cout << "\n   uno ...\n"; // show data ...
    cout << uno;
   
       
    cout << "\nGetting duo data in sorted order (Enter an empty name to exit loop) ...\n";
    Node* duo = NULL;
    for( ; ; )
    {
        Node* cur = new Node;
        cur->next = NULL;
if( !getData(cur->name, cur->gpa) )
        {
            cout << "Loop aborted ...\n";
            delete cur;
            break; // leave loop now ...
}
        // else ...
        insertSortedByGPA( duo, cur );
    }
   
    cout << "\n   duo ...\n";
    cout << duo;

   
    chopBack( uno, 3.0 );
    cout << "\nUNO List with all GPA's above 3.0 deleted ..." << endl;
cout << setw(16) << "Student Name" << setw(6) << "GPA" << endl;
    cout << uno;

    chopFront( duo, 2.5 );
    cout << "\nDUO List with all GPA's under 2.5 deleted ..." << endl;
cout << setw(16) << "Student Name" << setw(6) << "GPA" << endl;
    cout << duo;

/*
    // an alternate way to handle the 'last step' ...
   
    // merge lists ... by appending list 'duo' to the end of list 'uno' ...
    // first find last node in uno ...
    Node* prior = uno;
    Node* cur = uno;
    while( cur != NULL )
    {
        prior = cur;
        cur = cur->next;
    }
    if( prior != NULL ) prior->next = duo;
    else uno = duo; // since 'uno' was empty ...

    cout << "\nShowing merged lists (unsorted) ..." << endl;
cout << setw(16) << "Student Name" << setw(6) << "GPA" << endl;
    cout << uno;
   
    cout << "\nShowing merged lists (sorted) ..." << endl;
cout << setw(16) << "Student Name" << setw(6) << "GPA" << endl;
isortByName( uno );
    cout << uno;
*/

    Node* newHead = NULL; // merging two lists, sorted by name ...
    while( uno != NULL )
    {
        Node* tmp = uno->next; // keep copy of 'next' address ...
        insertSortedByName( newHead, uno );
        uno = tmp; // move up to next node in 'uno' ...
    }
    while( duo != NULL ) // now ... merge in 'duo' in name sorted order ...
    {
        Node* tmp = duo->next;
        insertSortedByName( newHead, duo );
        duo = tmp;
    }
   
    uno = newHead; // update ADDRESS of new head for uno ...
   
    cout << "\nShowing merged list sorted by name ... \n";
    cout << setw(16) << "Student Name" << setw(6) << "GPA" << endl;
    cout << uno;
   
    clear( uno ); // to keep good habit of preventing 'memory leaks' ...
       
    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    cin.get();
   
} // ............................................................... // end main



bool getData( string& name, double &gpa ) // name and gpa passed back by ref.
{
    cout << "Enter students name: " << flush;
    getline( cin, name );
    if( name == "" ) return false;
   
    cout << "Enter GPA: " << flush;
    string tmp;
    getline( cin, tmp );
    istringstream iss( tmp ); // construct iss from string tmp ...
    iss >> gpa; // get double value into gpa ...
    return true;
}

void insertSortedByGPA( Node*& pHead, Node* pNewNode ) // pHead updated by ref.
{
    // First ... handle most likely cases where new node is NOT first element
    if( pHead != NULL && pNewNode->gpa >= pHead->gpa )
    {
        // If here ... search the list for the right location
        Node* q = pHead; // Get a working copy of pHead in q
        // Start comparing with element AFTER 'q' ... i.e. the 'next in'
        while( q->next != NULL && q->next->gpa <= pNewNode->gpa )
            q = q->next; // Traverse the list ...

        // Ok, insert after 'q' by 're-nexting' the pointers ...
        // ( Includes inserting at end position ... where q->next is NULL )

        // for A->B to become A->N->B ...
        pNewNode->next = q->next; // first insert/link ... N->B
        q->next = pNewNode; // and now link ... A->N
    }
    else // becomes the first element ...
    {
        pNewNode->next = pHead; // old pHead becomes 2nd in list
        pHead = pNewNode; // and this new node becomes the head of the list
    }
}

void insertSortedByName( Node*& pHead, Node* pNewNode ) // pHead updated by ref.
{
    // First ... handle most likely cases where new node is NOT first element
    if( pHead != NULL && pNewNode->name >= pHead->name )
    {
        // If here ... search the list for the right location
        Node* q = pHead; // Get a working copy of pHead in q
        // Start comparing with element AFTER 'q' ... i.e. the 'next in'
        while( q->next != NULL && q->next->name <= pNewNode->name )
            q = q->next; // Traverse the list ...

        // Ok, insert after 'q' by 're-nexting' the pointers ...
        // ( Includes inserting at end position ... where q->next is NULL )

        // for A->B to become A->N->B ...
        pNewNode->next = q->next; // first insert/link ... N->B
        q->next = pNewNode; // and now link ... A->N
    }
    else // becomes the first element ...
    {
        pNewNode->next = pHead; // old pHead becomes 2nd in list
        pHead = pNewNode; // and this new node becomes the head of the list
    }
}

void isortByName( Node*& pHead ) // pHead updated by reference ...
{
    Node* newHead = NULL, *cur = pHead, *tmp;
    while( cur != NULL )
    {
        tmp = cur->next; // get a copy of the next address ...
        insertSortedByName( newHead, cur );
        cur = tmp; // update cur to the next address
    }
    pHead = newHead; // update pHead with head of new insert-sorted list...
}

void chopBack( Node*& pHead, double gpa ) // pHead updated by reference ...
{
    Node *cur = pHead, *prior = pHead;
    while( cur != NULL && cur->gpa <= gpa )
    {
        prior = cur;
        cur = cur->next;
    }
    // cout << "\n   prior->gpa = " << prior->gpa << endl; // for debugging ...
    if( cur != pHead )
    {
        clear( prior->next );
    }
    else clear( pHead );

}
void chopFront( Node*& pHead, double gpa ) // pHead updated by reference ...
{
    Node *cur = pHead, *prior = pHead;
    while( cur != NULL && cur->gpa < gpa )
    {
        prior = cur;
        cur = cur->next;
    }
    // cout << "\n   prior->gpa = " << prior->gpa << endl; // for debugging ...
    if( cur != pHead )
    {
        prior->next = NULL;
        clear( pHead );
        pHead = cur;
    }
}

void clear( Node*& pHead ) // pHead updated by reference ...
{
    while( pHead != NULL )
    {
        Node* tmp = pHead;
        pHead = pHead->next;
        delete tmp;
    }
}

Click on the '2' in the lower left hand corner to go to page 2 ...
« Last Edit: November 15, 2011, 02:56:31 AM by David »