And finally, this is the NEW version ... with FUNCTION POINTERS ... to handle C vectors (Cvec) of any struct you make ...
At the top, include stdio.h, stdlib.h, string.h ... (Note: these are all included if you include the file readLine.h or the file readWord.h)
And then ...you will first need to typedef your struct ... Rec and define your freeVrec functions (as above) ...
Also ... #include "Cvec.h"
Then you can ... #include "Cvec_func's.h"
Also ... you will need to define your compare Rec function(s) ... before your call ...
/* your compare function prototype(s) looks like this */
int myCompare( const Rec* a, const Rec* b );
/* Cvec_func's.h */ /* 2016-10-07 */
/*
this ver: using function pointers ...
msortCvec, isortCvec, isSortedCvec, UniqueCvec,
isUniqueCvec, findCvec, eraseCvec (i.e. erase Rec)
*/
#ifndef dwCvec_funcs_H
#define dwCvec_funcs_H
/* function protoypes ...*/
void mergeCvec( Cvec* cv, int bot, int top, Cvec* tmp,
int (*myCmp) (const Rec* a, const Rec* b) );
void my_msortCvec( Cvec* cv, int bot, int top, Cvec* tmp,
int (*myCmp) (const Rec* a, const Rec* b) );
void msortCvec( Cvec* cv, int (*myCmp) (const Rec* a, const Rec* b) );
void isortCvec( Cvec*, int (*myCmp) (const Rec* , const Rec*) );
int isSortedCvec( Cvec*, int (*myCmp) (const Rec*, const Rec*) );
void uniqueCvec( Cvec*, int (*myCmp) (const Rec*, const Rec*) );
int isUniqueCvec( Cvec* cv, int (*myCmp) (const Rec* a, const Rec* b) );
/* returns index if string present, else -1 */
int findCvec( Cvec*, const Rec*, int (*myCmp) (const Rec*, const Rec*) );
/* if int index valid, erases element there ... ( Note: --size but same cap ) */
void eraseCvec( Cvec*, int );
/* function definitions ...*/
void mergeCvec( Cvec* cv, int bot, int top, Cvec* tmp,
int (*myCmp) (const Rec* a, const Rec* 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( &(cv->ary[h1]), &(cv->ary[h2]) ) <= 0 )
tmp->ary[j++] = cv->ary[h1++];
else
tmp->ary[j++] = cv->ary[h2++];
}
/* Note: only one of the two 'while's' below is executed ... */
while( h1 <= mid ) /* copy any remaining entries (1st half) */
tmp->ary[j++] = cv->ary[h1++];
while( h2 <= top ) /* copy any remaining entries (2nd half) */
tmp->ary[j++] = cv->ary[h2++];
for( j = 0; j < sz; ++j ) /* copy back sorted tmp vec... */
cv->ary[bot+j] = tmp->ary[j];
}
void my_msortCvec( Cvec* cv, int bot, int top, Cvec* tmp,
int (*myCmp) (const Rec* a, const Rec* 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 Rec* a, const Rec* b) )
{
if( cv->size > 1 )
{
Cvec tmp;
initCvec( &tmp );
reserveCvec( &tmp, cv->size ); /* Note: resets cap, BUT size still 0 */
my_msortCvec( cv, 0, cv->size-1, &tmp, myCmp );
cv->isSorted = 1;
free( tmp.ary ); /* only free ary mem that held copies of pointers */
}
}
int isSortedCvec( Cvec* cv, int (*myCmp) (const Rec* a, const Rec* b) )
{
int size = cv->size;
while( --size )
if( myCmp(&cv->ary[size], &cv->ary[size-1]) < 0 ) return 0;
return 1;
}
void uniqueCvec( Cvec* cv, int (*myCmp) (const Rec* a, const Rec* b) )
{
if( cv->size > 1 )
{
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( &cv->ary[i], &cv->ary[j] ) != 0 )
{
++i;
if( i != j ) memcpy( &cv->ary[i], &cv->ary[j], sizeof(Rec) );
}
else clearRec( &cv->ary[j] );
}
cv->size = ++i;
}
}
int isUniqueCvec( Cvec* cv, int (*myCmp) (const Rec* a, const Rec* b) )
{
int i;
if( !cv->isSorted ) msortCvec( cv, myCmp );
for( i = cv->size-1; i > 0; --i )
if( myCmp( &cv->ary[i], &cv->ary[i-1] ) == 0 ) return 0;
/* else ... */
return 1;
}
/* returns index if string present, else -1 */
int findCvec( Cvec* cv, const Rec* r, int (*myCmp) (const Rec* a, const Rec* b) )
{
int i;
for( i = 0; i < cv->size; ++i )
if( myCmp(&cv->ary[i], r) == 0 ) return i;
/* else if reach here ... */
return -1;
}
/* if int index valid, erases element there */
void eraseCvec( Cvec* cv, int index )
{
/* int i; */
if( index < 0 || index >= cv->size )
{ printf( "\nERROR! Index %d out of range 0..%d\n", index, cv->size-1 );
return; }
clearRec( &(cv->ary[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(&cv->ary[index], &cv->ary[index+1], (cv->size-1-index)*sizeof(Rec));
/* now update size and return (by reference, since address passed in) */
-- cv->size;
}
void isortCvec( Cvec* cv, int (*myCmp) (const Rec* a, const Rec* b) )
{
int i, j;
Rec cmp;
for( i = 1; i < cv->size; ++i ) /* start with an array of just the first 2 elements (if exists) */
{
memcpy( &cmp, &cv->ary[i], sizeof(Rec) ); /* 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, &cv->ary[j]) < 0 )
{
memcpy( &cv->ary[j+1], &cv->ary[j], sizeof(Rec) ); /* copy pointer 'up' ... */
--j; /* decrement j in preparation for next inner loop ... */
}
memcpy( &cv->ary[j+1], &cmp, sizeof(Rec) ); /* insert pointer at index j+1 (since j was decremented above) */
}
cv->isSorted = 1;
} /* size hasn't changed ... */
#endif