Desktop Programming > C/C++ & Visual C++

C++ SOME UTILITY functions ... (3rd demo uses lambda's of C++11) ...

(1/2) > >>

David:
C++ SOME UTILITY functions  ... (Note!  The 3rd test program here needs a C++11 compiler.)


Update: please see this next link:

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

FREE homework help NOW available ...

You can contact me via:
http://sites.google.com/site/andeveryeyeshallseehim/home/he-comes
http://developers-heaven.net/forum/index.php/topic,2587.0.html

You also may like to see:  C SOME UTILITY functions ... 

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


This space is reserved for code and links to code for C++ utility functions ... (and demo's of their use.)

After I have collected several C++ snippets here ...  I hope to make an index with links on this front page.

But for now, please find these little snippets of code below,  (perhaps in related usage groupings of code, on the following pages.)


0., 1.  /* simple student ways to handle numeric input ...  so program won't crash on bad input */

template < typename T >
T takeInNum
(
    const std::string& msg,
    const T& min = std::numeric_limits< T >::min(),
    const T& max = std::numeric_limits< T >::max(),
    const std::string& errMsg = "\nInvalid numeric input!\n"
);

template < typename T, typename Predicate >
T takeIn( const std::string& msg, const Predicate& pred,
          const std::string& errMsg = "\nInvalid input!\n" );

template < typename T >
T takeIn( const std::string& msg,
   const std::string& errMsg = "\nInvalid input!\n" );


2., 3.  /* example of ways in C++ to handle line (string) input from keyboard operator ...
    especially, if design calls to repeat input until input string meets some passed in condition */

std::string takeInStr( const std::string& msg,
   bool noEmpty = true, const std::string& errMsg =
      "\nA 'blank line' is NOT valid input here ...\n" );

template < typename T, typename Predicate >
    T takeIn( const std::string& msg, const Predicate& pred,
              const std::string& errMsg = "\nInvalid input!\n" );

template < typename T >
T takeIn( const std::string& msg,
   const std::string& errMsg = "\nInvalid input!\n" );


4., 5.  /* examples of a common design request ... to Caps on first letters or All Caps ... */

std::string&  toCapsOnAllFirstLetters( std::string& s );

std::string& toAllCaps( std::string& str )


6.  /* a handy utility for many C++ student coding problems ... */
char takeInChar( const string& msg, bool noEmpty = false );


7.  /* defaults to 'true'/'yes' ... unless 'n' or 'N' entered */
bool more();


8., 9., 10.  /* examples of ways to trim leading and trailing white spaces (ws) ... */
std::string& trimr( std::string& s );
std::string& triml( std::string& s );
std::string& trim( std::string& s );


11.  /* example of way to split a string into a list of strings ... */

std::list < std::string > split( const std::string& s, const std::string delimits = " \t" );

void split( std::list < std::string>& lst, const std::string& s, const std::string delimits = " \t" );


12.  /* example of way to format, with comma's, whole number output (output as strings) ...  */
template < typename T >
std::string commasAddedStr( T val );


More ...

David:
0.  /* a simple student way to handle numeric input ...  so program won't crash on bad input */


Firstly, the include file ...


--- Code: ---// takeInUtilities.h //  // 2013-08-18 //

#ifndef TAKEINUTILITIES_H
#define TAKEINUTILITIES_H


#include <iostream>
#include <string>
#include <cctype> // re. tolower, toupper ...
#include <limits> // re. numeric_limits

namespace TakeInUtilities
{
    // use this for your (one on a line) numeric input (only) ... //
    template < typename T >
    T takeInNum
    (
        const std::string& msg,
        const T& min = std::numeric_limits< T >::min(),
        const T& max = std::numeric_limits< T >::max(),
        const std::string& errMsg = "\nInvalid numeric input!\n"
    )
    {
        T val;
        while( true )
        {
            std::cout << msg << std::flush;
            if( std::cin >> val && std::cin.get() == '\n'
                                && val >= min && val <= max )
            break;
            else
            {
                std::cout << errMsg;
                std::cin.clear();
                std::cin.sync();
            }
        }
        return val;
    }

    // defaults to 'noEmpty' ... i.e. don;t accept an empty string, but
    // allows an empty string as valid input if 'noEmpty' set to false
    std::string takeInStr( const std::string& msg,
        bool noEmpty = true,
        const std::string& errMsg =
            "\nA 'blank line' is "
            "NOT valid input here ...\n" )
    {
        std::string val;
        for( ; ; )
        {
            std::cout << msg << std::flush;
            getline( std::cin, val );
            if( noEmpty )
            {
                if( val.size() )
                    break;
                else // loop again ... //
                    std::cout << errMsg;
            }
            else
                break;
        }
        return val;
    }


    std::string& toCapsOnAllFirstLetters( std::string& str )
    {
        int prev_was_space = 1;
        int len = str.size();
        for( int i = 0; i < len; ++ i )
        {
            if( prev_was_space )
                str[i] = std::toupper( str[i] );
            prev_was_space = std::isspace( str[i] );
        }
        return str;
    }

    std::string& toAllCaps( std::string& str )
    {
        int len = str.size();
        for( int i = 0; i < len; ++ i )
        {
            if( std::isalpha( str[i] ) )
                str[i] = std::toupper ( str[i] );
        }
        return str;
    }

    // default allows an empty 'takeIn' ...
    char takeInChr( const std::string& msg, bool noEmpty = false )
    {
        std::string reply = takeInStr( msg, noEmpty );
        if( reply.size() == 1 )
            return reply[0];
        // else ...
        return 0;
    }

    // must explicity enter 'n' (or 'N') to have NO more ...
    // interprets empty line input as ... 'yes -> more'
    bool more() // defaults to more ... yes ... more ... //
    {
        if( tolower( takeInChr( "More (y/n) ? " )) == 'n' )
            return false;
        // else ...
        return true;
    }
}

#endif

--- End code ---


Now a little program to demo using the above code ...


--- Code: ---// test_takeInUtilities.h.cpp //  // 2013-08-18 //


#include <iomanip>

#include "takeInUtilities.h"

const char* HEADER = "\n\t\tYour 'Beginning Student' Billing Software\n";
const int MAX_ARY_SIZE = 2; // keep small while testing/debugging ... //

// Note the 5 data members in this data 'record' / data 'struct'
struct Product
{
    std::string itemName;
    int numItems;
    double unitPrice; // in local units per item ... //

    // Next two data members are re. customer "internal stat's" ...

    char fm; // track if item was purchased for female or male

    // track any customer comments about this product (max 160 char's)
    std::string comments;

    // Note: it C++ a struct (or a class) can have methods
    // (functions) that are used to handle data
    double lineTotal() const { return numItems * unitPrice; }

} ; // <-- note semi-colon to tell compiler struct is 'done' ... //


// Note: passed by ref... (so calling scope 'prod' updated) ... //
void takeIn( Product& prod )
{
    prod.itemName =
        TakeInUtilities::takeInStr( "Item name  : " );

    TakeInUtilities::toAllCaps( prod.itemName );

    prod.numItems =
        TakeInUtilities::takeInNum< int >( "Quantity   : ", 1, 10,
            "\nValid input is a number >= 1 & <= 10 \n" );

    prod.unitPrice =
        TakeInUtilities::takeInNum< double >( "Unit price : ", 0.0,
            1000.00, "\nValid input is a number >= 0.0 & <= 1000.00\n" );

    for( ; ; ) // an example of a C/C++ forever loop ... //
    {
        prod.fm = TakeInUtilities::takeInChr
        ( "Purchase for female/male : " );

        if( prod.fm == 'm' || prod.fm == 'f' || prod.fm == 0 ) break;
        // else ...
        std::cout << "\nOnly f or m or 'blank' valid input here ...\n";
    }

    for( ; ; )
    {
        prod.comments = TakeInUtilities::takeInStr
        ( "Any comments about this product (max char's = 160) : " );

        if( prod.comments.size() <= 160 ) break;
        // else ...
        std::cout << "\nSorry " << prod.comments.size()
                  << " char's won't fit in here ...\n";
    }
}

void showBill( const Product cart[], int size )
{
    using std::setw;
    using std::cout;
    cout << "\nYour cart ...\n"
         << setw( 20 ) << "Item"
         << setw( 15 ) << "Quanity"
         << setw( 15 ) << "Unit Price"
         << setw( 15 ) << "Line Total"
         << '\n';

    double sumTotal = 0.0;

    // show 2 decimal places in money
    cout << std::fixed << std::setprecision( 2 );

    // NOTE! In C/C++ ... arrays start with index 0 ...
    for( int i = 0; i < size; ++ i )
    {
        cout << ' ' << setw( 19 ) << cart[i].itemName
             << ' ' << setw( 14 ) << cart[i].numItems
             << ' ' << setw( 14 ) << cart[i].unitPrice
             << ' ' << setw( 14 ) << cart[i].lineTotal()
             << '\n';
        sumTotal += cart[i].lineTotal();
    }

    cout << "\n\nTOTAL: " << sumTotal << " local units of money."
         << "\n\nTHANK YOU FOR YOUR PURCHASE TODAY."
         << "\n\nPLEASE VISIT AGAIN SOON.\n";
}

void showStats( const Product cart[], int size )
{
    using std::setw;
    using std::cout;
    cout << "\nYour stat's ...\n"
         << setw( 20 ) << "Item"
         << setw( 15 ) << "Quantity"
         << setw( 15 ) << "For use by"
         << "   Comments"
         << '\n';

    // NOTE! In C/C++ ... arrays start with index 0 ...
    for( int i = 0; i < size; ++ i )
    {
        cout << ' ' << setw( 19 ) << cart[i].itemName
             << ' ' << setw( 14 ) << cart[i].numItems
             << ' ' << setw( 14 ) << cart[i].fm
             << "   " << cart[i].comments
             << '\n';
    }
}


int main()
{
    Product cart[MAX_ARY_SIZE]; // get room to hold this many products

    using std::cout;
    cout << HEADER
         << "\nBelow you will be asked to enter ...\n"
         << "\nITEM NAME,\nQUANTITY,\nUNIT PRICE,\n\nfor each item.\n";

    int no = 0; // inital num products in cart ... //

    do
    {
        cout << "\nFor item " << (no+1) << ", please enter ... \n";

        takeIn( cart[no] );
        cout << '\n';
        ++no;

        if( no == MAX_ARY_SIZE )
        {
            cout << "\nYou have reached the max cart size "
                 << "allowed here of " << no << " order lines.\n"
                 << "Proceeding to 'Check-Out' right now ...\n";
            break;
        }
    }
    while( TakeInUtilities::more() );

    showBill( cart, no );
    showStats( cart, no );

    TakeInUtilities::takeInStr // allow an empty string as input ... //
    ( "\nPress 'Enter' to continue/exit ... ", false );
}

--- End code ---

David:
Now using functors ... (no need yet to be compiled with C++11 ... that comes next.)


A second little test program ... (that uses the include file on the page following this page) ...


--- Code: ---// test_takeIns.h.cpp //  // 2013-08-18 //


#include "takeIns.h"


// functor def'n needed by following 'takeInString' ... //
// also ... returns string passed in with first letters in Caps ... //
struct NoBlankLine
{
    // ctor...
    NoBlankLine( bool noEmpty ) : yes( noEmpty ) {}

    // def'n of overloaded operator () for NoBlankLine
    bool operator() ( const std::string& s ) const
    {
        return  yes ? s.size() : true;
    }

    private:
    bool yes;
} ;


// will not accept an empty string if noEmpty has default value of true
std::string takeInString( const std::string& msg,
                          bool noEmpty = true,
                          const std::string& errMsg =
                          "\nBlank line not valid here!\n" )
{
    // firstly, input string using TakeIns::takeIn (with condition):
    std::string result = TakeIns::takeIn < std::string, NoBlankLine >
    (
        msg, NoBlankLine( noEmpty ), errMsg
    );
    return result;
}

// Now ... 3 more functor def'ns needed in main ... //

struct GreaterThanIntZero
{
    bool operator() ( int i ) const { return i > 0; }
} ;
struct NoNegs
{
    bool operator() ( double i ) const { return i >= 0.0; }
} ;
struct MaleFemale
{
    bool operator() ( char i ) const { return i == 'm' || i == 'f'; }
} ;



int main()
{
    do
    {
        std::string name = takeInString( "Enter your name    : " );

        std::cout << "\nYour entered               : " << name;
        TakeIns::toCapsOnAllFirstLetters( name );
        std::cout << "\nWith Caps on first letters : " << name
                  << "\n\n";

        int id = TakeIns::takeIn < int, GreaterThanIntZero >
        (
            "Enter your id      : ",
            GreaterThanIntZero(),
            "\nValid here are int size numbers > 0\n"
        );
        std::cout << "\nYou entered " << id << "\n\n";

        double pay = TakeIns::takeIn < double, NoNegs >
        (
            "Enter your payment : ",
            NoNegs(),
            "\nValid here are decimal numbers >= 0.0\n"
        );
        std::cout << "\nYou entered: " << pay << "\n\n";

        char sex = TakeIns::takeIn < char, MaleFemale >
        (
            "Female/Male (f/m)  : ",
            MaleFemale(),
            "\nValid entries are only f or m\n"
        );
        std::cout << "\nYou entered " << sex << "\n\n";

        std::string comments = takeInString
        (
            "Enter any comments : ",
            false /* allow a blank line ... as valid entry ... */
        );
        std::cout << "\nYou entered: \"" << comments << "\"\n\n";

    }
    while( TakeIns::more() );
}

--- End code ---

David:
Here is the include file ... that is needed by the test program on the page above ...

(and this include file is also used in the test program on the page following this page ... Be forewarned that that next test program uses C++11 lambda functions ... and so needs a C++11 compiler to be compiled.)



--- Code: ---// takeIns.h //  // 2013-08-19 //


// Acknowledgement:
// The 'design here' was adapted from one suggested by Mike
// in response to my post at DaniWeb earlier this month ...
// Thank you Mike : ) ... //


#ifndef TAKEINS_H
#define TAKEINS_H


#include <iostream>
#include <string>
#include <cctype> // re. tolower, toupper ...

 // The 'prime focus here' is JUST taking in (user entered) ...
 // primitive types ... numbers, C++ strings and char ...
 
 // so that a C++ student has a READY template to take in validated
 // primitive data ... (prompting for one item of data at a time) ...
 // without the 'progam crashing' on 'bad data' entered by a user at
 // the keyboard ...
 
 // i.e. this is NOT for getting data from a file ... //
 
namespace TakeIns
{
    template < typename T >
    bool get_val( T& val )
    {
        std::cin >> val;
        return std::cin && ( std::cin.get() == '\n' );
        // making sure NO extra non-numeric char's after number ... //
    }

    inline
    bool get_val( std::string& s )
    {
        getline( std::cin, s );
        return std::cin;
    }

    inline
    bool get_val( char& c )
    {
        std::string s;
        getline( std::cin, s );
        if( s.size() )
            c = s[0];
        else c = 0;
        return std::cin && s.size() <= 1;
    }



    // takeIn (in a loop) until valid ...
    // with a condition to meet before accepting ... //
    template < typename T, typename Predicate >
    T takeIn( const std::string& msg, const Predicate& pred,
              const std::string& errMsg = "\nInvalid input!\n" )
    {
        T result = T();
        while( true )
        {
            std::cout << msg << std::flush;
            if( get_val( result ) && pred( result ) )
            {
                std::cin.sync();
                break;
            }
            else
            {
                std::cout << errMsg;
                std::cin.clear();
                std::cin.sync();
            }
        }
        return result;
    }


    // takeIn (in a loop) until valid type before accepting ... //
    template < typename T >
    T takeIn( const std::string& msg,
        const std::string& errMsg = "\nInvalid input!\n" )
    {
        T result = T();
        while( true )
        {
            std::cout << msg << std::flush;
            if( get_val( result ) )
            {
                std::cin.sync();
                break;
            }
            else
            {
                std::cout << errMsg;
                std::cin.clear();
                std::cin.sync();
            }
        }
        return result;
    }


    // (no loop) just take in (the first) char entered (on a line) ... //
    char takeInChar( const std::string& msg )
    {
        std::cout << msg << std::flush;
        char c;
        get_val( c );
        return c;
    }

    // defaults to yes ... do more ... //
    bool more()
    {
        return ( tolower( takeInChar( "More (y/n) ? " ) ) != 'n' );
    }

    std::string& toCapsOnAllFirstLetters( std::string& str )
    {
        int prev_is_space = 1;
        int len = str.size();
        for( int i = 0; i < len; ++ i )
        {
            if( prev_is_space )
                str[i] = std::toupper( str[i] );
            prev_is_space = std::isspace( str[i] );
        }
        return str;
    }

    std::string& toAllCaps( std::string& str )
    {
        int len = str.size();
        for( int i = 0; i < len; ++ i )
            str[i] = std::toupper ( str[i] );
        return str;
    }
}

#endif
--- End code ---

David:
Here is a test program that uses the include file above ...

Note!

You will need to compile this test suite with a C++11 compiler ... since this test program uses C++11 lambda functions.

You will also NEED to include the TWO files on the following two pages (following this page) ...



--- Code: ---// takeInStuff_C++11.cpp //  // 2013-08-19 //

// uses C++11 lambda functions like:  []( int i ) { return i > 0; }
// uses C++11 (for each) function like:  for( char& c : inResultCstr )


#include <iomanip>

#include "takeIns.h"
#include "commasAdded.h"
#include "trim_split_cpp.h"



// Using a C++11 lambda function here ...
// Will not accept an empty string if noEmpty is 'true' (default)
// to get special def'n used here to 'takeInString' ... //
std::string takeInString( const std::string& msg, bool noEmpty = true )
{
    // Using 'TakeIns::takeIn' (with condition) to get input ... //
    std::string result = TakeIns::takeIn < std::string >
    (
        msg, // prompt msg passed in ... //
        [noEmpty]( const std::string& s ) // lambda def'n begins ...
        {
            return ( noEmpty ? s.size() : true ); // if no blank lines
            // allowed, make sure size!=0, otherwise, blank line ok //
        },  // end of lambda function def'n ... //

        "\nBlank line not valid here!\n" // errMsg passed in ... //
    );
    return result;
}



int main()
{
    do
    {
        std::string name = takeInString( "Enter your name  : " );

        std::cout << "\nYou entered      : \"" << name << '"';
        std::string t_name = copy_trim::trim( name );
        TakeIns::toCapsOnAllFirstLetters( t_name );
        std::cout << "\nTrimmed and Caps : \"" << t_name << "\"\n\n";

        int id = TakeIns::takeIn < int >
        (
            "Enter your id    : ",
            []( int i ) { return i > 0; },
            "\nValid here are 'int' size numbers > 0\n"
        );
        std::cout << "\nYou entered      : "
        << commasAddedStr( id ) << "\n\n";

        double pay = TakeIns::takeIn < double >
        (
            "Enter your payment : ",
            []( double i ) { return i >= 0; },
            "\nValid here are decimal numbers >= 0.0\n"
        );
        std::cout << std::setprecision(2) << std::fixed;
        std::cout << "\nYou entered        : $" << pay << "\n\n";

        char sex = TakeIns::takeIn < char >
        (
            "Male/Female (f/m)  : ",
            []( char i ) { return i == 'm' || i == 'f'; },
            "\nValid entries are only f or m\n"
        );
        std::cout << "\nYou entered        : " << sex << "\n\n";

        // Using 'TakeIns::takeIn' (with NO condition) for input ... //
        std::string comments = TakeIns::takeIn < std::string >
        (
            "Enter any comments : "
        );
        void_trim::trim( comments );
        std::cout << "\nTrimmed, was ...   : \"" << comments << "\"\n";

        std::list< std::string > myLst;
        split( myLst, comments );
        std::cout << "There were " << myLst.size()
                  << " words in the comments\n";

        std::cout << std::endl;
    }
    while( TakeIns::more() );
   
}
--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version