Author Topic: C++ SOME UTILITY functions ... (3rd demo uses lambda's of C++11) ...  (Read 41531 times)

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
C++ SOME UTILITY functions  ... (Note!  The 3rd test program here needs a C++11 compiler.)




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 ...
« Last Edit: September 06, 2018, 02:56:49 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: C++ SOME UTILITY functions ... (some C++11 code featured) ...
« Reply #1 on: August 18, 2013, 11:26:23 AM »
0.  /* a simple student way to handle numeric input ...  so program won't crash on bad input */


Firstly, the include file ...

Code: [Select]
// 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


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

Code: [Select]
// 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 );
}
« Last Edit: August 18, 2013, 01:17:49 PM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: C++ SOME UTILITY functions ... (some C++11 code featured) ...
« Reply #2 on: August 18, 2013, 12:52:00 PM »
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: [Select]
// 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() );
}
« Last Edit: August 19, 2013, 10:20:42 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: C++ SOME UTILITY functions ... (some C++11 code featured) ...
« Reply #3 on: August 18, 2013, 12:57:26 PM »
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: [Select]
// 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
« Last Edit: August 19, 2013, 10:19:50 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: C++ SOME UTILITY functions ... (3rd demo uses lambda's of C++11) ...
« Reply #4 on: August 18, 2013, 01:56:08 PM »
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: [Select]
// 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() );
   
}
« Last Edit: August 19, 2013, 10:15:37 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: C++ SOME UTILITY functions ... (3rd demo uses lambda's of C++11) ...
« Reply #5 on: August 18, 2013, 02:13:48 PM »
Some more string utilities, trim, ltrim, rtrim  ... and split ...

Has ...

functions that return a COPY ...

AND ...

void functions that return a reference ... (so that the value in the variable in calling scope is updated.)


Code: [Select]
// trim_split_cpp.h // this version 2013-08-19 //

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


#ifndef TRIM_SPLIT_CPP_H
#define TRIM_SPLIT_CPP_H

#include <string>
#include <list>


// returns a new list of strings ... //
std::list < std::string > split( const std::string& s,
                                 const std::string delimits = " \t" )
{
    std::list < std::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( std::string::npos == p1 ) break; // i.e. if empty or all delimits

        p2 = s.find_first_of( delimits, p1+1 );
        if( std::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;
}

// adds to list of strings passed in by ref... //
void split( std::list < std::string>& lst, const std::string& s,
            const std::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( std::string::npos == p1 ) break; // i.e. if empty or all delimits

        p2 = s.find_first_of( delimits, p1+1 );
        if( std::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;
        }
    }
}



namespace copy_trim
{

// trim leading and trailing whitespaces from returned copy of 's'...
std::string trim( const std::string& s, const std::string t = " \t" )
{
    //std::cout << "\ncopy version ...\n";
    size_t p1 = s.find_first_not_of( t );
    if( std::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 ...
std::string ltrim( const std::string& s, const std::string t = " \t" )
{
    size_t p1 = s.find_first_not_of( t );
    if( std::string::npos != p1 )
        return s.substr( p1 );
    // else ...
    return "";
}

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

} //end copy_trim namespace

namespace void_trim
{
   
    // trim leading and trailing whitespaces from 's' ... and return by 'ref.'
    void trim( std::string& s, const std::string t = " \t" ) // default whitespace: "\t "
    {
        //std::cout << "\nvoid version ...\n";
        size_t p1 = s.find_first_not_of( t ); // get index of 'first char' ...
        if( std::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 rtrim( std::string& s, const std::string t = " \t" )
    {
        size_t p2 = s.find_last_not_of( t );
        if( std::string::npos != p2 )
            s.erase( p2+1 );
        else
            s.clear();
    }

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

} //end void_trim namespace

#endif

« Last Edit: August 19, 2013, 10:29:59 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: C++ SOME UTILITY functions ... (3rd demo uses lambda's of C++11) ...
« Reply #6 on: August 18, 2013, 04:59:51 PM »
And a nice comma formatted string version ... of your whole numbers ... like this :  x,xxx,xxx,xxx


Code: [Select]
// commasAdded.h //  // 2013-08-19 //


#ifndef COMMAS_ADDED_H
#define COMMAS_ADDED_H

#include <sstream>
#include <string>

// use this (only) for NON decimal numbers ...
// for example ... where T is int, long, long long, unsigned, ... //
template < typename T >
std::string commasAddedStr( T val, std::string showSign = "" )
{
    std::stringstream ss;
    ss << val;
   
    std::string tmp;
    ss >> tmp;
    if( tmp[0] == '-' )
    {
        showSign = "-";
        tmp.erase( 0, 1 ); // erase neg sign from tmp string
    }
   
    int len = tmp.size();
    int len2 = len + (len-1)/3;
   
    // construct right sized container string filled with commas ... //
    std::string tmp2( len2, ',' );
   
    int comma = 0;
    while( len2 )
    {
        --len, --len2, ++comma;

        if( comma == 4 )
        {
            comma = 1;
            --len2; // skip over 'comma' for this copy ... //
        }
       
        tmp2[len2] = tmp[len];
    }

    return showSign+tmp2;
}

#endif
« Last Edit: August 19, 2013, 10:09:06 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Re: C++ SOME UTILITY functions ... (3rd demo uses lambda's of C++11) ...
« Reply #7 on: August 18, 2013, 11:00:57 PM »
A start to ...


Code: [Select]
// classDateTime.h // 2013-08-18 //

#ifndef CLASSDATETIME_H
#define CLASSDATETIME_H

/*
    For BEGINNING COMPUTER PROGRAMMING using HLA, Python, C/C++, goto ...
    http://developers-heaven.net/forum/index.php/topic,46.0.html
*/

#include <iostream>
#include <iomanip> // setw, setfill
#include <sstream>
#include <string>
#include <ctime>
#include <cctype> // toupper

//using namespace std;

class DateTime
{
private:
    int year;
    int month;      // 0..11 // get_month() const {return month + 1;}
    int day;        // 1..31
    int weekday;    // 0..6 // returns weekday + 1
    int hour;       // 0..23
    int minute;     // 0..59
    int second;     // 0..59
public:   
    DateTime() // default constructor to fill up private time data 'right now'
    {
        time_t now = time( 0 );
        std::istringstream iss( ctime( &now ) ); // "Fri Nov 27 16:22:24 2009"

        std::string weekdayStr, monthStr;
        char c; // dummy char to hold ':' char between hour:minute:second //
        iss >> weekdayStr >> monthStr >> day
            >> hour >> c >> minute >> c >> second // using char 'c' to skip ':'
            >> year;

        weekday = find_weekday( weekdayStr );
        month = find_month( monthStr );
    }
   
    std::string get_date() const
    {
        std::ostringstream oss;
        oss << year
            << "-" << std::setfill('0') << std::setw(2) << (month+1)
            << "-" << std::setw(2) << day << std::setfill(' ');
        return oss.str();
    }
    std::string get_time() const
    {
        std::ostringstream oss;
        oss << std::setfill('0') << std::setw(2) << hour
            << ":" << std::setw(2) << minute
            << ":" << std::setw(2) << second << std::setfill(' ');
        return oss.str();
    }
    std::string get_date_time() const { return get_date() + " " + get_time(); }
   
    std::string get_weekdayname() const   { return daysTable[ weekday ]; }
    std::string get_weekdaynameL() const  { return daysTable[ weekday+14 ]; }
    std::string get_weekdaynumber() const { return daysTable[ weekday+7 ]; }  //1st,2nd...7th
    std::string get_monthname() const     { return monthsTable[ month ]; }
    std::string get_monthnameL() const    { return monthsTable[ month+24 ]; }
    std::string get_monthnumber01() const { return monthsTable[ month+12 ]; }
    std::string get_monthnumber() const   { return monthsTable[ month+36 ]; } //1st,2nd...12th
    std::string get_monthdaynumber() const{ return dayOfMonthTable[ day-1 ]; }//1st,2nd...31st
   
    int get_year() const        { return year; }
    int get_month() const       { return month + 1; }
    int get_day() const         { return day; }
   
    int get_weekday() const     { return weekday + 1; }
         
    int get_hour() const        { return hour; }
    int get_minute() const      { return minute; }
    int get_second() const      { return second; }
       
private:
    static const std::string monthsTable[];
    static const std::string daysTable[];
    static const std::string dayOfMonthTable[];
    static int find_weekday( std::string wdStr )
    {
        for( int n = 0; n < 7; ++n )
            if( daysTable[n] == wdStr ) return n; // 0..6
        // else if error ... handle ... but for now ... out of bounds error
        return 7;
    }
    static int find_month( std::string mStr )
    {
        for( int n = 0; n < 12; ++n )
            if( monthsTable[n] == mStr ) return n; // 0..11
        // else if error ... handle ... but for now ... out of bounds error
        return 12;
    }     
};

// define your (language) static const arrays here ... (after declaration above)
const std::string DateTime::daysTable[] =
{
    "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
    "1st", "2nd", "3rd", "4th", "5th", "6th", "7th",
    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
    "Friday", "Saturday"
};
const std::string DateTime::monthsTable[] =
{
    "Jan", "Feb", "Mar", "Apr", "May", "Jun",
    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
    "01", "02", "03", "04", "05", "06",
    "07", "08", "09", "10", "11", "12",
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December",
    "1st", "2nd", "3rd", "4th", "5th", "6th",
    "7th", "8th", "9th", "10th", "11th", "12th"
};
const std::string DateTime::dayOfMonthTable[] =
{
    "1st", "2nd", "3rd", "4th", "5th", "6th",
    "7th", "8th", "9th", "10th", "11th", "12th",
    "13th", "14th", "15th", "16th", "17th", "18th",
    "19th", "20th", "21st", "22nd", "23rd", "24th",
    "25th", "26th", "27th", "28th", "29th", "30th", "31st"
};

#endif

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
Ok ...

16 utilities all in one place now (in a .h file) to facilitate code reuse ...

(I have found that these, ready to use functions, can really speed up coding many student type problems ... so students can now can just include the file :

"takeInUtilities_cpp.h"

to get access to all of these 16 functions - and many are templates.)

(I also attached a little test program to demo most of these functions.)

Please see next two files ... firstly the little test program:

Code: [Select]
// test_takeInUtilities_cpp.h.cpp //  // 2015-05-02 //


#include "takeInUtilities_cpp.h"

int main()
{
    do
    {
        int iVal = takeIn< int > ("Take in an int: " );
        std::cout << "You took in " << iVal << '\n';
        std::cout << "with commas " << toStrCommasAdded(iVal) << '\n';
       
        double dVal = takeIn< double > ("Take in a double: " );
        std::cout << "You took in " << dVal << '\n';
        std::cout << "with commas " << toStrCommasAdded(dVal) << '\n';
       
        char cVal = takeIn< char > ("Take in a char: " );
        std::cout << "You took in " << cVal << '\n';
       
       
        std::string sVal = takeIn< std::string > ("Take in a C++ string: " );
        std::cout << "You took in " << sVal << '\n';
       
        const char* cStr = takeInCstr( "Take in a C string: " );
        std::cout << "You took in " << cStr << '\n';
       
        const char* ccStr = takeInLineCstrMaxLen( "Take in line as Cstr, (max len = 79): ", 79 );
        std::cout << "You took in " << ccStr << '\n';
       
        // need a 'mutable' copy 'in memory' so can change/return
        // when passed in/returned by ref... below ... //
        std::string tmp(ccStr);
       
        std::cout << "You took in (as Title) " << toCapsOnAllFirstLetters(tmp) << '\n';
        std::cout << "You took in (all Caps) " << toAllCaps(tmp) << '\n';
       
        sVal = takeInLine( "Take in line: " );
        std::cout << "You took in " << sVal << '\n';
        std::cout << "You took in (as Title) " << toCapsOnAllFirstLetters(sVal) << '\n';
        std::cout << "You took in (all Caps) " << toAllCaps(sVal) << '\n';
    }
    while( more() );
}
« Last Edit: May 03, 2015, 06:26:58 AM by David »

Offline David

  • Hero Member
  • *****
  • Posts: 647
    • View Profile
And here is the file containing these 16 utility functions:

Code: [Select]
// takeInUtilities_cpp.h //  // 2015-05-02 //

#ifndef TAKEINUTILITIES_CPP_H
#define TAKEINUTILITIES_CPP_H

#include <iostream>
#include <sstream>
#include <string>

#include <cstring> // re. strlen, strcpy...
#include <cctype> // re. isspace, tolower, toupper...

//////// 16 prototypes for utilities to ease coding ////////
template< typename T >
T takeIn( const std::string& msg,
          const std::string& errMsg = "\nInvalid ... try again please ...\n\n" ) ;
// remember to delete new Cstring when done with it ... //
const char* takeInCstr( const std::string& msg,
                        const std::string& errMsg = "\nInvalid ... try again please ...\n\n" ) ;
template< typename T >
T takeInMin( const std::string& msg, T min = 0,
             const std::string& errMsg = "\nNumbers ONLY please ...\n\n") ;
template< typename T >
T takeInMax( const std::string& msg, T max,
             const std::string& errMsg = "\nNumbers ONLY please ...\n\n") ;
template< typename T >
T takeInMinMax( const std::string& msg, T min, T max,
                const std::string& errMsg = "\nNumbers ONLY please ...\n\n") ;

// convert number of type T to string ...
template < typename T >
std::string numberToString( T val ) ;
// convert string to number of type T ...
template < typename T >
T stringToNumber( const std::string& str ) ;

// return a (Non-empty?) C++ string //
std::string takeInLine( const std::string& msg, bool okEmpty = false ) ;
// return a (Non-empty?) C string ... with up to maxLen char's //
const char* takeInLineCstrMaxLen( const std::string& msg, int maxLen,
                                  bool okEmpty = false ) ;

char* toCapsOnAllFirstLetters( char* str ) ;
std::string& toCapsOnAllFirstLetters( std::string& str ) ;

char* toAllCaps( char* val ) ;
std::string& toAllCaps( std::string& val ) ;

template < typename T >
std::string toStrCommasAdded( T val ) ;

char takeInChr( const std::string& msg ) ;
bool more( const std::string& text = "" ) ;
////////////////////////////////////////////////////////////




//////// 16 definitions for utilities to ease coding ///////
template< typename T >
T takeIn( const std::string& msg, const std::string& errMsg )
{
    T val = T();
    while( true )
    {
        std::cout << msg << std::flush;
        if( std::cin >> val && std::cin.get() == '\n' )
            break;
        else
        {
            std::cout << errMsg;
            std::cin.clear(); // clear error flasgs
            std::cin.sync(); // 'flush' cin stream ...
        }
    }
    return val;
}
const char* takeInCstr( const std::string& msg, const std::string& errMsg )
{
    std::string val;
    while( true )
    {
        std::cout << msg << std::flush;
        if( std::cin >> val && std::cin.get() == '\n' )
            break;
        else
        {
            std::cout << errMsg;
            std::cin.clear(); // clear error flasgs
            std::cin.sync(); // 'flush' cin stream ...
        }
    }
    return val.c_str();
}
template< typename T >
T takeInMin( const std::string& msg, T min,
             const std::string& errMsg )
{
    T val;
    while( true )
    {
        std::cout << msg << std::flush;
        if( std::cin >> val && std::cin.get() == '\n' )
        {
            if( val >= min )
                break;
            else
                std::cout << "\nMin value accepted here is "
                          << min << "\n\n";
        }
        else
        {
            std::cout << errMsg;
            std::cin.clear();
            std::cin.sync();
        }
    }
    return val;
}
template< typename T >
T takeInMax( const std::string& msg, T max,
             const std::string& errMsg )
{
    T val;
    while( true )
    {
        std::cout << msg << std::flush;
        if( std::cin >> val && std::cin.get() == '\n' )
        {
            if( val <= max )
                break;
            else
                std::cout << "\nMax value accepted here is "
                          << max << "\n\n";
        }
        else
        {
            std::cout << errMsg;
            std::cin.clear();
            std::cin.sync();
        }
    }
    return val;
}
template< typename T >
T takeInMinMax( const std::string& msg, T min, T max,
                const std::string& errMsg )
{
    T val;
    while( true )
    {
        std::cout << msg << std::flush;
        if( std::cin >> val && std::cin.get() == '\n' )
        {
            if( val >= min && val <= max )
                break;
            else
                std::cout << "\nValid range accepted here is "
                          << min << ".." << max << "\n\n";
        }
        else
        {
            std::cout << errMsg;
            std::cin.clear();
            std::cin.sync();
        }
    }
    return val;
}


// convert number of type T to string ...
template < typename T >
std::string numberToString( T val )
{
    std::ostringstream oss;
    oss << val;
    return oss.str();
}
// convert string to number of type T ...
template < typename T >
T stringToNumber( const std::string& str )
{
    std::istringstream iss( str );
    T tmp;
    iss >> tmp;
    return tmp;
}

// return a (Non-empty) C string ... with up to maxLen char's ...
const char* takeInLineCstrMaxLen( const std::string& msg,
                                  int maxLen, bool okEmpty )
{
    std::string val;
    while( true )
    {
        std::cout << msg << std::flush;
        getline( std::cin, val );
        int len = val.size();
        if( len )
        {
            if( len <= maxLen ) break;
            // else
            std::cout << "\nMax allowed length is "
                      << maxLen << " char's\n";
        }
        else if( okEmpty ) // case of blank lines accepted as input //
             break;
        else
            std::cout << "\nBlank line input is NOT valid here ...\n\n";
    }
    return val.c_str();
}
// return a (Non-empty) C++ string ... with up to maxLen char's ...
std::string takeInLine( const std::string& msg, bool okEmpty )
{
    std::string val;
    while( true )
    {
        std::cout << msg << std::flush;
        getline( std::cin, val );
        if( okEmpty )
            break;
        // else ...
        if( val.size() )
            break;
        // else ...
        std::cout << "\nEmpty line input is NOT valid here ...\n\n";
    }
    return val;
}

char* toCapsOnAllFirstLetters( char* str )
{
    // to get CAPS on first char ...
    if( str )
    {
        bool prev_was_ws = true; // start with previous was white space
        int len = std::strlen( str );
        for( int i = 0; i < len; ++ i )
        {
            if( prev_was_ws )
                str[i] = std::toupper( str[i] );
            prev_was_ws = std::isspace( str[i] );
        }
    }
    return str;
}
std::string& toCapsOnAllFirstLetters( std::string& str )
{
    // to get CAPS on first char ...
    bool prev_was_ws = true; // start with previous was white space
    int len = str.size();
    for( int i = 0; i < len; ++ i )
    {
        if( prev_was_ws )
            str[i] = std::toupper( str[i] );
        prev_was_ws = std::isspace( str[i] );
    }
    return str;
}

char* toAllCaps( char* val )
{
    if( val )
    {
        size_t len = strlen(val) ;
        while( len )
        {
    --len;
    val[len] = toupper( val[len] );
        }
    }
    return val;
}
std::string& toAllCaps( std::string& val )
{
    size_t len = val.size();
    while( len )
    {
--len;
val[len] = toupper( val[len] );
    }
    return val;
}

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

    std::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('.')) != std::string::npos )
    {
        decimal = tmp.substr( pos ); // includes leading decimal point //
        tmp.erase( pos );
    }


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

    // construct right size and filled with commas //
    std::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;
}

char takeInChr( const std::string& msg )
{
    std::cout << msg << std::flush;
    std::string reply;
    getline( std::cin, reply );
    if( reply.size() )
return reply[0];
    // else ...
    return 0;
}

bool more( const std::string& text )
{
    if( tolower( takeInChr( "More " + text +
                 "(y/n) ? " ) ) == 'n' )
return false;
    // else ...
    return true;
}
////////////////////////////////////////////////////////////
#endif