News:

To still receiving newsletters from us please subscribe to our Newsletters:
http://tech.groups.yahoo.com/group/developers-Heaven/

Main Menu
Menu

Show posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Show posts Menu

Topics - David

#21



An often asked student request is regarding the use of cin in C++

So ...

here  is a little demo of using cin in C++


// demo_cin.cpp //  // 2016-01-26 @ 19:35 //

// a demo of using C++ cin //

#include <iostream>
#include <sstream> // re. stringstream objects //
#include <string>

using namespace std;



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

bool more( const string& text = "" )
{
    char reply = takeInChr( "More " + text + "(y/n) ? " );
    if( reply == 'n' || reply == 'N' )
        return false;
    // else ...
    return true;
}




int main()
{
    string dummy;

    do
    {
        cout << "Enter a char: ";
        char c;
        cin >> c; // extract first char //
        /*
        above, skips over any leading whitespace and reads first (non-whitespace) char entered.
        note: leaves any next char like the  '\n' char still in the cin (in) stream
        */
        cout << "You entered: '" << c << "'\n";

        getline( cin, dummy ); // clean up any stuff and '\n' whitespace left over //
        if( dummy.size() != 0 ) cout << "You also entered '" << dummy << "'\n";
    }
    while( more( "characters " ) ) ;



    do
    {
        cout << "Enter an integer: ";
        int val;
        cin >> val;
        /*
        above, skips over any leading whitespace and expects first non-whitespace entered to be a 0..9 or a + or -
        reads all next 0..9's and stops at first non-0..9
        Note: cin flags are set if good data or bad data encountered.
        Note also: cin leaves all next char like the  '\n' char still in the cin (in) stream
        Thus if you entered -123abc  456
        above and then pressed the Enter key,
        val holds -123 and calling cin.good() would then return true,
        but abc 456 and the '\n' whitespace char would still all be in the cin stream
        */
        if( cin.good() )
        {
            cout << "You entered: '" << val << "'\n";
            getline( cin, dummy ); // 'eat' whitespace '\n' left in cin stream //
            if( dummy.size() != 0 ) cout << "You also entered: '" << dummy << "'\n";
        }
        else
        {
            cin.clear(); // firstly, clear (all) cin error flags //
            getline( cin, dummy );
            cout << "Error! Was expecting a *valid* integer, but '" << dummy << "' was encountered.\n";
        }
    }
    while( more( "integers " ) );


    while( true )
    {
        // Safe data entry ... uses  ... as per the following ...

        cout << "Enter your ID number, a space and then your name(s): ";
        string line;

        // get the whole line into 'line' and 'eat' the '\n' char(s) at the end //
        getline( cin, line );


        istringstream iss( line ); // form 'iss' object from string obj. 'line' //


        // then parse out the data you expect from the iss object ...
        int id;
        string name;
        if( iss >> id && id > 0 ) // accept ONLY positive ID's here //
        {
            string word;
            while( iss >> word )
                name += word + ' ';

            if( name.size() != 0 )
            {
                name.erase( name.size()-1 ) ; // erase last ' ' char added //

                cout << "You entered '" << id << ' ' << name << "'\n";
                if( !more( "lines to parse " ) ) break;
            }
            else
                cout << "You forgot to enter any names ... try again.\n";
        }
        else
            cout << "Error! Was expecting a *valid* positive integer ... followed by name(s).\n"
                 << "Try again ...\n";
    }

}


#22


An often asked student request is regarding coding a dynamic array ...

So ... .

UPDATE: start here now to see the new 3 fast steps ..

http://developers-heaven.net/forum/index.php/topic,2622.msg3177.html#msg3177

Or here, to see even more recent Six Fast Steps ....

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


Return here to see a more 'complete' class Vector ... (in file Vector3.h below.)

template < typename T >
class Vector
{
///
} ;

to get you started.


Firstly the .h file ...

// Vector3.h //  // 2016-02-12 //

#ifndef VECTOR3_H
#define VECTOR3_H

#include <iostream>

const unsigned CHUNK_SIZE = 8;

template < typename T >
class Vector
{
public:
    typedef T* iterator;
    typedef const T* const_iterator;

    Vector();
    Vector( size_t n );
    Vector( const Vector& ); // copy ctor ...
    Vector( const T*, const T* ); // array ctor ...
    Vector< T >& operator = ( const Vector< T >& ); // overloaded =
    ~Vector() { clear(); }

    void push_back( const T& );
    void reserve( size_t );
    void resize( size_t );
    void shrink( size_t );
    void pack();
    void clear();

    // overloaded [], done below ...
    T& operator [] ( size_t ) ; // allow element to be updated
    const T& operator [] ( size_t ) const; // 'read only'

    // overloaded << is done outside class below ...

    // += is different for numbers and strings ...
    // NOTE: def'n of >> is often best done outside of class

    iterator begin() ; // { return ary; }
    iterator end() ; // { return ary+len; }
    const_iterator begin() const ; // { return ary; }
    const_iterator end() const ; // { return ary+len; }

    T at( size_t pos ) const ;

    size_t capacity() const;
    size_t size() const;

    bool empty() const { return len == 0 ; }

    T back() const;
    void pop_back();

    void erase( Vector< T >::iterator it );
    void erase( Vector< T >::iterator it, size_t num );
    void insert( size_t pos, const T& val, size_t num = 1 );


    void output( std::ostream& , char end = '\n' ) const;

protected:
    size_t cap;
    size_t len;
    T* ary;
    void enlarge(); // used by push_back
} ;




template < typename T >
void Vector< T >::output( std::ostream & outs, char end ) const
{
    for( size_t i = 0; i < len; ++i )
    {
        outs << ary[i] << end;
    }
}

template < typename T >
std::ostream& operator << ( std::ostream& os, const Vector< T >& v )
{
    v.output( os );
    return os;
}

// note syntax here ..................................... //
template < typename T >
typename Vector< T >::iterator Vector< T >::begin()
{
    return ary;
}

template < typename T >
typename Vector< T >::iterator Vector< T >::end()
{
    return ary+len;
}

template < typename T >
typename Vector< T >::const_iterator Vector< T >::begin() const
{
    return ary;
}

template < typename T >
typename Vector< T >::const_iterator Vector< T >::end() const
{
    return ary+len;
}
// ...................................................... //


template < typename T >
Vector< T >::Vector() : cap(0), len(0), ary(0) {}

template < typename T >
Vector< T >::Vector( size_t n ) : cap(n), len(n), ary( new T[cap] )
{
    for( size_t i = 0; i < len; ++i ) ary[i] = T();
}

template < typename T >
Vector< T >::Vector( const Vector< T >& v ) // copy constructor ...
{
    cap = v.cap;
    len = v.len;
    ary = new T[cap];
    for( size_t i = 0; i < len; ++i ) ary[i] = v.ary[i];
}

// array constructor ... NOTE! b is one past last element
template < typename T >
Vector< T >::Vector( const T* a, const T* b )
{
    cap = b-a;
    len = cap;
    ary = new T[cap];
    for( size_t i = 0; i < len; ++i ) ary[i] = a[i];
}

// overloaded operator=
template < typename T >
Vector< T >& Vector< T >::operator = ( const Vector< T >& v )
{
    if( this != &v )
    {
        delete [] ary;
        cap = v.cap;
        len = v.len;
        ary = new T[cap];
        for( size_t i = 0; i < len; ++i ) ary[i] = v.ary[i];
    }
    return *this;
}

template < typename T >
void Vector< T >::push_back( const T& e )
{
    if( len == cap ) enlarge();
    /* now add in new element ... */
    ary[len] = e;

    ++ len;
}

// new array to hold 2x's records ... copies old to new
template < typename T >
void Vector< T >::enlarge()
{
    if( cap ) cap += cap; // double capacity ...
    else cap = CHUNK_SIZE; // set initial capacity
    T* tmp = new T[ cap ];
    for( size_t i = 0; i < len; ++i ) tmp[i] = ary[i];
    //for( int i = cap-1; i >= len; --i ) tmp[i] = T();
    delete [] ary;
    ary = tmp; // update the base address of ary
}

template < typename T >
void Vector< T >::reserve( size_t newCap )
{
    if( newCap > cap )
    {
        cap = newCap;
        T* tmp = new T[ cap ];
        for( size_t i = 0; i < len; ++i ) tmp[i] = ary[i];
        delete [] ary;
        ary = tmp; // update the base address of ary
    }
}

template < typename T >
void Vector< T >::resize( size_t newSize )
{
    if( newSize > len )
    {
        reserve( newSize );
        for( size_t i = cap-1; i >= len; --i ) ary[i] = T();
        len = newSize;
    }
    else if( newSize < len )
    {
        len = newSize;
        pack();
    }
}

template < typename T >
void Vector< T >::shrink( size_t newSize )
{
    if( newSize < len ) len = newSize; // leave cap unchanged
}

template < typename T >
void Vector< T >::pack()
{
    if( len < cap/2 )
    {
        cap = len + len/2;
        T* tmp = new T[cap];
        for( size_t i = 0; i < len; ++i ) tmp[i] = ary[i];
        delete [] ary;
        ary = tmp; // update address ...
    }
}

template < typename T >
void Vector< T >::clear()
{
    if( ary )
    {
        delete [] ary;
        cap = 0;
        len = 0;
        ary = 0;
    }
}


template < typename T >
size_t Vector< T >::size() const
{
    return len;
}
template < typename T >
size_t Vector< T >::capacity() const
{
    return cap;
}

// NO bounds checking here ... //
template < typename T >
T& Vector< T >::operator [] (size_t i)
{
    return ary[i];
}
template < typename T >
const T& Vector< T >::operator [] (size_t i) const
{
    return ary[i];
}

template < typename T >
T Vector< T >::at( size_t pos ) const
{
    if( pos < len ) return ary[pos];

    // else ... if reach here ...
    std::cerr << "\nINDEX '" << pos
              << "' IS OUT OF BOUNDS"
              << ", THUS, RETURNED VALUE '" << T()
              << "' IS NOT VALID!\n";
    return T();
}


template < typename T >
T Vector< T >::back() const
{
    if( len ) return ary[len-1];

    // else ... if reach here ...
    std::cerr << "\nEmpty ... THUS, RETURNED VALUE '" << T()
              << "' IS NOT VALID!\n";
    return T();
}

template < typename T >
void Vector< T >::pop_back()
{
    if( len ) -- len;
    else //if reach here ...
        std::cerr << "\nEmpty ... THUS ... can NOT pop_back() anything!\n";
}


template < typename T >
void Vector< T >::erase( Vector< T >::iterator it )
{
    if( ! len )
    {
        std::cerr << "\nERROR! Vector empty.\n";
        return;
    }
    //else ...
    if( it < begin() || it >= end() )
    {
        std::cerr << "\nERROR! NOT in vector ...\n";
        return;
    }
    // else ...
    for( size_t i = it - begin() ; i < len-1; ++i )
        ary[i] = ary[i+1]; // copy each element above, down one index, so erased
    // now update len for 'this' vector object ...
    -- len;
}

template < typename T >
void Vector< T >::erase( Vector< T >::iterator it, size_t num ) // begin at it, num to erase //
{
    if( ! len )
    {
        std::cerr << "\nERROR! Vector empty.\n";
        return;
    }
    //else ...
    if( it < begin() || it >= end() )
    {
        std::cerr << "\nERROR! NOT in vector ...\n";
        return;
    }

    const size_t index = it - begin();
    if( num > len - index ) num = len - index;

    // else ...
    if( num > 0 )
        for( size_t i = index; i < len-num; ++i )
            ary[i] = ary[i+num]; // copy nth element above, down n places, so erased
    // now update len for 'this' vector object ...
    len -= num;

    pack();
}

// default is INSERT ONE element, i.e. num = 1 //
template < typename T > // assumes pos >= 0, num > 0
void Vector< T >::insert( size_t pos,  const T& val, size_t num )
{
    if( num == 0 )
    {
        std::cerr << "\nERROR! Can NOT insert 0 elements ...\n";
        return;
    }

    if( cap < len + num ) reserve( len + num ); // updates cap
    if( pos > cap-num ) pos = len; // just add in ... at end ...
    else if( pos < len ) // shift last 'len-pos' elements up num places ....
    {
        int top = len + num - 1;
        for( size_t i = 0; i < len-pos; ++i ) {
            ary[top] = ary[top-num];
            --top;
        }
    }
    for( size_t i = 0; i < num; ++ i ) ary[pos+i] = val; // insert val's
    len += num; // update len
}


#endif

#23
HLA / Python 3.x examples ...
February 05, 2015, 08:57:56 PM
Here are some Python 3.x examples that beginners in Python ... and even intermediate level coders in Python ... may find useful.

Enjoy :)



The first illustrates an important "GOTCHA" in Python ... take a look:

# demo_GOTCHA'S_with_list_and_.py #


# CARE needed ... when using functions ...
# when passing in MUTABLE objects to functions !!!

# (Since with objects .... passing in a reference,
#  i.e. a pointer, i,e, an address)

# So ... if obj gets CHANGED inside the function ...
# AND IF CHANGES NEED to be
# reflected in the OBJECT, outside the function scope,
# i.e. you want to change, (or maybe NOT to change),
# the passed in mutable object,
# and have, (or maybe NOT TO have),
# those changes RETAINED in the calling scope !!! #


outLst = [ 1,2,3 ]
print( "Before ...", outLst )

# Note: this is NOT an efficent use of list ... popping off the front #
# If need to pop from front, better to use a 'deque' container,
# that handles well, adding and popping at both front and back ends #
def popFront( lst ): # changes reflected in calling scope #
    while lst:
        # print( "deleting", lst[0], "from list... " )
        # del(lst[0]) # oe use below to return val)
        print( "lst.pop(0) =", lst.pop(0) )
        print( "lst is now:", lst )

popFront( outLst )
print( "After ...", outLst )


print( "vs..." )


outLst = [ 1,2,3 ]
print( "Before ...", outLst )

def popBack( lst ): # changes NOT reflected in calling scope #
    while lst:
        print( "deleting", lst[-1], "from list... " )
        lst = lst[:-1]  # lst now is NEW,
                        # SO NOT same address as lst passed in "
        print( "lst is now:", lst )

popBack( outLst )
print( "After ...", outLst )


name = '  maTThew daVid jOHn zAVITz   '
print( "\nBefore :  '" + name + "'" )

# recall strings are IMMUTABLE,
# so NEED to make and return NEW string #
def toTitleCase( strIn ):
    newStr = ''
    prev = ' '
    for c in strIn.strip():
        if prev.isspace():
            newStr += c.upper()
        else:
            newStr += c.lower()
        prev = c
       
    return newStr

print( "After  :  '" + toTitleCase(name) + "'" )


name = '  maTThew    daVid  jOHn         zAVITz   '
print( "\nBefore :  '" + name + "'" )

# recall strings are IMMUTABLE,
# so NEED to make and return NEW string #
def toTitleCase2( strIn ):
    lst = strIn.split()
    return ' '.join( [x[0].upper() + x[1:].lower() for x in lst] )


print( "After  :  '" + toTitleCase2(name) + "'" )

       
input( "\nPress 'Enter' to continue/exit ... " )
   
#24
This question is regarding a student grade type of program ...

Write a program that enters marks for any number of students, (for some semester course) ...
Calculate each student's total marks, total / total_possible * 100 (%) ... and the letter grade.
Then the class average and letter grade.
   
(The grading is:  A for 90's, B for 80's, C for 70's, D for 60's ...  but below is F)


The output could look similar to this:


# ID First Second Final Average% Grade
1 20071156      5.5 16.5 32.0 64 D
...
Class average for 10 students is: 72.5 (C)

       
   
Use functions where ever it might help logic flow.
#25



The subject of Graphs, Directed Graphs and Weighted Directed Graphs can be quite daunting (especially at first) ...

This site will feature some simple beginning steps ... and a collation of example code, that was recently found on the web  ... but here it is all together ... edited, fixed and polished some ... to help make it all ... work for YOU!

Here is a little C++ example, to get you started ... that uses an adjacency list  ...(Google it) ...

Check it out.

It simply tests and reports if a target vertex is reachable from some start vertex.
An example might be ... can one get from one place ... in a maze ... to some other?

// a_isReachable.cpp //  // 2014-12-08 //

// a DiGraph (Directed Graph) using an adjacency list //

/*
    Edited/augmented & fixed memory leaks
    now uses STL vector containers, etc (instead of new arrays, etc)
   
    Idea and original code found at:
    http://www.sanfoundry.com/cpp-program-find-shortest-path-between-two-vertices-using-dijkstras-algorithm/
   
    This program simply tells if a node 'd', (the destination),
    is 'reachable' from 's', (the start),
    (the node from which we start the search to see if
     there exists any 'reachable path')
   
    The 'digraph' here is unweighted ...
   
    The program stops and reports 'reachable' at the first
    'reachable' path encountered as it traverses the 'graph'
*/

#include <iostream>
#include <vector>
#include <list>

#include <string> // re. more() ...
#include <cctype> // re. tolower(..)

#include <algorithm> // re. swap

using namespace std;



// This class represents a directed graph
// (a simple un-weighted digraph)
// using an adjacency list representation ... //

class Graph
{
    vector< list< int > > adj;
public:
    // ctor... v is number of Verticies (Nodes)
    Graph( int v );
   
    // function to add an edge to graph
    void addEdge( int p, int q ) ;
   
    // returns true if there is a path from s to d, other wise returns false
    bool isReachable( int s, int d );
   
    // a wrapper function to return size 'vector< list< int > > adj'
    size_t size() const { return adj.size() ; }
   
    friend ostream& operator << ( ostream&, const Graph& );
} ;


// def'ns

ostream& operator << ( ostream& os, const Graph& g )
{
    int size = g.adj.size();

    if( size )
    {
        list< int >::const_iterator it;
        for( int i = 0; i < size; ++ i )
        {
            for( it = g.adj[i].begin(); it != g.adj[i].end(); ++ it )
                 os << '(' << i << ','<< *it << ")  ";
            os << '\n';
        }
    }
    return os;
}

Graph::Graph( int v ) // ctor...
{
    adj.resize( v );
}

void Graph::addEdge( int v, int w )
{
    adj[v].push_back( w ) ; // Add w to v's list.
}

// A BFS (Breadth First Search) based function ...
// to check whether d is reachable from s.
// Note the use of a queue (a list < int > here)... FIFO //
bool Graph::isReachable( int s, int d )
{
    // Base case ...
    if( s == d )
        return true;

    // construct & (initial) all the vertices as not yet visited ...
    vector< bool > visited ( this->size(), false );

    // construct an empty queue (a list of int) for BFS ...
    list< int > queue;

    // set the current node as visited and enqueue it
    visited[s] = true;
    queue.push_back(s);

    while( !queue.empty() )
    {
        // Dequeue a vertex from queue ...
        s = queue.front();
        queue.pop_front();
       
        // iterator 'it' will be used to get all the
        // adjacent vertices of a vertex ...
        list< int >::iterator it;

        // Get all adjacent vertices of the dequeued vertex s
        // If an adjacent has not been visited, then mark it visited
        // and enqueue it
        for( it = adj[s].begin(); it != adj[s].end(); ++it )
        {
            // If this adjacent node is the destination node, then return true
            if ( *it == d )
                return true;

            // Else, continue to do BFS
            if( !visited[*it] )
            {
                visited[*it] = true;
                queue.push_back(*it);
            }
        }
    }

    return false;
}


// utiliites to facilitate valid input in a loop ... //
int takeInChr( const std::string& msg = "" )
{
    std::cout << msg << flush;
    std::string reply;
    getline( cin, reply );
    if( reply.size() )
return reply[0];
    // else ...
    return 0;
}
bool more()
{
    if( tolower( takeInChr( "\n\nMore (y/n) ? " )) == 'n' )
return false;
    // else ...
    return true;
}

bool uvOkRange( int u, int v, int topVal )
{
    bool goodData = true;
    if( u < 0 || u > topVal )
        { cout << '\n' << u << " NOT in range 0.."
               << topVal << '\n'; goodData = false; }
    if( v < 0 || v > topVal )
        { cout << '\n' << v << " NOT in range 0.."
               << topVal << '\n'; goodData = false; }
    return goodData;
}




// Driver program to test methods of graph class
int main()
{
    // construct an empty graph to hold 5 Verticies (5 Nodes) ..
    Graph g(5);
   
    // get adjacent nodes for each node in graph ...
    g.addEdge(0, 1);  // 1 'is reachable' from 0
    g.addEdge(0, 2);  // 2 'is reachable' from 0
   
    g.addEdge(1, 3);  // 3 'is reachable' from 1
   
   
    g.addEdge(2, 1);
    g.addEdge(2, 3);
   
    g.addEdge(2, 4);
   
    g.addEdge(3, 4);
    g.addEdge(4, 4);

    do
    {
        cout << "The graph g: \n"<< g ;
       
        cout << "\nEnter 2 int's separated by a space ..."
             << "\nthe source and destination vertices, in range 0..4 : ";
        int u, v;
        if( cin >> u >> v && cin.get() == '\n' && uvOkRange( u, v, 4 ) )
        {
            int count = 2;
            while( count-- )
            {
                cout << "\nThere is "
                     << (g.isReachable(u, v) ? "a " : "NO ")
                     << "path from " << u << " to " << v;
                swap( u, v );
            }

        }
        else
        {
            cin.clear();
            cin.sync();
            cout << "\nData entry error ...\n";
        }
    }
    while( more() );
}



For a easy way to download all these example programs, see ...

http://www.4shared.com/folder/WUykX6-t/DiGraphsAndWDiGraphs.html


Addendum:

This subject ... of how to reach a place ... leads to  ... a much BIGGER context !!!



After several days of many hours each ... I suddenly was impressed ...  that the structure and the meaning of any notation  ... is so important!

Abstract symbols have meaning only in pre-defined (real) context.

For example:

What do I mean when I say (two, to, too, ... ) ?

The same sound has several spellings to help differentiate the meaning provided by different contexts ...


It's really quite amazing what a bird's eye look/see ...

by any of God's seeing creation ... can do!


In terms of reach-ability ...

How can (fleshly/finite) man, (ever) see/reach the (invisible infinite Spirit), the Creator of this whole large universe?


Well ... firstly, everything created tells much regarding the creator ...

Firstly ... that a Creator exists!

And much more !!!


But ... since we can see, hear, speak, move, love, hate ... so much more our Creator!

So did / does our creator ever re-veal beyond what the created things speak?


Yes ... the history of this ... His-Story ... is well established and preserved ...

passed on by those to whom it was chosen to be entrusted.


There is a steady line drawn from Adam via Seth, to Noah and via Shem, to Abraham and via Isaac, Jacob/Israel, Judah ... to Yeshua the Messiah, who was also fore-named Emmanuel (i.e. the creator El to be with us, the creator who in the beginning, as Elohim, created the heavens and the earth.)

Please continue at:

http://developers-heaven.net/forum/index.php/topic,2587.0.html
#26
Update:

you can contact me via this link ...

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

(my/editor gmail link is on the 2nd page)



C++ 11 has been here for awhile ... so it's time to 'open the books' and start to use some of the nice coding features like auto and lamda's ...

Also, time to tackle the tricky code needed to add const_iterator to a simple single linked-list ... a list that already works pretty well with just an iterator ...

The approach taken here, will be as follows:

Firstly, let's look at a very simple SLList, and see if we can get that working.  It will be just two files, a test .cpp file and a template class list .h file

Here we will use 'nested classes' ...all the List code is in the one .h file.

The list here is pretty 'bare bones' ... but that's ok ... because we just want to see the code for the nested iterator and const_iterator classes.

Note!  This first example will be done using a C++11 compiler.


Secondly, we will take ... what I recently read ...  was a 'more STL like approach' and use separate files for the parts needed ... 1) Node, 2) iterator, 3) const_iterator, 4) SLList ... and 5) a little test file

Note the use of typedef here to 'import/nest' the iterator and const_iterator classes 'inside' the SLList class.
Also note the frequent use of friend classes and forward declarations of these classes before they are defined, to facilitate them being 'friends' ...

Note!  This second example will be done using a PRE-C++11 compiler ... (i.e. ISO C++)


The third example, will be done using a C++11 compiler ...

Just a short test file,

and two .h files ...

one for the node class
and
one for the single linked list class

This single linked list is a little more 'embellished' ...

for example it demos/uses move copy and move assignment

The methods defined here are mostly just the ones you might want to have ... i.e. ... if you wanted to derive a STACK class from this single linked list class ... which is also shown next ...

And then ... a little demo program, that uses that (derived) STACK class ... to solve a palindrome type student problem.

Note here, the iterator and const_iterator classes are 'nested' in side the single linked list class.

I would suggest that you follow this development sequence ...

from an easy 'bare-bones' list ...

to a little more functional single linked list ...

because we want to focus here,

not on all the functions,

but rather on how to get the const_iterator parts merged in the list ...

It may take a while for you to 'see' the several key coding changes/additions ...

to make the transition for just having an iterator ...

to ALSO having a const_iteratoer ... in your list class.

It took me much 'digging' and 'thinking' and 'trying' ... to finally get it (all?) to work ...the way I 'expected' it should work.

Enjoy ... but be prepared for taking some time to dig in ... read all the comments ... make some code 'changes/edits/errors' ... and read the error messages ... and add some tests and see the code working (or not?)

Shalom shalom,

David





#27
A beginning of a collection of utilities ...

For Java 7 and Java 8 ...




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

After I have collected several Java 7 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.)


Just to get started ... (please see snippets below) ...

Added (2015-01-18 for new students of java ... A first Big step in Java beyond 'Hello World' ... see Java files at bottom of this first page.)


To facilitate input from keyboard user
To bug-proof input and streamline code ...
(for many student type problems)


More.yn( 'y' ) // defaults to yes if 'y' passed in ... return type is Java boolean
TakeIn.takeInInt( msg ) // msg is prompt message ... return type is Java int
TakeIn.takeInLng( msg )  // return type is Java long
TakeIn.takeInDbl( msg )  // return type is Java double
TakeIn.takeInStr( msg ) // return type is Java String
TakeIn.takeInChr( msg ) // return type is Java char
ReadWholeFile.readFileIntoString( fname) // return type is Java String
ReadWholeFile.readFileIntoList( fname) // return type is Java List < String >
...
See additional classes, at the bottom, to facilitate reading and writing strings, arrays and lists of text files ...
where large file read times are compared for Python 3.3, C++, C and Java 7 with nio ...
(and Java 7's new io ... compares well with the C read times ... ONLY IF the files are already in cache memory ... otherwise, C is still the FASTEST, then Python, then C++ and finally Java 7 ... in this typical ratio of times on my test system 53 : 62 : 72 : 80 (see test system below)



Update 2017-11-27

Please note that class TakeInLine is my replacement for the above ...
and you can see this class ...
and examples of its use at the following link:

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

After just reviewing these now, several-year-old pages, I'm thinking I should start a new thread, a.s.a.p.,  featuring Java 8 usage for Beginning Java coders ... bottom up.


Added on 2015-01-18 at bottom here, for new students of Java:

A 'next step' in Java after the usual 'Hello World' first step ...

*  demos safe take in of values ... from a keyboard user
   (using Java's exception handling)
*  demos classes with static methods ...
   (See the class TakeIn ... that facilitates safe take in of values from keyboard user.) 
*  demos some examples of Java String and Char handling ...
*  demos looping using while(..) and do..while(..) ... until a (boolean) condition is met
*  demos use of if, if else, else structure
*  demos organizing a program into blocks of code to facilitate code re-use
   (See class TakeIn, class More, class ToCaps)
*  demos use of importing (access to) some Java library methods/functions that are used here
*  demos use of Java 8 lambda function
*  demos use of Java 8 parallel processing


// HelloPerson.java //  // version 2015-01-18 //

import java.io.IOException;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.stream.*; // Java 8 needed //
//import java.util.Comparator; // re. old way not using lambda functions //

/**
*  A BIG first step in Java beyond the proverbial "Hello World of Java" starting program
*/
public class HelloPerson
{
    public static void main(String[] args) throws IOException
    {
        do
        {
            List < Integer > ages = new ArrayList <> (); // Java infers types from 'left to right' //
           
            String name = null;
            while( (name = TakeIn.takeInStr( "Enter a name: " ).trim() ).length() == 0 )
            {
                System.out.printf( "%nBlank lines not accepted here ... " );
            }
            name = ToCaps.toCapsOnAllFirstLetters( name );
   
            System.out.print( "Hello " + name + " ... " );
           
            int age = 0;
            while( !validAgeRange( age = TakeIn.takeInInt( "What is your age: " ))) ; // loop until valid data entered ... //
           
            if( age != 1 )
            {
                if( (age < 10) || (age > 50) )
                    System.out.println( name.toUpperCase() + ", awesome age, being " +
                                        age + " years old ..." );
                else
                    System.out.println( name + ", that's really nice that you are only " +
                                        age + " years old!" );
            }
            else // age is 1 ... so just to demo the 'wrapper' toAllCaps method call here ... //
                System.out.println( ToCaps.toAllCaps(name) + /* just to use the 'wrapper' here */
                                    ", that's AWESOME ... BUT REALLY, you are ACTUALLY " +
            age + " year old!!!" );
            ages.add( age );
           
            float sum = age;
            while( Character.toLowerCase(TakeIn.takeInChr( "Do you have other brothers "
                                                            + "or sisters (y/n)? " )) == 'y' )
            {
                while( !validAgeRange( age = TakeIn.takeInInt( "Enter age: " ))) ; // loop until valid data entered ... //
                ages.add( age );
                sum += age;
            }
           
            // Java 8 could break up a long list to different cores to speed up processing ... //
            float newSum = ages.parallelStream().reduce((accum, item) -> accum + item).get() ;
            System.out.format( "%nParallel processed average age: %.1f%n", newSum/ages.size() );
           
           
            Collections.sort(ages);
            System.out.format( "For all the ages entered: " + ages + "%n"
                                + "the average age is %.1f%n", sum/ages.size() );
            /*                   
            // old way before java 8, also need to: import java.util.Comparator; // 
            // to sort in reverse (i.e. descending) orded of age ... //
            ages.sort( new Comparator< Integer >()
                        {
                            @Override
                            public int compare(Integer a, Integer b)
                            { return b-a; }
                        }
                     );
            */
            ages.sort( (a, b) -> b.compareTo(a) ); // Java 8 way using lambda function, for 'reverse' sort ... //
            System.out.println( "ages reversed: " + ages );
        }
        while( More.yn() ); // More.yn defaults here to 'y' ... //
    }
   
    static boolean validAgeRange( int age )
    {
        if( (age >= 1) && (age <= 965) )
            return true;
        //else ...
        System.out.printf( "%nI don't think so ... REALLY ... " );
        return false;
    }
}



Uses ...
// TakeIn.java //  // version 2015-01-18 //

import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;


public class TakeIn
{
    // Java's way to handle 'const' ... is by using 'static final' ...
    // bUT NOTE, that in Java, type String is already IMMUTABLE(i.e. 'final') ... //
    static String EXTRA_CHARS = "%nError! EXTRA_CHAR'S!  Invalid non-white-space char's %nare " +
                                "present that lead and/or trail the input value.%n";
    // call as: TakeIn.takeInStr( msg ) ...
    public static String takeInStr( String msg ) throws IOException
    {
        System.out.print( msg );
       
        // Create a BufferedReader using System.in ... //
        BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
        String line = "";
        try
        {
            line = br.readLine();
        }
        catch( IOException e )
        {
            //System.err.println( e );
            //System.err.printf( "%nUNEXPECTED string input error ... %n" );
            //line = ""; // default here to empty line ... //
            throw new IOException( e + " UNEXPECTED error attempting string input!" );
        }
        //line = line.trim();
        return line;
    }
 
 
    // call as: TakeIn.takeInChr( msg )
    public static char takeInChr( String msg ) throws IOException
    {   
        String line = takeInStr( msg );
        if( line.length() > 0 )
            return (char)line.charAt(0);
        // else ...
        return (char)0; 
    } 


       
    // call as: TakeIn.takeInInt( msg )
    public static int takeInInt( String msg ) throws IOException
    {   
        int iVal = 0;
        boolean done = false;
        while( !done )
        {
            String line = takeInStr( msg ).trim();
            String[] ary =  line.split( "[ \t]+" );
     
            if( ary.length == 1 )
            {
                try
                {
                    iVal = Integer.parseInt( ary[0] );
                    done = true;
                }
                catch( NumberFormatException e )
                {
                    System.out.printf( "%nError! " + e );
                    System.out.printf( "%nOnly valid 'int' numbers are accepted, so try again ...%n%n" );
                }
            }
            else System.out.printf( EXTRA_CHARS );
        }
        return iVal;
    }
   

    // call as: TakeIn.takeInLng( msg )
    public static long takeInLng( String msg ) throws IOException
    {   
        long longVal = 0;
        boolean done = false;
        while( !done )
        {
            String line = takeInStr( msg ).trim();
            String[] ary =  line.split( "[ \t]+" );

            if( ary.length == 1 )
            {
                try
                {
                    longVal = Long.parseLong( ary[0] );
                    done = true;
                }
                catch( NumberFormatException e )
                {
                    System.out.printf( "%nError! " + e );
                    System.out.printf( "%nOnly valid 'long' numbers are accepted, so try again ...%n%n" );
                }
            }
            else System.out.printf( EXTRA_CHARS );
        }
        return longVal;
    }
   
   
    // call as: TakeIn.takeInDbl( msg ) ...
    public static double takeInDbl( String msg ) throws IOException
    {   
        double dVal = 0;
        boolean done = false;
        while( !done )
        {
            String line = takeInStr( msg ).trim();
            String[] ary =  line.split( "[ \t]+" );

            if( ary.length == 1 )
            {
                try
                {
                    dVal = Double.parseDouble( ary[0] );
                    done = true;
                }
                catch( NumberFormatException e )
                {
                    System.out.printf( "%nError! " + e );
                    System.out.printf( "%nOnly valid 'double' numbers are accepted, so try again ...%n%n" );;
                }
            }
            else System.out.printf( EXTRA_CHARS );
        }
        return dVal;
    }
}



Also uses ...
// ToCaps.java //  // version 2015-01-18 //

public class ToCaps
{
    public static String toCapsOnAllFirstLetters( String str )
    {
        boolean prevWasWS = true;
        char[] chars = str.toCharArray();
        for( int i = 0; i < chars.length; ++i )
        {
            if( Character.isLetter( chars[i]) )
            {
                if( prevWasWS )
                {
                    chars[i] = Character.toUpperCase( chars[i] );   
                }
                prevWasWS = false;
            }
            else prevWasWS = Character.isWhitespace( chars[i] );
        }
        return new String( chars );
    }
   
    public static String toAllCaps( String str ) // can just use str.toUpperCase() //
    {
        return str.toUpperCase();
    }
   
    public static String toCapsOnFirstLetter( String str )
    {
        if( str.length() > 0 )
        {
            char[] chars = str.toCharArray();
            chars[0] = Character.toUpperCase( chars[0] );
            return new String( chars );
        }
        /*
        if( str.length() > 0 )
            return Character.toUpperCase(str.charAt(0))
                    + str.substring(1);
        */
        // else ...
        return str;
    }
}



And now the 4th ... last file needed here:
// More.java //  // 2015-01-18 //

import java.io.InputStreamReader;
import java.io.BufferedReader;

public class More
{
    // call as:  More.yn( 'y' ) // or 'n' if want no as defaultChar ... //
    public static boolean yn( final char defaultChar ) // 'y' or 'n' tells 'defaultChar' ... //
    {
        System.out.print( "More (y/n) ? " ) ;

        // Create a BufferedReader using System.in
        BufferedReader br = new BufferedReader( new InputStreamReader( System.in ) );
        String reply = null;
        try
        {
            reply = br.readLine();
        }
        catch( Exception e )
        {
            System.out.printf( "%nAn unexpected ERROR during String input!%n" + e );
            //System.out.printf( "%nExiting loop ... %n" );
            reply = "n"; // default here to NO ... //
        }

        // NEED these ... //
        if( defaultChar == 'y' )
        {
            if( reply.length() == 0 ) return true;
            if( Character.toLowerCase(reply.charAt(0)) == 'n' ) return false;
            return true;
        }
        // else ...
        if( defaultChar == 'n' )
        {
            if( reply.length() == 0 ) return false;
            if( Character.toLowerCase(reply.charAt(0)) == 'y' ) return true;
            return false;
        }
        // else ... defaults to YES ...
        return true;       
    }

    // call as:  More.yn()
    // this defaults to 'y' ... i.e. yes more ... //
    public static boolean yn() // defaults to yes/y //
    {
        return yn( 'y' );
    }
   
}


Enjoy :)
#28
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 ...
#29
Why would any one ever want to use C code in a C++ program?



Here are some typical 'student reasons' why ...


1.  The prof said to...

2.  You want faster code by using C strings...

3.  You want your executable file size to be much reduced...
#30
Just download and install the latest Python 3.3.2 and then ...

you are all ready ...

to jump-start doing Data-Base Programming with Python 3
(and SQLite3 version 3.7.12 included.)





Below are some example to help get you started:


import sqlite3

conn = sqlite3.connect( 'my_test1.db' )

print( "Opened database successfully" )

input( "Press 'Enter' to continue/exit ... " )
#31
C/C++ & Visual C++ / C SOME UTILITY functions ...
May 26, 2013, 07:27:36 PM
This space is reserved for code and links to code for C utility functions ...

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.)




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

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


Update 2015-04-08: 

SEE the next link for several newly improved STUDENT take in type utilities  ...
with out of bounds error handling ...
(Some VERY HANDY student utilities.)

http://developers-heaven.net/forum/index.php/topic,2608.msg3158.html#msg3158


1.  /* example of a way to fix fgets TWO sometimes very annoying problems   */
char* fixedFgets( char* str, size_t bufSize, FILE* fin );

2.  /* example of a way to trim leading and trailing ws ... */
char* stripWS( char* s );

3.  /* example of an expedient way in C to handle string input from keyboard operator ...
    especially, if design calls to repeat input until string is of 'acceptable length' */
char* takeInStr( const char* msg, char* buf, unsigned bufLen, unsigned maxStrLen );

4.  /* an example of a common design request ... to Caps on first letters */
char* toCapsOnFirstLets( char* str );

5.  /* a simple student way to handle numeric input ...
   so program won't crash on bad input */
int takeInInt( const char* msg, int myMin, int myMax );

6.  /* loop until user takes in a valid int ... after prompt(s) ...  */
int takeInValidInt( const char prompt[] );

7.  /* a handy utility for many C student coding problems ... */
char takeInChar( const char* msg );

8.  int more(); /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */

9.  /* since using 'static' buf inside, memory persists ... so can return address */
char* takeInStaticString( const char* msg, unsigned max_len );

10. /* accepts only positive (i.e. >= 0) valid int range of values ... */
int takeInValidPosIntViaStaticString( const char* prompt, int high );

11. /*  returns a valid int in range INT_MIN..INT_MAX  */
int takeInValidMinMaxIntViaStaticString( const char* prompt, int myMin, int myMax );

...

And more added below ... like binary search, an iterative and also a recursive example, date and time and valid date and valid dob and days between two dates and ...


/* returns 'int' value if in range '0'..'9' else returns -1 if NOT a digit */

int getDigit( char c )
{
    if ( c < '0' || c > '9' ) return -1;
    return c - '0';
}

/*
    Note: int( c ), where c is a char in the range '0'..'9'
    would return integers in the range 48..57
    ... but getDigit( c ) returns integers in the range 0..9
*/



/* returns int value if in range '0'..'9' else returns -1 if not a number */

int isNum( char c )
{
    if ( c < '0' || c > '9' ) return -1;
    return c - '0';
}




1.  Six Fast Steps to Programming in C

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


2.  CvecOfInt.h, CvecOfString.h, Cvec.h, Cvec_func's.h (with FUNCTION POINTERS)

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


3.  Cvec_func's.h example programs ... using FUNCTION POINTERS to facilitate reuse

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


4. ClistOfInt.h, ClistOfString.h, Clist.h, Clist_func's.h (with FUNCTION POINTERS)

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


5.  Clist_func's.h example programs ... using FUNCTION POINTERS to facilitate reuse

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


6.  split.h ... a C emulation of the Python spilt function to parse a string ...

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


7.  Binary Search Tree template class in C ++ and Simple C Version

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


8.  Beyond Beginning Computer Programming in C ...

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


9.  Send in your C++ or C student coding problem, with code inside code tags (#)

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


10. Free coding help for beginners in C or C++

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


11. Clist Insertion Sort Tutorial ... and also see a recursive merge sort of a list

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


12. First steps ... via example programs in C++ and C ...

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


13. New thread especially for students of C and C++

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


14. BEGINNING COMPUTER PROGRAMMING (using C++ or C)

http://developers-heaven.net/forum/index.php/topic,127.0.html
#32
BEGINNING COMPUTER PROGRAMMING


(Using a Try it and See it approach)

                                                                                                                         
(AND ... a Computer Student's/Teacher's DREAM Introductory Computer Language - HLA)


Update: 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 may also want to see ...

http://developers-heaven.net/forum/index.php?topic=46.0

BEGINNING COMPUTER PROGRAMMING (using HLA and Python 3.1 and C++) 


http://developers-heaven.net/forum/index.php?topic=2599.0

Six Fast Steps to Programming in High Level Assembly (HLA)



Introduction:



To facilitate the solid insights provided in learning about computing by some exposure to Assembly Language, but also to provide a friendly and facile start for new programmers, HLA provides all the facility and power of Assembly Language, but with a user friendly syntax, yet offers many of the elegant structures of an HLL (High Level Language) like Pascal or C or even the OOP of a language like C++.  And so, going on to C, or C++, or any other modern HLL, will be more readily enabled, and with some real appreciation of what's going on under the hood and inside the machine.



The author has successfully taught Computer Programming at a Canadian grade 7/8 Junior High and 9 to 12 High School level when PCs first became available using varied approaches, including using a personally authored simulated SIMPLE SIMON compiler running on a PC.   But his final approach, after which this course is being patterned, was the most fun, and also the most successful, for both students ... and teacher.



Please enjoy and profit from your work. Don't be afraid to make changes and see what happens.  Now dig in ... You may be surprised how much you will learn.



Shalom shalom,

David W. Zavitz

Toronto, Ontario, CANADA

dwzavitz@gmail.com


For arrangements to use this text beyond individual personal use, please contact the author at the above e-mail.

© (C) 2007-08-17



Acknowledgements:

This course and text would not be possible without the very gifted insights, teaching experiences, and programming skills of Randall Hyde,

http://en.wikipedia.org/wiki/Randall_Hyde

the Author, Creator, and so far, the Sustainer of HLA. I also would like to acknowledge the tremendous encouragement given by my youngest son Matthew, who's recent Engineering need to know a little C++, and then Assembly ... provided the incentive for a little more then that, from dad, (which led to HLA and now this attempt to benefit beginning computer students in general.)  Also, I would like to thank my students at Scarborough Christian High School, who besides being very promising young ladies and gentlemen, provided exemplary feedback as we went along into some not yet fully charted territory.




Table of Contents:

Chapter 01: The Computer prints a message
Chapter 02: The Computer gets some input
Chapter 03: The Computer adds some numbers
Chapter 04: The Computer repeats a procedure
Chapter 05: The Basic Elements of computer programming ... and low level example(s)
Chapter 06: The Computer rolls the dice ... a first simulation
Chapter 07: First Memory Flow Lab
Chapter 08: Memory Flow Lab2
Chapter 09: Memory Flow Lab3
Chapter 10: HLA Data Types
Chapter 11: The Computer does some Algebra with real numbers ... and Input Data Validation
Chapter 12: Pointers, Strings, your own Types, Records, Arrays, and dynamic things on the fly!
Chapter 13: The Computer files its Records
Chapter 14: The Computer reads its Files
Chapter 15: The Computer updates (edits, deletes, sorts, chops-duplicates-in) its Files
Chapter 16: The Computer ... vast OS's ... and the garbage collects?  (Operating Systems ... what is DOS?)
Chapter 17: The Computer delivers daily Manna ... (gui Canadien ... eh?)
Chapter 18: OOP ... goes the computer?
Chapter 19: OOP 2
Chapter 20: Shaping Moving OOP with HLA   ... a CLASS ACT ! (revised 2013-05-24)
#33


This section is designed to help new C++ students 'to see something of' ...

the progression in coding ...

from a simple struct Node, 

that has a data element and a pointer to the next Node element ...

to code for a functioning template class list

with iterators to traverse the list and access the data in a Node ...


Please see the comments in each of the 6 programming steps below.

In the 5th and 6th steps the code for the List class is in its own .h file

(these .h files follow the respective test programs, for programming steps 5 and 6 ... )


You may also like to see these steps ...
http://developers-heaven.net/forum/index.php/topic,2629.0.html


OK ... here is step one ...

// List_step1.cpp //  // 2013-05-08 //

// design a struct to hold data and a 'next' address i.e. a link to 'next' Node
// here, at step 1, we will just be holding, for the data, an int ...
// NOTE how C++ facilites, via a constructor, assigning initial values ...

#include <iostream>

using namespace std;

struct Node
{
    int data;
    Node* next;

    // ctor ... handles both cases of default ctor and value passed ctor ...
    // if call Node myNode; in your program, default value for int data is 0
    // if call Node myNode(7); in your program, default value for int data is 7
    // Note that the value assigned to next is NULL in both of the above cases
    Node( int dt = 0 ) : data(dt), next(NULL) {}

};

void print( const Node* cur )
{
    cout << cur->data;
}



// NOTE below that head is a pointer to Node
// AND updated by being passed in (and back) by C++ reference style passing
void push_back( Node*& head, int n )
{
Node* newNode = new Node( n );
Node* cur = head;

    if( cur ) // not first node
    {
        while( cur )
        {
            if( cur->next == NULL )
            {
                cur->next = newNode;
                return;
            }
            else cur = cur->next;
        }
    }
    else head = newNode;
}

//delete specific item ...
void deleteItem( Node*& head, int item )
{
    Node* cur = head; // get copy
    Node* prev = NULL;


    while( cur )
    {
        if( cur->data == item ) break;
        prev = cur;
        cur = cur->next;
    }

    // test end conditions ...

    if( cur ) // was found
    {
        if( prev ) // was not first node, so prev and cur exist
        {
            prev->next = cur->next; // skip over cur ...
            delete cur;
        }
        else // was first node
        {
            head = head->next;
            delete cur;
        }

    }
    else cout << "\nNot found ...\n";
}

void printAll( const Node* cur )
{
    if( !cur )
    {
        cout << "\nThe list is empty ... so can't print anything ...\n";
        return;
    }

    while( cur )
    {
        print( cur );
        cout << " ";
        cur = cur->next;
    }
    cout << endl;
}

void clean( Node*& cur ) // updated head to NULL when done
{
    while( cur )
    {
        Node* delNode = cur;
        cur = cur->next;
        delete delNode;
    }
}



int main()
{

    // NOTE!  'head' MUST be initialled to NULL for push_back etc to work ... //
    Node* head = NULL;

    push_back( head, 10 );
    push_back( head, 30 );
    push_back( head, 20 );
    push_back( head, 40 );

    printAll( head );

    cout << "\ndeleting 20 ... \n";
    deleteItem( head, 20 );
    printAll( head );

    cout << "\ndeleting 10 ... \n";
    deleteItem( head, 10 );
    printAll( head );

    cout << "\nclean list ... \n";
    clean( head );
    printAll( head );

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



Here is a little introduction to coding for a binary search tree in C and C++

Enjoy :)


At first, let's look at some simpler C code re. a 'first go' at a Binary Search Tree ...
(Note: the previous error in the C version, of the  ... 'remove value from the BST' function, is now fixed, as of 2014-11-05)

Below, please find a little test program ... followed by the .h include file that is being tested' by this demo test program ...

/* test_binarySearchTree_c.h.c*/ /* 2014-11-02 */

/* presuming ? negative numbers are stored in memory using 2's complement ? */
#define MIN_INT (1 << (sizeof(int)*8 - 1))
#define MAX_INT -(MIN_INT + 1)

#define startWithAryValues 1
#define RAN_ARY_SIZE 25

#include "binarySearchTree_c.h" /* includes <stdio.h>, <stdlib.h> */

#include <time.h> /* re. srand( time(0) ) */


const char* MENU = "\n 1.  Add to the tree"
"\n 2.  Find maxDepth of tree"
"\n 3.  printInOrder"
"\n 4.  printInPreOrder"
"\n 5.  printInPostOrder"
"\n 6.  Delete a node"
"\n 7.  Delete all"
"\n 8.  Delete a value"
"\n 9.  Find a value"
"\n 0.  Exit"
"\n\nEnter your choice: ";


void transfer( Node**, const int ary[], int size );

int getValidInt( const char* msg );

void testDeleteAllInOrderInserted()
{
    int ary[RAN_ARY_SIZE] = { 0 } ;
const int sizeAry = RAN_ARY_SIZE;

Node* root = NULL;
int i, size = 0;

srand( time(0) ) ;

for( i = 0; i < sizeAry; ++i )
{
        ary[i] = rand() % sizeAry;
        if( !find( root, ary[i]) ) ++size;
        insert( &root, ary[i] );
    }
       
    puts( "printInOrder ... " );
    printInOrder( root );
    printf("with size = %d", size );

    for( i = 0; i < sizeAry; ++i )
    {
        if( find( root, ary[i] ) ) --size;
        delVal( &root, ary[i] );
        printf( "\n\nAfter attempt at deleting %d, size is %d, "
                "getCount is %d, maxDepth is %d\n",
                ary[i], size, getCount(root), maxDepth(root) );
        printInOrder( root );
    }
   
    printf("\n\nPress 'Enter' to continue ..." );
    while( getchar() != '\n' ) ;
}


int main()
{
#if startWithAryValues
const int ary[] = { 30, 10, 40, 20, 50,
      11, 5, -5, 44, 66,
77, 33, 22, 99, -7 };
const int sizeAry = sizeof( ary ) / sizeof(int);
int i;
#endif

int choice, numGood, value;

Node* root = NULL;
int size = 0;

#if startWithAryValues
int loop = 3;

printf( "testDeleteAllInOrderInserted() ... \n" );
testDeleteAllInOrderInserted();
top:
size = sizeAry/loop;
transfer( &root, ary, size  );
printf( "\nThe maxDepth of tree from root is: %d", maxDepth( root ) );
printf( "\nprintInPreOrder: " );
printInPreOrder( root );
printf( "\nprintInOrder: " );
printInOrder( root );
printf( "\nThe size of tree is: %d\n", size );
printf( "The getCount from root is: %d\n", getCount( root ) );
for( i = 1; i <= size; ++i )
{
NodePos np;
initNodePos( &np );
getKthNode( root, &np, i );
printf( "\nThe maxDepth of tree from position %d is: %d", i,
  maxDepth( np.cur ) );
printf( "\nThe getCount from position %d is: %d", i,
getCount( np.cur ) );
}
fputs( "\n\nPress 'Enter' to continue ... ", stdout ); fflush( stdout );
while( getchar() != '\n' );

if( --loop > 0 ) goto top;

#endif

printf( "\n\nMIN_INT = %d, MAX_INT = %d\n\n", MIN_INT, MAX_INT );
do
{
printf( MENU ); fflush( stdout );
choice = -1;
scanf( "%d", &choice );
while( getchar() != '\n' );

switch( choice )
{
case 1:
printf("Enter a value: ");
numGood = scanf( "%d", &value );
while( getchar() != '\n' );
if( numGood == 1 )
{
insert( &root, value );
++size;
printf( "\nThe maxDepth of tree is: %d", maxDepth( root ) );
printf( "\nprintInOrder: " );
printInOrder( root );
printf( "\nThe size of tree is: %d\n", size );
}

else printf( "\nBad entry NOT inserted ...\n" );
break;
case 2:
printf( "\nThe maxDepth of tree is: %d", maxDepth( root ) );
break;
case 3:
printf( "\nprintInOrder: " );
printInOrder( root );
printf( "\ngetCount = %d", getCount( root ) );
printf( ", getCountInOrder = %d", getCountInOrder( root ) );
break;
case 4:
printf( "\nprintInPreOrder: " );
printInPreOrder( root );
printf( "\ngetCount = %d", getCount( root ) );
printf( ", getCountInOrder = %d", getCountInOrder( root ) );
break;
case 5:
printf( "\nprintInPostOrder: " );
printInPostOrder( root );
printf( "\ngetCount = %d", getCount( root ) );
printf( ", getCountInOrder = %d", getCountInOrder( root ) );
break;
case 6:
if( root )
{
del( &root );
printf( "\nOne node has been deleted ....\n" );
--size;
printf( "\nThe size of tree now is: %d",size );
}
else printf( "\nTree was empty ....\n" );
break;
case 7:
{
int n = 0;
while( root )
{
del( &root );
++n;
--size;
}
printf( "\nThe size of tree now is: %d",size  );
printf( "\n%d nodes were deleted ... \n", n );
break;
}
case 8:
{
int delValue = getValidInt( "Enter value to delete: " );
if( find( root, delValue ) )
{
                delVal( &root, delValue );
                printf( "\n%d was deleted ok ... ", delValue );
--size;
printf( "\nThe size of tree is: %d",size );
}
else
printf( "\n%d was NOT found, so NOT deleted...", delValue );

}
break;
case 9:
{
int findValue = getValidInt( "Enter value to find: " );
if( find( root, findValue ) )
printf( "\n%d was found ok ...", findValue );
else
printf( "\n%d was NOT found ...", findValue );
}
break;
case 0: /* exit on 0 ... */
{
int count = 0;
count = delAll( &root );
printf( "\n%d nodes were deleted ...\n", count );
/*
int n = 0;
while( root )
{
del( &root );
++n;
--size;
}
printf( "\nThe size of tree now is: %d",size  );
printf( "\n%d nodes were deleted ... \n", n );
break;
*/
}
break;
default:
printf( "\nInvalid choice ... \n" );
}
putchar( '\n' );
}
while( choice != 0 );

fputs( "\nPress 'Enter' to continue ... ", stdout ); fflush( stdout );
while( getchar() != '\n' );
return 0;
}

#35
These space is reserved for example solutions to common Student Type programming problems ...

Here, the goal is to see how one might code student type solutions in C++ code, compared to C code, compared to Python 3 code ...

(and to compare the processing speeds where time would be significant.)

Let's start with a very common C++ Student Grades program where the data for each program is input from a file, we will call ...

grades.txt

structured like this:
// example of file structure ...
/*
4 7
Sam : Smith-Jones : 10 : 52 : 99 : 70 : 90  : 88  : 77
Julie  :  Anders Johnston : 80 : 52 : 33 : 70 : 90 : 44 : 99
Zorman Storman : Davies : 0 : 52
Omar Gomar : Davies : 100 : 100 : 100 : 100 : 100 : 100 : 100
*/


Here is a first go ... using a struct that seems a suitable match to the file structure ...

i.e. each struct holds each line of data, First Name, Last Name and up to 7 integer scores, each out of 100 max

BUT NOTE: the first line in the data file holds two integers separated by 'white space'.  The first integer lets the program know how many lines of student data follow.  The 2nd integer lets the program know the max number of scores to be stored in memory for each student.

Also note: we are using the STL vector to hold our student data struct's, and a library sort to sort by names and average grade.

A slightly advanced feature here would be using static variables in the student struct ...

1. to store (one time only) the max number of student scores to be handled for each student record
2. to store (one time only) the max length of all the student names, to 'make pretty the alignment' of the output

... and a vector of integers inside each struct, to hold the grades for each student data struct

Also using functions (methods) in the struct that pertain to processing the data stored in each student struct

Also, note our coded compare functions passed to the library sort function, to specify how to do each desired sort, here by descending average mark and also by ascending student last name, first name.

// gradesCpp.cpp // 2013-02-03 //

#include <string>
#include <fstream>
#include <sstream> // re. istringstream obj's to parse line
#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm> // re. sort ...

using namespace std;

const string FNAME = "grades.txt";
// example of file structure ...
/*
4 7
Sam : Smith-Jones : 10 : 52 : 99 : 70 : 90  : 88  : 77
Julie  :  Anders Johnston : 80 : 52 : 33 : 70 : 90 : 44 : 99
Zorman Storman : Davies : 0 : 52
Omar Gomar : Davies : 100 : 100 : 100 : 100 : 100 : 100 : 100
*/


struct Student
{
    string fname, lname;
    static int max_len;
    static int num_tests;
    double avg;
    vector< int > grades;
   
    Student() // default constructor ...
    {
        avg = 0;
        grades.reserve( num_tests );
    }
   
    void show()
    {
        cout << left << setw(max_len+5) << setfill('.')
             << (lname + ", " + fname) << " ";
       
        cout << setfill(' ') << right;
        for( unsigned i = 0; i < grades.size(); ++ i )
        {
            cout << setw(3) << grades[i] << ' ';
        }
        cout << " Average = " << setprecision(1) << fixed << setw(5)
             << avg << endl;
    }
   
    void cal_set_avg()
    {
        //avg = 0; // set by (default) constructor above //
        unsigned i;
        for( i = 0; i < grades.size(); ++ i )
        {
            avg += grades[i];
        }
        if( i ) avg /= num_tests;
    }
} ;

// initial static variables used in above struct here ...
int Student::max_len = 0;
int Student::num_tests = 0;


// these next compare functions are used by sort algorithm
bool cmpAvg( const Student& a, const Student& b )
{
    return a.avg > b.avg;
}
bool cmpName( const Student& a, const Student& b )
{
    if( a.lname == b.lname ) return a.fname < b.fname;
    return a.lname < b.lname;
}


void rstrip( string& s )
{
    int len = s.size();
    while( len && s[--len] == ' ' );
    s.erase(len+1);
}
void lstrip( string& s )
{
    int len = s.size(), count = 0;
    while( len && s[count] == ' ' ) --len, ++count;
    s.erase( 0, count );
}
void strip( string& s )
{
    int len = s.size(), count = 0;
    while( len && s[--len] == ' ' );
    s.erase(len+1);
    while( len && s[count] == ' ' ) --len, ++count;
    s.erase( 0, count );
}

void fillFromFile( ifstream& fin, vector< Student >& v )
{
    cout << "File dump ..." << endl;

    int numStuds;
    fin >> numStuds >> Student::num_tests;
    cout << numStuds << ' ' << Student::num_tests << endl;

    string line;
    getline( fin, line ); // get to end of line ...

    v.reserve( numStuds ); // reserve dynamic memory for numStuds Students
    while( getline( fin, line ) )
    {
        cout << line << endl;
       
        // get fname and lname ('stripped' of end spaces) ...
        istringstream iss( line );
        Student s;
        getline( iss, s.fname, ':' );
        rstrip( s.fname );
        getline( iss, s.lname, ':' );
        strip( s.lname );

        int lenl = s.lname.size();
        int lenf = s.fname.size();
        if( lenl+lenf > Student::max_len )
            Student::max_len = lenl+lenf; // update max_len

        // get all grades for this student record ...
        string tmp;
        while( getline( iss, tmp, ':' ) )
        {
            // convert string tmp to int g ...
            istringstream issg( tmp );
            int g;
            issg >> g;
            s.grades.push_back( g ); // append this 'g' to this Student's grades
        }
        s.cal_set_avg(); // calculate and set this student average

        // ok ... append this Student record ...
        v.push_back( s );
    }
}




int main()
{
    vector< Student > studs; // create empty vector to hold 'Student' objects
   
    ifstream fin( FNAME.c_str() ); // recall must use 'C type' of string here
    if( fin )
    {
        fillFromFile( fin, studs );
        cout << "\nVector dump ..." << endl;
        unsigned i;
        for( i = 0; i < studs.size(); ++i ) studs[i].show();

        sort( studs.begin(), studs.end(), cmpName );
       
        cout << "\nSorted by name... " << endl;
        for( i = 0; i < studs.size(); ++i ) studs[i].show();
       
        sort( studs.begin(), studs.end(), cmpAvg );
       
        cout << "\nSorted by avg... " << endl;
        for( i = 0; i < studs.size(); ++i ) studs[i].show();
       
        fin.close();
    }
   
    cout << "\nPress 'Enter' to continue/exit ... " << flush;
    string line;
    getline( cin, line );
}
#36
HLA / Demo Programs linked from Beginning Calculus
January 13, 2013, 05:56:16 PM
Below, please find the Python Demo Programs linked to here, from the new thread ...

Beginning Calculus



To go to Beginning Calculus, click here ...

http://developers-heaven.net/forum/index.php?topic=2601.0

To go to a Beginner's Level introduction to the Python version 3 programming language ...

http://developers-heaven.net/forum/index.php?topic=46.0


This first demo is an 'updated version' of Archimedes method to calculate the value for the constant pi

Select/Copy the following program, coded in the Python computer language, and paste that code into a Text Editor like Notepad ... then 'SaveAs' that file with file name my_piArchimedes.py

Making sure, that you have a 3.x version of the freely available Python Interpreter installed on your PC, then, you can 'click on' ... i.e. 'run' that .py file you just saved.

Note: Python program file names end with .py


# my_piArchimedes.py # this ver. 2013-01-20 #

# This Python program needs Python version 3 (or newer version)
# installed on your PC ... to run ok

header1 = \
'''A demo program in 'Beginning Calculus' by dwzavitz

   Find perimeter/2 of inscribed regular polygon for circle radius = 1 unit
   using here an ... 'Updated Archimedes Method' ...
   that cal's sin(t/2) from sin(t) as the number of sides double each loop
   Uses sin(t/2)  = sqrt( (1 - sqrt(1 - (sin(t))^2) ) / 2 ) ... (see below)

  for regular inscribed polygon ... (for 'UNIT CIRCLE')
   _
  |_|_r=1, n=4, t/2 = 45 deg's, sin(t/2) = 1/sqrt(2), pi = 4/sqrt(2) = 2.824
   _
  / \_r=1, n=6, t/2 = 30 deg's, sin(t/2) = 0.5, s = 1, pi = n*(0.5)  = 3
  \_/
'''

header2 = \
'''Recall:
    e^(i*2*t) = cos(2*t) + i*sin(2*t)
    e^(i*2*t) = e^(i*t)^2 =  (cos(t) + i*sin(t))^2
              = (cos(t))^2 - (sin(t))^2) + i*2*sin(t)cos(t)
             
And taking 'non-i' parts to be equal ...
    cos(2*t)  = (cos(t))^2 - (sin(t))^2)

So  cos(2*t)  = 1 - 2*(sin(t))^2  ... Recall (sin(x))^2 + (cos(x))^2 = 1
So  sin(t)    = sqrt( (1 - cos(2*t) ) / 2 )
And sin(t/2)  = sqrt( (1 - cos(t) ) / 2 )
But since   ... ...        cos(t) = sqrt(1 - (sin(t))^2)
Now sin(t/2)  = sqrt( (1 - sqrt(1 - (sin(t))^2) ) / 2 )
'''

from math import * # make pi (and all math library) available in global namespace #

# above '*' char indicates to import all math functions, etc...
# and so now ... don't need 'math.xxx' math namespace name at front of 'xxxdef Perimeter( n, sin_th ):


def halfPerimeter( n, sin_th ): ## Note: (n/2 - 2*sin_th) = n * sin_th ##
    return n * sin_th


print( header1 )
input( "Press 'Enter' to continue ... " )

print( header2 )
input( "Press 'Enter' to continue ... " )

print( "Loop#    Sides sin(th/2)             " + \
       "Half Perimeter -> Area ('Unit Circle')" )   

#n = 4 ## n is number of sides to start (of inscribed regular polygon) ##
n = 6  ## Note: 6 sides was Archimedes starting number ##
#sin_th =  2**0.5/2  # start value: 4 sides and t = 90, t/2 = 45 deg's
sin_th = 0.5  # start value: 6 sides and t = 60, t/2 = 30 ...


P = 0
count = 0
while True: # loop forever until break condition below is realized #
    count += 1
    P_old = P
    P = halfPerimeter( n, sin_th )
    if count % 5 == 1:
        print( '{:2d} {:11,d} {:.15e} {:.16f}'.format(count,n,sin_th, P) )

    if P - P_old < 10**(-16): # i.e. when reach limit of 'float precision'
        break

    # double the number of sides to get ready for next loop
    n = 2*n

    # now update the sine of the next 1/2 angle when sides doubled

    #sin(t/2)  = sqrt( (1 - sqrt(1 - (sin(t))^2) ) / 2 )
    #sin_th = sqrt( (1 - sqrt(1-sin_th**2) / 2 ) #updating to sin(th/2) here#

    ## MUCH better sig dig result in PC if use this form of above ##
    ## by multiplying top and bottom of fraction by sqrt( (1+sqrt(1-sin_th**2)) ) ##
    sin_th = sin_th / 2**0.5 /sqrt( 1 + sqrt( 1- sin_th**2 ) )


print() # print a blank line ...

print( '%.16f' % pi, '<- pi (the actual value, rounded to 16 decimal places)' )
print( '%.16f %.16f <- P_old' % (P_old, P_old/pi) )
print( '%.16f %.16f <- P' % (P, P/pi) )
print( '%.16f <- (P - P_old) compared to 10**-16 = %.16f' % (P - P_old, 10**-16) )

input( "\nPress 'Enter' to continue/exit ... " )

# program output ... when run ...
'''
Press 'Enter' to continue ...
Loop#    Sides sin(th/2)             Half Perimeter -> Area ('Unit Circle')
1           6 5.000000000000000e-01 3.0000000000000000
6         192 1.636173162648678e-02 3.1414524722854611
11       6,144 5.113269070136972e-04 3.1415925166921559
16     196,608 1.597896653979543e-05 3.1415926534561005
21   6,291,456 4.993427043898358e-07 3.1415926535896590
26 201,326,592 1.560445951218302e-08 3.1415926535897896

3.1415926535897931 <- pi (the actual value, rounded to 16 decimal places)
3.1415926535897896 0.9999999999999989 <- P_old
3.1415926535897896 0.9999999999999989 <- P
0.0000000000000000 <- (P - P_old) compared to 10**-16 = 0.0000000000000001

Press 'Enter' to continue/exit ...   
'''



This next demo finds perimeter/2 of BOTH inscribed AND exscribed regular polygons ... for a circle with radius = 1 unit
(using here an ... 'Updated Archimedes  ***SQUEEZE***  Method')

# my_piArchimedes2.py # this ver. 2013-01-20 #

# This Python program needs Python version 3 (or newer version)
# installed on your PC ... to run ok


header1 = \
'''A demo program in 'Beginning Calculus' by dwzavitz

   Find perimeter/2 of inscribed regular polygon for circle radius = 1 unit

   AND perimeter/2 of EXscribed regular polygon ...
   
   using here an ... 'Updated Archimedes  ***SQUEEZE***  Method' ...
   
   that cal's sin(t/2) from sin(t) as the number of sides double each loop
   Uses sin(t/2) = sin(t)/2^0.5/sqrt( 1+sqrt(1-(sin(t))^2) ) ... (see below)
   And  tan(t/2)  =  tan(t) / (sqrt(1+(tan(t))^2)) + 1) ... (see below)

  for regular inscribed polygon ... (for 'UNIT CIRCLE')
   _
  |_|_r=1, n=4, t/2 = 45 deg's, sin(t/2) = 1/sqrt(2), pi = 4/sqrt(2) = 2.824...
   _
  / \_r=1, n=6, t/2 = 30 deg's, sin(t/2) = 0.5, s = 1, pi = n*(0.5)  = 3
  \_/ for EXscribed hexagon tan(t/2) = 1/sqrt(3),   pi  =  n/sqrt(3) = 3.464...
'''

header2 = \
'''Recall:

    e^(i*2*t) = cos(2*t) + i*sin(2*t)
    e^(i*2*t) = e^(i*t)^2 =  (cos(t) + i*sin(t))^2
              = (cos(t))^2 - (sin(t))^2) + i*2*sin(t)cos(t)
             
And taking 'non-i' parts to be equal ...
    cos(2*t)  = (cos(t))^2 - (sin(t))^2)

So  cos(2*t)  = 1 - 2*(sin(t))^2  ... Recall (sin(x))^2 + (cos(x))^2 = 1
So  sin(t)    = sqrt( (1 - cos(2*t) ) / 2 )
And sin(t/2)  = sqrt( (1 - cos(t) ) / 2 )
But since   ... ...        cos(t) = sqrt(1 - (sin(t))^2)

(So for inscribed regular polygon ...)
    sin(t/2)  = sqrt( (1 - sqrt(1 - (sin(t))^2) ) / 2 )

(And for excribed regular polygon ...)
    tan(t) = 2*tan(t/2) / ( 1 - (tan(t/2))^2 ) ... implies
    c   =   2*x / (1-x^2)  ...substituting in c = tan(t), x = tan(t/2) implies
    x = ( sqrt(1+c^c) - 1 ) / c
      = c / ( sqrt(1+c^2) +1 )  ...  implies  ...
    tan(t/2)  =  tan(t) / (sqrt(1+(tan(t))^2)) + 1)
'''

# make pi, sqrt (and all math library) available in global namespace #
from math import *

# above '*' char indicates to import all math functions, etc...
# and so now ... don't need 'math.xxx' math namespace name at front of 'xxxdef Perimeter( n, sin_th ):


def halfPerimeter( n, sin_th ): ## Note: (n/2 - 2*sin_th) = n * sin_th ##
    return n * sin_th


print( header1 )
input( "Press 'Enter' to continue ... " )

print( header2 )
input( "Press 'Enter' to continue ... " )
print()

print( "Loop#    Sides sin(th/2) / tan(th/2) " + \
       "Half Perimeter -> Area ('Unit Circle')" )   

#n = 4 ## n is number of sides to start (of inscribed regular polygon) ##
n = 6  ## Note: 6 sides was Archimedes starting number ##
#sin_th =  2**0.5/2  # start value: 4 sides and t = 90, t/2 = 45 deg's
sin_th = 0.5  # start value: 6 sides and t = 60, t/2 = 30 ...

#tan_th = 1 # for starting with exscribed square #
tan_th = 3**(-0.5) # for starting exscribed hexagon #

P = 0
count = 0
while True: # loop forever until break condition below is realized #
    count += 1
    P_old = P
    P = halfPerimeter( n, sin_th )
    Ptan = tan_th * n
    if count % 5 == 1:
        print( '{:2d} {:11,d} {:.15e} {:.16f}'.format(count,n,sin_th, P) )
        print( '{:2d} {:11,d} {:.15e} {:.16f}'.format(count,n,tan_th, Ptan) )
        print()

    if P - P_old < 10**(-16): # i.e. when reach limit of 'float precision'
        break

    # double the number of sides to get ready for next loop
    n = 2*n

    # now update the sine of the next 1/2 angle when sides doubled

    #sin(t/2)  = sqrt( (1 - sqrt(1 - (sin(t))^2) ) / 2 )
    #sin_th = sqrt( (1 - sqrt(1-sin_th**2) / 2 ) #updating to sin(th/2) here#

    ## MUCH better sig dig result in PC if use this form of above ##
    ## by multiplying top and bottom of fraction by sqrt( (1+sqrt(1-sin_th**2)) ) ##
    sin_th = sin_th / 2**0.5 /sqrt( 1 + sqrt( 1- sin_th**2 ) )

    tan_th = tan_th / (sqrt(1+tan_th**2) + 1)


#print() # print a blank line ...

print( '{:.16f} <- average of inscribed and exscribed ...'.format( (P+Ptan)/2 ) )
print( '%.16f' % pi, '<- pi (the actual value, rounded to 16 decimal places)' )


input( "\nPress 'Enter' to continue/exit ... " )

# program output ... when run ...
'''
Press 'Enter' to continue ...

Loop#    Sides sin(th/2) / tan(th/2) Half Perimeter -> Area ('Unit Circle')
1           6 5.000000000000000e-01 3.0000000000000000
1           6 5.773502691896257e-01 3.4641016151377544

6         192 1.636173162648678e-02 3.1414524722854611
6         192 1.636392213531158e-02 3.1418730499798242

11       6,144 5.113269070136972e-04 3.1415925166921559
11       6,144 5.113269738582516e-04 3.1415929273850978

16     196,608 1.597896653979543e-05 3.1415926534561005
16     196,608 1.597896654183539e-05 3.1415926538571730

21   6,291,456 4.993427043898358e-07 3.1415926535896590
21   6,291,456 4.993427043898989e-07 3.1415926535900560

26 201,326,592 1.560445951218302e-08 3.1415926535897896
26 201,326,592 1.560445951218305e-08 3.1415926535897962

3.1415926535897931 <- average of inscribed and exscribed ...
3.1415926535897931 <- pi (the actual value, rounded to 16 decimal places)

Press 'Enter' to continue/exit ...   
'''



This next Python code, takes good advantage of Pythons built in unlimited-long integers, to find pi to up 100,000 decimal places ...

Enjoy ...

# my_pi100_000places.py # this ver. 2013-01-11 #

# This file to be run under Python ver. 3 #

header = \
'''A demo program in 'Beginning Calculus' by dwzavitz
to find pi up to 100,000 decimal places
'''


# acotx = 1/x - 1/3x**3 + 1/5x**5 - 1/7x**7 + ... #
def acot( x, unity ):
    ssum = xpower = unity // x
    n = 3
    sign = -1
    count = 0
    while 1:
        xpower = xpower // (x*x)
        term = xpower // n
        if not term:
            break
        ssum += sign*term
        sign = -sign
        n += 2
        count += 1
        '''
        if count == 100000:
            print( "count = ", count )
            break
        '''

    print( "count = {:,d}".format( count ) )
    #input( "\nPress 'Enter' to continue ... " )
    return ssum

def mypi( digits ):
    unity = 10**( digits + 10 )
    # PI/4 <=  4*ACOT5 - ACOT239 #
    return 4 * ( 4 * acot( 5, unity ) - acot(239, unity) ) // 10**10



print( header )

done = False
while not done:
    s = 'Num of xxx decimal places to find in pi = 3.xxx (20 to 100000): '
    try:
        dig = int(input( s ))
        done = True
        if dig > 100000:
            done = False
            raise
        elif dig >= 30000:
            done = False
            print('{:,d}'.format(dig),"could take several seconds ... ",end = '')
            if input( "Ok (y/n) ? " ) == 'y' :
                done = True
        if dig < 20:
            dig = 20
            print( "Doing min of 20 decimal places ..." )
    except:
        print( "Invalid ... integer input <= 100,000 only please ... " )
       

import datetime
t1 = datetime.datetime.now()
tostr = str(mypi(dig)) # call mypi and convert num to str ...

print( "len(tostr)", '{:,d}'.format( len(tostr) ) )

import sys
outSave = sys.stdout
fout = open( "PI.txt", "w" )
sys.stdout = fout

print( "mypi(", dig, ")=\n", tostr[:1] + '.', sep = '' )
count = 0
for c in tostr[1:]:
    count += 1
    print( c, sep='', end='' )
    if count == 100:
        print()
        count = 0
#print()
#print( '3.\n' + '1234567890'*(dig//10) )

sys.stdout = outSave
fout.close()

t2 = datetime.datetime.now()

print( "Processing time was (time2 - time1) =", t2-t1 )

import os
os.system( 'notepad ' +  'PI.txt' )

#input( "\nPress 'Enter' to continue/exit ... " )
#37
Ask the Author / Beginning Calculus ...
January 05, 2013, 07:18:56 PM
This new thread is to help prepare students for ...

Beginning Calculus


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
(See e-mail link near bottom of first page)
http://developers-heaven.net/forum/index.php?topic=2587.0

(Note to Computer Programming Students:
Many computer programming problems require a good grasp of Calculus.  As the pages on this topic of Beginning Calculus are developed, I hope to link to several demo computer programs that require some knowledge of Calculus.)


The goal here is:

In an as simple/straightforward way as possible, and using a 'step by step build' ... to get a good foundation/grasp of Calculus ...

so as to give a 'head-start' for serious students that need to pass Calculus and then want to use it with understanding.


We will try to make good use of many existing useful Calculus 'texts' already up on the web ...

and a top-down/bottom-up 'Modular Computer Programming' style here  ...

in our attempt to avoid the too common modern science fallacy of 'circular reasoning'.

One example of this fallacy in circular reasoning, an example that needs to be actively exposed, goes something like this:

If you ask an (evolutionary) geologist, how to know that certain (sedimentary) rocks, (rocks we now know, from lab tests, are laid down by fast moving flood water, when it slows, as per 'Noah's Flood') ... if they are of a certain age ... you may be told that 'the type of fossils in that rock tells its age.'

So off you go to the (evolutionary) paleontologist and ask to know the age of those fossils, and you are told: 'The geologist has supplied me with the date of that rock.'

So ... the (evolutionary) presumption of LONG ages is 'presumed true' from the start ... here ... a fallacy.

Euclid's proofs are a 'step by step' build that are a worthy classic in logic, used by Archimedes and Newton ... and were taught even when I did my High School Geometry, all the way up to Ontario grade 13, ending June '66.

Enjoy ...

The 'top-down' goes like this ...

We will 'name and describe' some major modules right at the start, which we need to 'call' as we progress in 'running' our 'program' ... but we also must ensure that each module (and sub-module) is 'correct' and 'well built' ...

From the 'bottom up' ...

We will ensure the we build each module and sub module from appropriate 'true primitives' of our 'machine programming language', before our program is 'finished' and we expect it to run at all, let along, correctly. 


Firstly: Pre-Calculus ...


Review of basic Math, Geometry, Algebra
   
Note: e^x means 'e to the exponent x', A*e means 'A times e'

Recall 'Bedmas'  ... so exponent is calculated first ... then multiply by constant value 'A'

( So you will 'know' how to evaluate an expression like A * e^x )

'Bedmas' is a mnemonic that means first do work inside brackets, then do exponent, then do division and/or multiplication in the order they occur, then do addition and/or subtraction in the order they occur ... All these are 'binary operations' ... Input a, b ... then doing 'binary op' ... output c


Number types:


Natural counting numbers (positive integers)


Discovery of 'zero' ... (extends natural numbers to include 0)


Discovery of negative integers ... extends 'whole' number line to 'left'
(Now we can solve any equation like y = x + b, and have y, x and b ALL be (just) integers)


Discovery of rational numbers a/b, (extends base number set to include decimal fractions, with a, b in set of all integers and b != 0)
(Now we can solve any equation like y = m*x + b and have y, m, x and b ALL be (just) 'rationals')
Recall 'trick' to find a and b in rational q= a/b = 0.123123etc...

1000 * q = 123.123123...
            q = 000.123123...

Now subtract ...
So    999 * q = 123
and            q = 123/999
Thus can find integers a and b and thus we show that any repeating decimal is a rational number. 


Note!!!

Can you see now, how we are moving from discrete counts of quanta, to a continuum?

You will want to note that between any two different rational numbers, a, b with a < b, no matter how close together they might be, we can always insert the one rational, (a+b)/2, or the 9 rationals a + k*(b-a)/10 where k takes values 1 to 9 ...  And between each of these we can keep on inserting, and so on ...

We will see that Calculus helps us to find ways to evaluate, to as many decimal places of precision as desired, quantities that are 'real' ... but may NOT be 'rational' ... i.e. NOT 'ratio' of two integers!  (We already know about some such numbers like square root of 3, for example, or pi.  You may have learned an algorithm to find the square root of any decimal fraction, to as many places of decimal precision as you like, but do you know a method, like Archimedes did, over 2200 years ago, to find pi to as much precision as desired?)

http://itech.fgcu.edu/faculty/clindsey/mhf4404/Archimedes/Archimedes.html

See link to modern computer program that uses an Updated Archimedes Method of finding pi ...

http://developers-heaven.net/forum/index.php?topic=2602.0


Discovery/extension to the 'real continuum' ... i.e. the 'complete' number line to include numbers that are non repeating decimals like pi, e, sqrt(2), etc. 

Note: you may be required to prove some 'real' ... like sqrt(2) ... is not a 'rational' on an exam.

An often used method here is *proof by contradiction*
So firstly, assume 'true' and that for some integers a, b ... sqrt(2) = a/b with NO common factors
(i.e. fraction is in 'lowest terms'), then square each side and 2*b^2 = a^2 ... which implies that a^2 is 'even' ... which implies that a is 'even' (since an odd times an odd is odd) ... So ... now can re-write a as 2*c ... So substituting '2*c' in the place of 'a' ... (2*c)^2 = 4*c^2 = 2*b^2 ... And thus ... 2*c^2 = b^2 ... Which implies that b^2 and then b are even.   

So we see 'here' that both a and b must 'then' be even.   But this contradicts that a/b was in lowest terms with NO common denominator (like 2 here).  So we conclude that sqrt(2) is NOT a rational number. 

To show that a number like e is not a rational, we could show that it is a non-repeating infinite decimal sequence ... by looking at the infinite series expansion for e below:

e = 1 + 1/1! + 1/2! + 1/3! + 1/4! + ...

(Note: n! means 'n factorial' and n! = 1*2*3* .... *n
Can you see that n! becomes ever much larger as n grows larger?)

... and see that adding in the next term, in a never ending series of ever increasingly SMALL decimal bits ... ensures the next decimals in the sequence have no repeating pattern, since the new factor in the ever increasing factorial, that we next divide by, will keep adding new re-scrambled smaller bits .... 'all the way' ... out to infinity ...


Discovery/extension to 'complete' 2-Dimensional Plane via 2D vectors or z = r*e^(i*t) = r*(cos(t) + i*sin(t)) and i has the value sqrt(-1)

Above begs question(s) of what is(are) ...
e,
cos(t),
sin(t)

...


Hint:

Think of music, like a violin string vibrating, think of the the alternating current induced into an electrical circuit by a microphone near by, think of the radio wave vibrations that fill our skies, think of nerve pulse electrical activity coursing though you right now, as you read this, think of the waves on the lake as a fish jumps up and breaks through the surface ... and dives back down into the deep ...  Ah ... we are emersed in so much beautiful and intricate sine wave and exponential activity ... Don't you think?



What I am seeing myself ... and from some recent research of well seasoned Calculus Professors ... that what is especially needed as a necessary Pre-Calculus preparation ... is a good grounding in Algebra and Problem Solving with close attention to excellent skill in 'details manipulation' of even fairly complex algebra ... so as to get the correct result in the end ... and to 'know' that your answer is correct 100 % of the time, (or nearly most of the time.)

The reality to me seems ... that although the math needed in ones routine practice will soon enough become 'routine' ... the 'bar' to even get to 'practice' ... often seems 'pretty high'. 


More to follow ...


P.S.

You may be interested in what motivated Newton in his 'discovery and pursuit of the tools of calculus' ...

"The greatest Scientist of all time, Sir Isaac Newton, was also a great student of the Bible. In fact, his motivation to grind telescope lens, to better track the planets positions in the sky, to study and to discover the laws of gravity, motion and the laws of calculus that allowed him to predict, with great precision, where the planets would be in the sky, back in Bible times and into the future to our days ... was ... because he wanted to see, if he was part of that generation that would still be living when the Lord Jesus, the Anointed Holy One of Israel, would return.  However Newton came to realize, that that time was ahead, even for this present generation.  First Israel had to be become a nation again (in 1948), and then Jerusalem had to come back to Israel (in 1967), in order for all the trouble that was predicted to occur with all the nations being troubled over Jerusalem ... and then for Jesus to return, to save his people that remain, just outside Jerusalem, at the same spot He ascended into heaven about 2000 years ago."


The above 'excerpt' was taken from ...

http://developers-heaven.net/forum/index.php?topic=2587.msg2918#msg2918


P.P.S.

An other perspective from MIT ... 'The Big Picture of Calculus'

http://www.youtube.com/watch?v=UcWsDwg1XwM


Jumping in to see a very common example of applied calculus ...

http://www.dummies.com/how-to/content/how-to-analyze-position-velocity-and-acceleration-.html

http://www.mathcentre.ac.uk/resources/uploaded/mc-web-mech1-10-2009.pdf

http://www.youtube.com/watch?v=d-_eqgj5-K8


On the next page, please *NOTE THIS VERY AMAZING AND VERY USEFUL FORMULA*:

Euler showed that e^(i*pi) + 1 = 0
(Recall that i is defined as sqrt(-1) ... thus i^2 = -1 and i^4 = 1)


Also, please note this typo error, on next page here corrected
Implies ... d(C)/dr = d(pi*r)/dr = 2*pi ( where here we use notation dC/dr instead of notation C' ) <wrong version>
Implies ... d(C)/dr = d(2*pi*r)/dr = 2*pi ( where here we use notation dC/dr instead of notation C' ) <corrected version>
#38
This space is designated to hold a library of HLA vector and HLA list functions ... similar to the Cvec/Cvec2 and Clist/Clist2 library of functions available here...

http://developers-heaven.net/forum/index.php?topic=2580.0


For some example programs that demo the use of these HLA vector and list containers with their push_back, (and list push_front, and vector reserve) ... and merge sort, insert sort, find, erase, and unique functions ... see this next link ...

http://developers-heaven.net/forum/index.php?topic=2599.0


The first set of vector and list functions, permit just one type of vector or list in a program.  These pairs of include files are named:


The first pair is:

"vector_func's.hhf"
"vector.hhf"

If you include file "vector_func's.hhf" to get access to the sort, etc... functions, that file FIRSTLY includes file "vector.hhf", which firstly includes file "stdlib.hhf"




The next pair is:

"sllist_func's.hhf"
"sllist.hhf"


If you include file "sllist_func's.hhf" to get access to the sort, etc... functions, that file FIRSTLY includes file "sllist.hhf", which firstly includes file "stdlib.hhf"



Note: see the vector2/sllist2 .hhf files at the bottom also ... linked here ...

http://developers-heaven.net/forum/index.php?topic=2600.msg2978#msg2978
#39
  ~~16~
Six Fast Steps to Programming in High Level Assembly (HLA)

This series of programs and comments is a continuation of the series Six Fast Steps to Programming in C ... and ... Six Fast Steps to Programming in C++

Update!  Update: please see this next link:

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


FREE homework help NOW available via e-mail ... (or in person if in Toronto Ontario Canada region.)


The following fast paced tutorial may be of interest to new students of High Level Assembly (HLA) ...


Also now includes examples of using HLA strings with readLine, (available to you now by including my file "readLine.hhf" ... please see link to file "readLine.hhf" below), to read in dynamic HLA strings of ANY length, (length limited only by available memory).  This will add 2 more example programs, example 7. and example 8. to the 1. to 6. example HLA programs that follow.

Link for 7.
A simple example of my HLA type Vec container ... using an HLA Vec of HLA strings ...
http://developers-heaven.net/forum/index.php?topic=2599.msg2961#msg2961

Link for 8.
Using an HLA SLList type container of HLA strings ... (also demo's using 'split' line of text into a SLList of 'words')
http://developers-heaven.net/forum/index.php?topic=2599.msg2962#msg2962


Note: when you have exhausted these following pages, you may like to see vector2.hhf and list2.hhf (and func's .hhf files also) at the following link:

vector 2 link ...
http://developers-heaven.net/forum/index.php?topic=2600.0

list 2 link ...
http://developers-heaven.net/forum/index.php?topic=2600.0


The first part of this tutorial 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 assembles, and when run, asks the user to press 'Enter' to continue/exit ...

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 repeat ... until type HLA loop that calls a function 'more()' at the end of the loop

3. The next program demo's a way to get and validate user input using a FUNCTION  ... (a type of HLA procedure - one that returns a value in a register - commonly the 32 bit EAX register) ... to get valid input.

4. The next three programs progress from inputting 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.

Note: you will need to have the appropriate pair of the following custom helper files:  vector.hhf, vector_func's.hhf ... or ... sllist.hhf and sllist_func's.hhf in the same folder as the programs '5.' and '6.' that use them, to assemble the programs '5'. and '6.' that use vector_func's.hhf and sllist_func's.hhf ... Please note that a link to these 4 helper files is provided below.

Note also, that all the numeric input example programs here, find the (integer) sum and the (floating point) average value ... of the numbers input.  Please note also the use of the FPU to handle floating point numbers.  Following are links to help with using the FPU and floating point numbers (and all things HLA) ...

http://216.92.238.133/Webster/www.artofasm.com/Windows/HTML/AoATOC.html

http://216.92.238.133/Webster/www.artofasm.com/Windows/HTML/RealArithmetic.html#998833

Please use this next link to access all things 'HLA" ...

http://216.92.238.133/Webster/

You may also like to see the SLOWER PACED beginning steps at this next link to  ...

BEGINNING COMPUTER PROGRAMMING USING HLA

https://docs.google.com/document/pub?id=1axLRopTi6Qb7ky_Er-IokvtkuneJMYqZAow8Ldas2t0


Or look here for some other programming links, etc ...

http://secureservices.ca

A student goal (and reward) here may be simply expressed like this ...

After the student has understood these examples, that student may then readily handle ... IN HLA ... many common beginner student type data processing problems ... with much of the same ease of using the C++ STL vector and list containers and the C++ STL support functions.
#40


These following pages will be about a way to use void pointers and function pointers in C  ... to demonstrate how they might be used together to emulate/provide the functionality in C of the C++ vector and list containers.

Previously, (see the following links),

http://developers-heaven.net/forum/index.php?topic=2580.0

http://developers-heaven.net/forum/index.php?topic=2582.0

using Cvec.h and Clist.h and function pointers, but NOT void pointers, we provided this functionality, but it was some-what limited ... limited to just one type of vector and one type of list per program ... for example ... we could not have in the same program, a vector of doubles and also a vector of an other type ... we needed to make one a list and the other a vector container.  Also, we could not have a vector of vector ... or a list of list ... only allowed then, (in the same program), was a vector of list ... or a list of vector.

But with the added use of the void pointers below, we can now accommodate, in the same program, as many types of vectors and/or lists as needed, just like in C++ ... also you now can code for a vector of vector ... or a list of list ... just like in C++

Firstly, take a look at the new Cvec2.h file and the new Cvec2_func's.h file ... also the slightly augmented files readLine.h and readWord.h, with an added function now with prototype:  char* newMem( int bytes );

/* Cvec2.h */  /* this version 2015-06-15 */

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

/*
    TO USE ... you will need to define / typedef (struct) some record structure
    for example:  typedef a struct/node/element/record as Rec ...
    and define freeVrec( void* r ); ... so can call freeVrec( cv->ary +i*cv->elen );
    SEE EXAMPLES at bottom ...
*/
                           
#ifndef dwCvec2_H
#define dwCvec2_H

#ifndef debug_dwCvec2_H
#define debug_dwCvec2_H 0   /* set debug default to 'off' ...*/
#endif

#ifndef dwREADLINE_H
#include "readLine.h" /* includes stdio.h, stdlib.h, string.h, ctype.h, etc */
#endif

/* #include <stdlib.h> // re. realloc */
/* #include <string.h> // re. memcopy */

/* re-set this starting num of rec's to minimize realloc's */
#ifndef VEC_CHUNK_SIZE
#define VEC_CHUNK_SIZE 8
#endif

typedef struct myCvec
{
    void* ary;
    int elen;
    int size;
    int cap;
} Cvec;

void initCvec( Cvec* cv, int el_size )
{
    cv->ary = NULL;
    cv->elen = el_size;
    cv->cap  = cv->size = 0;
}

void clearCvec( Cvec* cv, void (*freeVrec) (void* el) )
{
    if( cv->size )
    {
        int i;
        for( i = cv->size-1; i >= 0; --i )
            freeVrec(  (char*)cv->ary + i * cv->elen  );
#if debug_dwCvec2_H
        printf( "Inside clearCvec at free( cv->ary ) = %p\n",  cv->ary );
#endif
        free( cv->ary );
        initCvec( cv, cv->elen );
    }
}


/* new array to hold 2x's records ... copies old to new */
void enlargeCvec( Cvec* cv )
{
    void* tmp;
    if( cv->cap ) cv->cap += cv->cap; /* double capacity ... */
    else cv->cap = VEC_CHUNK_SIZE; /* set initial capacity */
    tmp = realloc( cv->ary, cv->cap * cv->elen );
    if( tmp == NULL )
    {
        myAssert( 0, "Error: realloc failed in enlargeCvec..." );
    }
    /* else ... */
    cv->ary = tmp; /* update the base address of cv->ary */
}


void reserveCvec( Cvec* cv, int newCap )
{
    if( newCap > cv->cap )
    {
        void* tmp;
        cv->cap = newCap;
        tmp = realloc( cv->ary, cv->cap * cv->elen );
        if( tmp == NULL )
        {
            myAssert( 0, "Error: realloc failed in reserveCvec..." );
        }
        /* else ... */
        cv->ary = tmp; /* update the base address of cv->ary */
    }
}

void push_backCvec( Cvec* cv, void* el )
{
    if( cv->size == cv->cap ) enlargeCvec( cv );
    /* now add in new Rec ... */
    memcpy( ((char*)cv->ary + cv->size*cv->elen), el, cv->elen );
    ++ cv->size;
}

#endif

/*

typedef struct myStudent
{
    char* name;
    int id;
} Student ;


void freeStudent( void* el )
{
    Student* p = (Student*) el;
    free( p->name );
}

typedef struct myStudent2
{
    char* fname;
    char* lname;
    int id;
} Student2 ;


void freeStudent2( void* el )
{
    Student2* p = (Student2*) el;
    free( p->lname );
    free( p->fname );
}


void showStudent( const Student* s )
{
    printf( "%s %d", s->name, s->id );
}
void showCvec( const Cvec* s )
{
    int i;
    for( i = 0; i < s->size; ++i )
        { showRec( (Student*)s->ary + i ); putchar( '\n' ); }
}

void showStudent2( const Student2* s )
{
    printf( "%s, %s :: %d", s->lname, s->fname, s->id );
}
void showCvec2( const Cvec* s )
{
    int i;
    for( i = 0; i < s->size; ++i )
        { showStudent2( (Student2*)s->ary + i ); putchar( '\n' ); }
}

*/



And now the file Cvec2_func's.h ...

/* Cvec2_func's.h */  /* 2015-06-15 */

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

/*
    this ver:   using function pointers ...
                msortCvec, isortCvec, isSortedCvec, UniqueCvec,
                isUniqueCvec, findCvec, eraseCvec (i.e. find/erase Rec)
*/

#ifndef dwCvec2_funcs_H
#define dwCvec2_funcs_H

#ifndef dwCvec2_H
#include "Cvec2.h"
#endif

void mergeCvec( Cvec* cv, int bot, int top, Cvec* tmp,
                int (*myCmp) (const void* a, const void* b) )
{
    int mid = (bot+top)/2;
    int sz = top - bot + 1;   /* size of the range to be merged */
    int j = 0;                /* next open index in tmp */
    int h1 = bot;             /* next index to consider in the 1st half */
    int h2 = mid + 1;         /* next index to consider in the 2nd half */

    /* while indexes h1 and h2 are not past their ends ... */
    while( h1 <= mid && h2 <= top )
    {   /* move the smaller element into the tmp vec next ... */
        if( myCmp( ((char*)cv->ary + h1*cv->elen), ((char*)cv->ary + h2*cv->elen) ) <= 0  )
            memcpy( ((char*)tmp->ary + cv->elen*j++), ((char*)cv->ary + cv->elen*h1++), cv->elen );
            /* tmp->ary[j++] = cv->ary[h1++]; */
        else
            memcpy( ((char*)tmp->ary + cv->elen*j++), ((char*)cv->ary + cv->elen*h2++), cv->elen );
            /* tmp->ary[j++] = cv->ary[h2++]; */
    }
    /* Note: only one, at most, of the two 'while's' below is executed ... */
    while( h1 <= mid ) /* copy any remaining entries (1st half) */
        memcpy( ((char*)tmp->ary + cv->elen*j++), ((char*)cv->ary + cv->elen*h1++), cv->elen );
        /* tmp->ary[j++] = cv->ary[h1++]; */
    while( h2 <= top ) /* copy any remaining entries (2nd half) */
        memcpy( ((char*)tmp->ary + cv->elen*j++), ((char*)cv->ary + cv->elen*h2++), cv->elen );
        /* tmp->ary[j++] = cv->ary[h2++]; */

    for( j = 0; j < sz; ++j ) /* copy back sorted tmp vec... */
        memcpy( ((char*)cv->ary +(bot+j)*cv->elen), ((char*)tmp->ary + j*cv->elen), cv->elen );
        /* cv->ary[bot+j] = tmp->ary[j]; */
}
void my_msortCvec( Cvec* cv, int bot, int top, Cvec* tmp,
               int (*myCmp) (const void* a, const void* b) )
{
    if( bot == top ) return;
    else
    {
        int mid = ( bot + top ) / 2;
        my_msortCvec( cv, bot, mid, tmp, myCmp );   /* sort the first ... */
        my_msortCvec( cv, mid+1, top, tmp, myCmp ); /* and the second half */
        mergeCvec( cv, bot, top, tmp, myCmp );      /* now merge 2 sorted chunks */
    }
}
/* *NOTE* Calling msortCvec sets the returned by ref Cvec to *** isSorted *** */
void msortCvec( Cvec* cv, int (*myCmp) (const void* a, const void* b) )
{
    if( cv->size > 1 )
    {
        Cvec tmp;
        initCvec( &tmp, cv->elen );
        reserveCvec( &tmp, cv->size ); /* Note: resets cap, BUT size still 0 */
        my_msortCvec( cv, 0, cv->size-1, &tmp, myCmp );
        free( tmp.ary ); /* only free ary mem that held copies of pointers */
    }
}


void isortCvec( Cvec* cv, int (*myCmp) (const void* a, const void* b) )
{
    int i, j;
    void* cmp = (void*) newMem( cv->elen );
    for( i = 1; i < cv->size; ++i ) /* start with an array of just the first 2 elements (if exists) */
    {
        memcpy( cmp, ((char*)cv->ary + i*cv->elen), cv->elen ); /* get copy of this new cmp pointer on each outer loop ... */
        j = i-1; /* get index of element just to the left of the above 'cmp' to start comparisons */
        while( j >= 0 && myCmp(cmp, ((char*)cv->ary+cv->elen*j)) < 0 )
        {
            memcpy( ((char*)cv->ary + cv->elen*(j+1)), ((char*)cv->ary + cv->elen*j), cv->elen ); /* copy pointer 'up' ... */
            --j; /* decrement j in preparation for next inner loop ... */
        }
        memcpy( ((char*)cv->ary + cv->elen*(j+1)), cmp, cv->elen ); /* insert pointer at index j+1 (since j was decremented above) */
    }
    free( cmp );
} /* size hasn't changed ... */


int isSortedCvec( Cvec* cv, int (*myCmp) (const void* a, const void* b) )
{
    int size = cv->size;
    while( --size )
        if( myCmp( ((char*)cv->ary + cv->elen*(size)), ((char*)cv->ary + cv->elen*(size-1)) )
            < 0 ) return 0;
    return 1;
}


void uniqueCvec( Cvec* cv, int (*myCmp) (const void* a, const void* b),
                 void (*freeVrec) (void* el) )
{
    int i = 0, j = 1;
    if( !isSortedCvec( cv, myCmp ) )
        msortCvec( cv, myCmp ); /* first make sure, name-sorted order by case */

    for( ; j < cv->size ; ++j )
    {
        if( myCmp( ((char*)cv->ary + cv->elen*i), ((char*)cv->ary + cv->elen*j) ) != 0 )
        {
            ++i;
            if( i != j ) memcpy( ((char*)cv->ary + cv->elen*i), ((char*)cv->ary + cv->elen*j),
                                  cv->elen );
        }
        else freeVrec( (char*)cv->ary + cv->elen*j );
    }

    cv->size = ++i;
}
int isUniqueCvec( Cvec* cv, int (*myCmp) (const void* a, const void* b) )
{
    int i;
    if( !isSortedCvec( cv, myCmp ) )
        msortCvec( cv, myCmp );

    for( i = cv->size-1; i > 0; --i )
        if( myCmp( ((char*)cv->ary + cv->elen*i), ((char*)cv->ary + cv->elen*(i-1)) ) == 0 )
            return 0;
    /* else ... */
    return 1;
}

/* returns index if string present, else -1 */
int findCvec( Cvec* cv, const void* rec, int (*myCmp) (const void* a, const void* b) )
{
    int i;
    for( i = 0; i < cv->size; ++i )
        if( myCmp( ((char*)cv->ary + cv->elen*i), rec ) == 0 ) return i;
    /* else if reach here ... */
    return -1;
}

/* if int index valid, erases element there */
void eraseCvec( Cvec* cv, int index, void (*freeVrec) (void* el) )
{
    /* int i; */
    if( index < 0 || index >= cv->size )
        { printf( "\nERROR! Index %d out of range 0..%d\n", index, cv->size-1 );
          return; }

    freeVrec( (char*)cv->ary + cv->elen*index ); /* needed here for dynamic memory types */

    /* copy each (set of pointers above) down one index */
    /* for( i = index; i < cv->size-1; ++i ) */
        /* memcpy(&cv->ary[i], &cv->ary[i+1], sizeof(Rec)); */
    if( index < cv->size-1 )
        memcpy( ((char*)cv->ary + cv->elen*index), ((char*)cv->ary + cv->elen*(index+1)),
                (cv->size-1-index)*cv->elen);

    /* now update size and return (by reference, since address passed in) */
    -- cv->size;
}

#endif



Now the new readLine.h

See this link for latest version:

http://developers-heaven.net/forum/index.php/topic,2580.msg2864.html#msg2864