/* Cvec.h */ /* this version 2016-10-09 */
/*
BEFORE loading ... you MUST FIRST typedef (struct) Rec ...
i.e. typedef a struct/node/element/record as Rec ...
and define clearRec( Rec* r ); ... so can call clearRec( &(cv->ary[i]) );
*/
#ifndef dwCvec_H
#define dwCvec_H
/* #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
{
Rec* ary;
int size;
int cap; /* capacity*/
int isSorted;
} Cvec;
/* with these, an address is passed, so NO copy made and/or original updated */
void initCvec( Cvec* ); /* sets ary to NULL and size, cap to 0 and isSorted to 1 */
void push_backCvec( Cvec*, Rec* );
void enlargeCvec( Cvec* );
void reserveCvec( Cvec*, int );
void clearCvec( Cvec* );
void initCvec( Cvec* cv )
{
cv->ary = NULL;
cv->size = cv->cap = 0;
cv->isSorted = 1;
}
void push_backCvec( Cvec* cv, Rec* rc )
{
if( cv->size == cv->cap ) enlargeCvec( cv );
/* now add in new Rec ... */
memcpy( &(cv->ary[cv->size]), rc, sizeof(Rec) );
/*
cv->ary[cv->size].name = rc->name;
cv->ary[cv->size].address = rc->address;
cv->ary[cv->size].phone = rc->phone;
*/
++ cv->size;
cv->isSorted = 0;
}
/* 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 * sizeof(Rec) );
if( tmp == NULL )
{
clearCvec( cv );
myAssert( 0, "Error: realloc failed in enlargeCvec..." );
}
/* else ... */
cv->ary = (Rec*) 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 * sizeof(Rec) );
if( tmp == NULL )
{
clearCvec( cv );
myAssert( 0, "Error: realloc failed in reserveCvec..." );
}
/* else ... */
cv->ary = (Rec*) tmp; /* update the base address of cv->ary */
}
}
void clearCvec( Cvec* cv )
{
if( cv->size )
{
int i;
for( i = cv->size-1; i >= 0; --i )
clearRec( &(cv->ary[i]) );
free( cv->ary );
initCvec( cv );
}
}
#endif
/* CvecOfInt.h */ /* this version: 2016-10-07 */
/*
this version with added isortCvec (still has msortCvec)
also added isSorted, uniqueCvec, isUniqueCvec, sumCvec, findCvec, eraseCvec
*/
#ifndef dwCvecOfInt_H
#define dwCvecOfInt_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* re. memcpy */
#ifndef myType
#define myType int
#endif
typedef struct
{
myType val;
} Rec ;
void clearRec( Rec* rc )
{
/* empty here ... since no dynamic memory (as in Cstring) to free ... */
rc = rc; /* to keep compiler warning nessage supressed ,,, */
}
#ifndef dwMYASSERT
#define dwMYASSERT
void myAssert( int condition, const char text[] )
{
if( !condition )
{
fprintf(stderr, "%s\n", text );
fputs( "Press 'Enter' to exit program ... ", stderr );
getchar();
exit(1);
}
}
#endif
/* Ok ... NOW can include ... */
#include "Cvec.h"
/* needs stdlib.h, string.h and myAssert & all included above */
/* and these ...*/
void mergeCvec( Cvec*, int, int, int, Cvec* );
void my_msort( Cvec*, int, int, Cvec* );
void msortCvec( Cvec* );
int isSortedCvec( Cvec* );
myType sumCvec( Cvec* );
/* void showCvec( Cvec* ); */
int findCvec( Cvec*, myType ); /* returns index if int value present, else -1 */
void eraseCvec( Cvec*, int ); /* if int index valid, erases element there */
void isortCvec( Cvec* );
void uniqueCvec( Cvec* cv );
int isUniqueCvec( Cvec* cv );
/* * * * * * * * * * * * * * * * mergeCvec sort * * * * * * * * * * * * * * * * * */
void mergeCvec( Cvec* cv, int bot, int mid, int top, Cvec* tmp )
{
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... */
if( cv->ary[h1].val < cv->ary[h2].val ) tmp->ary[j++].val = cv->ary[h1++].val;
else tmp->ary[j++].val = cv->ary[h2++].val;
}
/* Note: only one of the two while loops below is executed ... */
while( h1 <= mid ) tmp->ary[j++].val = cv->ary[h1++].val; /* copy any remaining entries (1st half) */
while( h2 <= top ) tmp->ary[j++].val = cv->ary[h2++].val; /* copy any remaining entries (2nd half) */
for( j = 0; j < sz; ++j ) cv->ary[bot+j].val = tmp->ary[j].val; /* copy back sorted tmp vec... */
}
void my_msort( Cvec* cv, int bot, int top, Cvec* tmp )
{
if( bot == top ) return;
else
{
int mid = ( bot + top ) / 2;
my_msort( cv, bot, mid, tmp ); /* sort the first ... */
my_msort( cv, mid + 1, top, tmp ); /* and the second half ...*/
mergeCvec( cv, bot, mid, top, tmp ); /* now mergeCvec these 2 sorted chunks ... */
}
}
void msortCvec( Cvec* cv )
{
if( cv->size > 1 )
{
Cvec tmp;
initCvec( &tmp );
reserveCvec( &tmp, cv->size );
my_msort( cv, 0, cv->size-1, &tmp );
cv->isSorted = 1;
free( tmp.ary ); /* only free ary mem that held copies of pointers */
}
}
int isSortedCvec( Cvec* cv )
{
int size = cv->size;
while( --size )
if( cv->ary[size].val < cv->ary[size-1].val ) return 0;
return 1;
}
myType sumCvec( Cvec* cv )
{
myType sum = 0;
int i;
for( i = cv->size -1; i >= 0; --i ) sum += cv->ary[i].val;
return sum;
}
/*
void showCvec( Cvec* cv ) // valid here only for int's ...
{
int i;
for( i = 0; i < cv->size; ++i ) printf( "%d ", cv->ary[i].val );
}
*/
int findCvec( Cvec* cv, myType value ) /* returns index if present ... else -1 */
{
int i;
for( i = 0; i < cv->size; ++i )
if( cv->ary[i].val == value ) return i;
/* else if reach here ... */
return -1;
}
void eraseCvec( Cvec* cv, int index ) /* if index valid, erases element there */
{
/* int i; */
if( index < 0 || index >= cv->size )
{ printf( "\nERROR! Index %d out of range 0..%d\n", index, cv->size-1 );
return; }
/*
// for( i = index; i < cv->size-1; ++i ) */
/* //{ */ /* copy each element above, down one index, so 'index' value 'erased' */
/* // cv->ary[i].val = cv->ary[i+1].val;
//}
*/
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 i, j;
for( i = 1; i < cv->size; ++i ) /* start with an array of just the first 2 elements (if exists) */
{
myType cmp = cv->ary[i].val; /* get copy of this new cmp element 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 && cmp < cv->ary[j].val )
{
cv->ary[j+1].val = cv->ary[j].val; /* copy element 'up' ... */
--j; /* decrement j in preparation for next inner loop ... */
}
cv->ary[j+1].val = cmp; /* insert element at index j+1 (since j was decremented above) */
}
cv->isSorted = 1;
}
void uniqueCvec( Cvec* cv )
{
int i = 0, j = 1;
if( !cv->isSorted ) msortCvec( cv );
for( ; j < cv->size ; ++j )
{
if( cv->ary[i].val != cv->ary[j].val )
{
++i;
if( i != j ) cv->ary[i].val = cv->ary[j].val;
}
/* else
freeRec( &cv->ary[j] ); // NOT needed since NO dynamic memory // */
}
cv->size = ++i;
}
int isUniqueCvec( Cvec* cv )
{
int i;
if( !cv->isSorted ) msortCvec( cv );
for( i = cv->size-1; i > 0; --i )
if( cv->ary[i].val == cv->ary[i-1].val ) return 0;
/* else ... */
return 1;
}
#endif
/* readLine.h */ /* this version: 2016-10-08 */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
/*
Safe string data entry from file ... to replace gets and fgets
BUT free new memory ... when done! Don't forget that C strings are
pointers to a block of char, with a '\0' char at the terminal end ...
Call like this:
char* line = readLine( stdin );
or ...
while( (line = readLine( FILEp )) )
{
// process line ...
}
*/
/* includes stdio.h, stdlib.h, string.h, ctype.h with myAssert, newMen, newCopy and newSubStr functions */
#ifndef dwREADLINE_H
#define dwREADLINE_H
/* can re-set/adjust here to best match your line-length */
#ifndef LINECHUNK
#define LINECHUNK 256
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h> /* re. isspace in trim ... */
#ifndef dwMYASSERT
#define dwMYASSERT
void myAssert( int condition, const char text[] )
{
if( !condition )
{
fprintf(stderr, "%s\n", text );
fputs( "Press 'Enter' to exit program ... ", stderr );
getchar();
exit(1);
}
}
#endif
#ifndef dwNEWMEMORY
#define dwNEWMEMORY
char* newMem( int bytes )
{
char* n = (char*)malloc( bytes ); /* cast for C++ compilers */
myAssert( (n != NULL), "Error: malloc failed in 'newMem' ... " );
return n;
}
#endif
#ifndef dwNEWCOPY
#define dwNEWCOPY
char* newCopy( const char* str )
{
char* n = newMem( strlen(str) + 1 ); /* cast for C++ compilers */
strcpy( n, str );
return n;
}
#endif
#ifndef dwNEWSUBSTR
#define dwNEWSUBSTR
char* newsubstr( const char* str, int beg, int len )
{
char* n = newMem( len + 1 ); /* cast for C++ compilers */
strncpy( n, str+beg, len );
n[len] = 0;
return n;
}
#define newSubStr newsubstr
#endif
#ifndef dwTRIM
#define dwTRIM
char* trim( char* s )
{
char *start = s, *end = s;
while( *end ) ++end ;
if( end == s ) return s; /* empty string */
for( --end; s <= end && isspace(*end); --end ) ;
end[1] = 0;
while( isspace(*s) ) ++s;
memmove( start, s, (end+2-s) ); /* 2 ... to copy terminal 0 */
return start;
}
char* rtrim( char* s )
{
char* end = s;
while( *end ) ++end ;
if( end == s ) return s; /* empty string */
for( --end; s <= end && isspace(*end); --end ) ;
end[1] = 0;
return s;
}
char* ltrim( char* s )
{
char *start = s, *end = s;
while( *end ) ++end ;
if( end == s ) return s; /* empty string */
while( isspace(*s) ) ++s;
memmove( start, s, (end+1-s) ); /* 1 ... to copy terminal 0 */
return start;
}
#define strip trim
#define lstrip ltrim
#define rstrip rtrim
#endif
#ifndef dwUPDOWN
#define dwUPDOWN
char* strToUpper( char* str )
{
char* p = str;
while( *p != 0 ) { *p = toupper(*p); ++p; }
return str;
}
char* strToLower( char* str )
{
char* p = str;
while( *p != 0 ) { *p = tolower(*p); ++p; }
return str;
}
char* strToUpperFirstLetter( char* str )
{
if( str && strlen(str) )
str[0] = toupper(str[0]);
return str;
}
char* strToTitleCase( char* str )
{
char* p = strToLower(str);
char prev = ' ';
while( *p )
{
if( isspace(prev) ) *p = toupper( *p );
prev = *p;
++p;
}
return str;
}
#endif
#ifndef dwTAKE_IN_CHAR_MORE
#define dwTAKE_IN_CHAR_MORE
/* a handy utility for many C student coding problems ... */
char takeInChar( const char* msg )
{
char chr;
printf( msg ); fflush( stdout );
chr = getchar();
if( chr != '\n' ) while( getchar() != '\n' ) ; /* flush stdin ... */
return chr;
}
int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
if( tolower( takeInChar( "More (y/n) ? " )) == 'n' ) return 0;
/* else ... */
return 1;
}
#endif
/* returns a string in new memory holding each word ... or NULL if EOF */
char* readLine( FILE* fp )
{
int c, cap = LINECHUNK, size = 0; /* c to hold each char ... */
void* tmp;
char* strData = (char*) malloc( cap ); /* cast for C++ compilers ... */
myAssert( (strData != NULL), "Error: malloc failed at top of 'readLine' ... " );
while( (c = fgetc(fp)) != '\n' && c != EOF )
{
if( size == cap-1 ) /* skip while size < cap-1 */
{
cap += cap; /* double memory capacity ... */
if( (tmp = realloc(strData, cap)) == NULL )
{
free(strData);
myAssert( 0, "Error: realloc failed in 'readLine' ... " );
}
/* else ... good realloc above, so update strData pointer */
strData = (char*) tmp;
}
/* now ... since reached here ... */
strData[size++] = c; /* append this char ... */
}
strData[size] = 0; /* '\0' terminate */
if( c == EOF && strData[0] == 0 ) { free(strData); return NULL; }
/* else ... since didn't return NULL above, compact string to right-size */
if( (tmp = realloc(strData, size+1)) == NULL ) /* size+1 to hold 0 at end */
{
free(strData);
myAssert( 0, "Error: realloc failed in compacting C string ... " );
}
return (char*) tmp; /* return the string with NO extra capacity ... */
}
#endif
/* readWord.h */ /* this ver 2016-10-09 */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
/*
Safe string data entry from file or keyboard ...
BUT ... free new memory when done with it!
Don't forget that C strings are pointers to a block of char,
with a '\0' char at the terminal end ... Call like this:
char* word = readWord(stdin, 31, "\n\t ,.;:", &lastChr);//note delimiter str
or ...
while((word = readWord(FILEp, startChunkSize, delimiterStr, &lastCharRead)))
{
// do stuff ...
}
Note 1: select your initial word chunk size to minimize calls to realloc
Note 2: address of last char passed in/out so can flush stdin or file line
*/
#ifndef dwREADWORD_H
#define dwREADWORD_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* re. strchr */
#include <ctype.h> /* re. isspace in trim ... */
#ifndef dwMYASSERT
#define dwMYASSERT
void myAssert( int condition, const char text[] )
{
if( !condition )
{
fprintf(stderr, "%s\n", text );
fputs( "Press 'Enter' to exit program ... ", stderr );
getchar();
exit(1);
}
}
#endif
#ifndef dwNEWMEMORY
#define dwNEWMEMORY
char* newMem( int bytes )
{
char* n = (char*) malloc( bytes ); /* cast for C++ compilers */
myAssert( (n != NULL), "Error: malloc failed in 'newMem' ... " );
return n;
}
#endif
#ifndef dwNEWCOPY
#define dwNEWCOPY
char* newCopy( const char* str )
{
char* n = newMem( strlen(str) + 1 ); /* cast for C++ compilers */
strcpy( n, str );
return n;
}
#endif
#ifndef dwNEWSUBSTR
#define dwNEWSUBSTR
char* newsubstr( const char* str, int beg, int len )
{
char* n = newMem( len + 1 ); /* cast for C++ compilers */
strncpy( n, str+beg, len );
n[len] = 0;
return n;
}
#endif
#ifndef dwTRIM
#define dwTRIM
char* trim( char* s )
{
char *start = s, *end = s;
while( *end ) ++end ;
if( end == s ) return s; /* empty string */
for( --end; s <= end && isspace(*end); --end ) ;
end[1] = 0;
while( isspace(*s) ) ++s;
memmove( start, s, end+2-s ); /* 2 ... to copy terminal 0 */
return start;
}
char* rtrim( char* s )
{
char* end = s;
while( *end ) ++end ;
if( end == s ) return s; /* empty string */
for( --end; s <= end && isspace(*end); --end ) ;
end[1] = 0;
return s;
}
char* ltrim( char* s )
{
char *start = s, *end = s;
while( *end ) ++end ;
if( end == s ) return s; /* empty string */
while( isspace(*s) ) ++s;
memmove( start, s, end+1-s ); /* 1 ... to copy terminal 0 */
return start;
}
#endif
#ifndef dwUPDOWN
#define dwUPDOWN
char* strToUpper( char* str )
{
char* p = str;
while( *p != 0 ) { *p = toupper(*p); ++p; }
return str;
}
char* strToLower( char* str )
{
char* p = str;
while( *p != 0 ) { *p = tolower(*p); ++p; }
return str;
}
char* strToUpperFirstLetter( char* str )
{
if( str && strlen(str) )
str[0] = toupper(str[0]);
return str;
}
char* strToTitleCase( char* str )
{
char* p = strToLower(str);
char prev = ' ';
while( *p )
{
if( isspace(prev) ) *p = toupper( *p );
prev = *p;
++p;
}
return str;
}
#endif
#ifndef dwTAKE_IN_CHAR_MORE
#define dwTAKE_IN_CHAR_MORE
/* a handy utility for many C student coding problems ... */
char takeInChar( const char* msg )
{
char chr;
printf( msg ); fflush( stdout );
chr = getchar();
if( chr != '\n' ) while( getchar() != '\n' ) ; /* flush stdin ... */
return chr;
}
int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
if( tolower( takeInChar( "More (y/n) ? " )) == 'n' ) return 0;
/* else ... */
return 1;
}
#endif
/* returns a string into new memory to hold each word ...
or NULL if EOF */
char* readWord( FILE* fp, int chunk_len, const char delimits[], char* c)
{
char *strData, *tmp;
int i = 0; /* i for index in string, *c to hold each char */
if( chunk_len < 4 )
chunk_len = 4; /* set to min. starting chunk size */
else if( chunk_len %4 )
chunk_len = chunk_len + ( 4 - chunk_len%4 );
/* cast added for C++ compilers */
strData = (char*) malloc( chunk_len );
myAssert( (strData != NULL), "Error: malloc failed in readWord (1)" );
while( ( *c = fgetc( fp )) != EOF && strchr( delimits, *c ))
; /* advance over any whitespace i.e. delimits */
if( *c != EOF ) /* ok ... get this first char ... */
strData[i++] = *c;
else
{
free( strData );
return NULL; /* at EOF or all 'delimits' ... */
}
while( (*c = fgetc( fp )) != EOF && !strchr( delimits, *c ) )
{
if( i == chunk_len-1 ) /* skip while i <= chunk_len-2 */
{
chunk_len += chunk_len; /* double memory ...*/
if( ( tmp = (char*) realloc( strData, chunk_len )) == NULL )
{
free( strData );
myAssert( 0, "Error: realloc failed in readWord (2)" );
}
/* if reach here, realloc above was a success,
so update strData */
strData = tmp;
}
/* now can ... */
strData[i++] = *c;
}
strData[i] = 0; /* assure '\0' termination */
/* if EOF and empty strData, quit reading file,
BUT FIRST, free this strData */
if( *c == EOF && strData[0] == 0 )
{ free( strData ); return NULL; }
/* else ... and note ... i is index of '\0' */
if( (tmp = (char*) realloc( strData, i+1 )) == NULL )
{
free( strData );
myAssert( 0, "Error: realloc failed in readWord (3)" );
}
/* if reach here, realloc above was a success, program NOT aborted, so ...*/
return tmp;
}
#endif
/* CvecOfString.h */ /* this version: 2016-10-07 */
/*
this version with added isortCvec (still has msort)
also added isSorted, uniqueCvec, isUniqueCvec, showCvec, findCvec, eraseCvec
*/
#ifndef dwCvecOfString_H
#define dwCvecOfString_H
#include "readline.h" /* includes stdio.h, stdlib.h, string.h, <ctype.h>
myAssert, newCopy */
typedef struct
{
char* str;
} Rec ;
void clearRec( Rec* rc )
{
free( rc->str );
}
/* Ok ... NOW can include ... */
#include "Cvec.h"
/* needs stdlib.h, string.h and myAssert & all included above */
/* and these ...*/
void mergeCvec( Cvec*, int, int, int, Cvec* );
void my_msortCvec( Cvec*, int, int, Cvec* );
void msortCvec( Cvec* );
int isSortedCvec( Cvec* );
int findCvec( Cvec*, const char* ); /* returns index if string present, else -1 */
void eraseCvec( Cvec*, int ); /* if int index valid, erases element there */
void isortCvec( Cvec* );
void showCvec( const Cvec* );
void uniqueCvec( Cvec* cv );
int isUniqueCvec( Cvec* cv );
char* joinCvec( Cvec*, const char* );
/* * * * * * * * * * * * * * * * merge sort * * * * * * * * * * * * * * * * * */
void mergeCvec( Cvec* cv, int bot, int mid, int top, Cvec* tmp )
{
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... */
if( strcmp(cv->ary[h1].str, cv->ary[h2].str) <= 0 )
tmp->ary[j++].str = cv->ary[h1++].str;
else
tmp->ary[j++].str = cv->ary[h2++].str;
}
/* Note: only one of the two while loops below is executed ... */
while( h1 <= mid ) /* copy any remaining entries (1st half) */
tmp->ary[j++].str = cv->ary[h1++].str;
while( h2 <= top ) /* copy any remaining entries (2nd half) */
tmp->ary[j++].str = cv->ary[h2++].str;
for( j = 0; j < sz; ++j ) /* copy back sorted tmp vec... */
cv->ary[bot+j].str = tmp->ary[j].str;
}
void my_msortCvec( Cvec* cv, int bot, int top, Cvec* tmp )
{
if( bot == top ) return;
else
{
int mid = ( bot + top ) / 2;
my_msortCvec( cv, bot, mid, tmp ); /* sort the first ... */
my_msortCvec( cv, mid + 1, top, tmp ); /* and the second half ... */
mergeCvec( cv, bot, mid, top, tmp ); /* now merge these 2 sorted chunks ... */
}
}
void msortCvec( Cvec* cv )
{
if( cv->size > 1 )
{
Cvec tmp;
initCvec( &tmp );
reserveCvec( &tmp, cv->size );
my_msortCvec( cv, 0, cv->size-1, &tmp );
cv->isSorted = 1;
free( tmp.ary ); /* only free ary mem that held copies of pointers */
}
}
int isSortedCvec( Cvec* cv )
{
int size = cv->size;
while( --size )
if( strcmp(cv->ary[size].str, cv->ary[size-1].str) < 0 ) return 0;
return 1;
}
int findCvec( Cvec* cv, const char* s ) /* returns index if present ... else -1 */
{
int i;
for( i = 0; i < cv->size; ++i )
if( strcmp(cv->ary[i].str, s) == 0 ) return i;
/* else if reach here ... */
return -1;
}
void eraseCvec( Cvec* cv, int index ) /* if index valid, erases element there */
{
/* 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 pointer above down one index */
/* //for( i = index; i < cv->size-1; ++i )
//cv->ary[i].str = cv->ary[i+1].str;
//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 i, j;
for( i = 1; i < cv->size; ++i ) /* start with an array of just the first 2 elements (if exists) */
{
char* cmp = cv->ary[i].str; /* 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 && strcmp(cmp, cv->ary[j].str) < 0 )
{
cv->ary[j+1].str = cv->ary[j].str; /* copy pointer 'up' ... */
--j; /* decrement j in preparation for next inner loop ... */
}
cv->ary[j+1].str = cmp; /* insert pointer at index j+1 (since j was decremented above) */
}
cv->isSorted = 1;
}
void showCvec( const Cvec* cv )
{
int i;
for( i = 0; i < cv->size; ++i ) printf( "%s ", cv->ary[i].str );
}
void uniqueCvec( Cvec* cv )
{
if( cv->size > 1 )
{
int i = 0, j = 1;
if( !cv->isSorted ) msortCvec( cv );
for( ; j < cv->size ; ++j )
{
if( strcmp( cv->ary[i].str, cv->ary[j].str ) != 0 )
{
++i;
if( i != j ) cv->ary[i].str = cv->ary[j].str;
}
else clearRec( &cv->ary[j] );
}
cv->size = ++i;
}
}
int isUniqueCvec( Cvec* cv )
{
int i;
if( !cv->isSorted ) msortCvec( cv );
for( i = cv->size-1; i > 0; --i )
if( strcmp( cv->ary[i].str, cv->ary[i-1].str ) == 0 ) return 0;
/* else ... */
return 1;
}
char* joinCvec( Cvec* cv, const char* s )
{
char* concatStr;
int i, sumsize = 0;
int add = strlen( s );
for( i = 0; i < cv->size; ++i ) sumsize += strlen(cv->ary[i].str) + add;
concatStr = (char*) malloc( sumsize-add+1 );
myAssert( (concatStr != NULL), "Error, malloc failed to allocate memory for concatStr" );
concatStr[0] = 0;
for( i = 0; i < cv->size; ++i )
{
strcat( concatStr, cv->ary[i].str );
if( i < cv->size-1 ) strcat( concatStr, s );
}
return concatStr;
}
#endif
/* 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
/* takeInLine.h */ /* 2016-10-19 */
#ifndef dwTAKE_IN_LINE_H
#define dwTAKE_IN_LINE_H
#include "readLine.h"
#include <math.h>
#include <limits.h>
#define MAX_DIG_IN_INT (int)log10(INT_MAX) + 1.
#define ERR_BLANK_LINE "\nBlank line NOT valid input here!\n"
char* takeInLine( const char* msg )
{
fputs( msg, stdout );
fflush( stdout );
return readLine( stdin );
}
char* takeInLineNotBlank( const char* msg )
{
char* line = NULL;
for( ; ; )
{
line = takeInLine( msg );
if( line[0] ) /* i.e. if NOT BLANK LINE ... */
break;
/* else ... */
printf( ERR_BLANK_LINE );
free( line );
}
return line;
}
/* using readLine and getting new dynamic memory ... so can return address */
/* LOOPS until entered line_length > 0 and line_length <= maxLen ... */
char* takeInLineMaxLen( const char* msg, unsigned maxLen )
{
char* line = NULL;
for( ; ; )
{
line = takeInLineNotBlank( msg );
if( strlen( line ) <= maxLen )
break;
/* else ... */
printf( "\nFor '%s', maximum length of %u char's was exceeded!\n",
line, maxLen );
free( line );
}
return line;
}
/* returns a valid int in range INT_MIN..INT_MAX */
int takeInInt( const char* prompt )
{
/* make extra large to hold 10 chars & sign & terminal '\0' char */
char loc_buf[16];
int tmpInt;
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
int good = 1, i = 0, len = 0, sign = 1;
char* tmp = takeInLineNotBlank( prompt );
char* tmpCpy = tmp;
if( tmp[0] == '+' )
++tmp;
else if( tmp[0] == '-')
{
++tmp;
sign = -1;
}
len = i = strlen( tmp );
/* check len ok ... */
good = ( len <= MAX_DIG_IN_INT );
/* check all digits (after any single leading sign) ... */
while( good && --i >= 0 )
good = isdigit( tmp[i] );
/* check in range that can be held by an int ... */
if( good && len == MAX_DIG_IN_INT )
{
if( sign == 1 )
{
sprintf( loc_buf, "%d", INT_MAX );
if( strcmp( tmp, loc_buf ) > 0 )
good = 0;
}
else
{
sprintf( loc_buf, "%d", INT_MIN );
if( strcmp( tmp, &loc_buf[1] ) > 0 )
good = 0;
}
}
if( good )
{
tmpInt = atoi( tmpCpy );
free( tmpCpy );
break;
}
/* else ...*/
printf( "\n'%s' is NOT valid input here!\n", tmpCpy ) ;
free( tmpCpy );
}
return tmpInt;
}
/* returns a valid int in range min..max */
int takeInIntMinMax( const char* prompt, int min, int max )
{
int tmpInt;
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
tmpInt = takeInInt( prompt );
if( tmpInt >= min && tmpInt <= max )
break;
/* else ...*/
printf( "\nValid input here is an integer in range %d..%d!\n",
min, max );
}
return tmpInt;
}
/* accepts only int's in range 0..max */
int takeInIntPosMax( const char* prompt, int max )
{
return takeInIntMinMax( prompt, 0, max );
}
double takeInDouble( const char* prompt )
{
char buf[80];
double val = 0;
for( ; ; )
{
char* line = takeInLineNotBlank( prompt );
if( sscanf( line, "%lf%s", &val, buf ) == 1 )
{
free( line );
break;
}
/* else .. */
printf( "\n'%s' is NOT valid input here!\n", line );
free( line );
}
return val;
}
/* returns a valid decimal in range min..max */
double takeInDoubleMinMax( const char* prompt, double min, double max )
{
double val;
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
val = takeInDouble( prompt );
if( val >= min && val <= max )
break;
/* else ...*/
printf( "\nValid input here is a decimal value in range %.2e..%.2e!\n",
min, max );
}
return val;
}
/* accepts only deciamal's in range 0..max */
double takeInDoublePosMax( const char* prompt, double max )
{
return takeInDoubleMinMax( prompt, 0, max );
}
#endif
/* test_takeInLine.c */ /* 2016-10-20 */
#include "takeInLine.h" /* includes file readLine.h and that has ... */
const char* getSex( const char sex )
{
if( sex == 'M' )
return "MALE";
return "FEMALE";
}
int main()
{
char gender;
int id;
double amount;
do
{
char* name = strToTitleCase(takeInLineMaxLen( "Enter student name: ", 80 ));
for ( ; ; )
{
gender = toupper(takeInChar( "Enter gender (m/f) "));
if( gender == 'M' || gender == 'F' )
break;
/* else ... */
puts( "Must enter either of m or f to proceed." );
}
id = takeInIntMinMax( "Enter ID in range 1..999 : ", 1, 999 );
amount = takeInDoublePosMax( "Enter $ amount tution due in range 0..100000: ", 100000 );
printf( "Name: %s, Gender: %s, ID: %d, Tution Due: %.2f dollars.\n",
name, getSex(gender), id, amount );
printf( "\nOn to next student?\n" );
printf( "Whenever you are ready, enter y or n, " );
printf( "or just press the Enter key for 'y'.\n" );
free( name );
}
while( more() );
return 0;
}
/* more2.c */ /* 2016-10-07 */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "takeInLine.h" /* uses/needs custom file: "readLine.h" */
int main()
{
int count = 0;
double sum = 0.0;
for( ; ; ) /* an example C/C++ forever loop ... until 'break' */
{
int testInt = takeInInt( "Enter next integer to sum: " );
++count;
sum += testInt;
if( !more() ) break;
}
printf( "\nFor %d numbers entered, sum was %.0f and average was %.2f\n",
count, sum, sum/count );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
/* arrayInt2.c */ /* 2016-10-07 */
/* enters integer data, finds sum, average, sorts, finds value, erase, show ...*/
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "takeInLine.h" /* uses/needs custom file: "readLine.h" */
#define MAX_SIZE 6 /* using a small size here for simple testing purposes ... */
long sumAry( const int ary[], int size )
{
long sum = 0;
for( --size; size >= 0; --size ) sum += ary[size];
return sum;
}
void showAry( const int ary[], int size )
{
int i;
for( i = 0; i < size; ++i ) printf( "%d ", ary[i] );
}
int findAry( const int ary[], int size, int value ) /* if found, returns index */
{
int i;
for( i = 0; i < size; ++i )
if( ary[i] == value ) return i;
/* else if reach here ... */
return -1;
}
void eraseAry( int ary[], int* size, int index ) /* if valid index erase element */
{
int i;
if( index < 0 || index >= *size )
{ printf( "\nERROR! Index %d out of range 0..%d\n", index, *size-1 );
return; }
for( i = index; i < *size-1; ++i )
ary[i] = ary[i+1]; /* copy each element above, down one index, so erased */
/* now update size and return new size ... (by ref.) */
-- *size;
}
void isortAry( int ary[], int size )
{
int i, j, cmp;
for( i = 1; i < size; ++i ) /* start with an array of just the first 2 elements (if exists) */
{
cmp = ary[i]; /* get copy of this new cmp element 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 && cmp < ary[j] )
{
ary[j+1] = ary[j]; /* copy element 'up' ... */
--j; /* decrement j in preparation for next inner loop ... */
}
ary[j+1] = cmp; /* insert element at index j+1 (since j was decremented above) */
}
}
int main()
{
int my_ary[ MAX_SIZE ]; /* create array to hold upto MAX_SIZE int's */
int i = 0, index, last;
long sum;
do
{
my_ary[i] = takeInInt( "Enter next integer to sum: " );
++i;
if( i == MAX_SIZE )
{
printf( "You have reached %d, the max size.\n", MAX_SIZE );
break;
}
}
while( more() ); /* make sure stdin is 'empty' before calling more() */
sum = sumAry( my_ary, i );
printf( "\nFor %d numbers entered, sum was %ld and array average was %.2f\n",
i, sum, (float)sum/i );
printf( "\nshowAry: " ); showAry( my_ary, i );
last = my_ary[i-1];
printf( "\n\nAfter sorting ..." );
isortAry( my_ary, i );
printf( "\nshowAry: " ); showAry( my_ary, i );
index = findAry( my_ary, i, last );
if( index >= 0 )
{
/* Note: below, need to pass address of i ... so i can be updated */
eraseAry( my_ary, &i, index );
printf( "\n\nAfter erasing %d ...", last );
printf( "\nshowAry: " ); showAry( my_ary, i );
}
else printf( "%d NOT found in my_ary.\n", last );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
/* CvecInt2.c */ /* 2016-10-07 */
/* enters integer data, finds sum, average, sorts, finds value, erase, show ...*/
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "CvecOfInt.h" /* uses/needs custom file: "Cvec.h" */
#include "takeInLine.h" /* uses/needs custom file: "readLine.h" */
void showCvec( Cvec* cv )
{
Rec* p = cv->ary;
for( ; p != &cv->ary[cv->size]; ++p ) printf( "%d ", p->val );
printf( "\nsizeCvec = %d\n", cv->size );
}
int main()
{
int index, last;
long sum;
Cvec cv; /* create CvecOfInt to hold all the int's to be input */
Rec tmp; /* typedef struct ... Rec has int member 'val' ... */
initCvec( &cv );
do
{
tmp.val = takeInInt( "Enter next integer to sum: " );
push_backCvec( &cv, &tmp );
}
while( more() ); /* make sure stdin is 'empty' before calling more() */
sum = sumCvec( &cv );
printf( "\nFor %d numbers entered, sum was %ld and Cvec average was %.2f\n",
cv.size, sum, (float)sum/cv.size );
printf( "\nshowCvec: " ); showCvec( &cv );
last = cv.ary[ cv.size-1 ].val;
msortCvec( &cv );
printf( "\nAfter msort ... " );
printf( "isSortedCvec( &cv ) = %d\n", isSortedCvec( &cv ) );
printf( "showCvec: " ); showCvec( &cv );
index = findCvec( &cv, last );
if( index >= 0 )
{
eraseCvec( &cv, index );
printf( "\nAfter erasing %d ...", last );
printf( "\nshowCvec: " ); showCvec( &cv );
}
else printf( "\n%d NOT found in Cvec.\n", last );
tmp.val = takeInInt( "\nEnter a new integer to isort: " );
push_backCvec( &cv, &tmp );
isortCvec( &cv );
printf( "After isortCvec ... " );
printf( "isSortedCvec( &cv ) = %d\n", isSortedCvec( &cv ) );
printf( "showCvec: " ); showCvec( &cv );
clearCvec( &cv );
printf( "\nAfter clearCvec ...\n" );
printf( "The size of Cvec is now %d\n", cv.size );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
/* CvecString2.c */ /* 2016-10-07 */
/* enters dynamic C string data, sorts, finds value, erase, show ...*/
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "CvecOfString.h" /* uses/needs custom files: "Cvec.h", "readLine.h" */
#include "takeInLine.h" /* ALSO ... uses/needs custom file: "readLine.h" */
void showLines( const Cvec* cv )
{
int i;
for( i = 0; i < cv->size; ++ i ) printf( "%s\n", cv->ary[i].str );
}
int main()
{
char last[80];
Cvec cv;
Rec rc;
int index;
initCvec( &cv );
do
{
rc.str = takeInLine( "Enter a line of text: " );
push_backCvec( &cv, &rc );
}
while( more() ); /* make sure stdin is 'empty' before calling more() */
printf( "\nshowLines:\n" ); showLines( &cv );
printf( "isSortedCvec( &cv ) = %d\n", isSortedCvec( &cv ) );
strcpy( last, cv.ary[ cv.size - 1 ].str );
printf( "\nAfter sorting ..." );
isortCvec( &cv );
printf( "\nshowLines:\n" );
showLines( &cv );
printf( "isSortedCvec( &cv ) = %d\n", isSortedCvec( &cv ) );
index = findCvec( &cv, last );
if( index >= 0 )
{
/* Note: below, need to pass address of i ... so i can be updated */
eraseCvec( &cv, index );
printf( "\nAfter erasing '%s'\n", last );
printf( "showLines:\n" ); showLines( &cv );
}
else printf( "%s NOT found in my_ary.\n", last );
/* free all dynamic C strings ... */
clearCvec( &cv );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
/* CvecPrson2.c */ /* 2016-10-07 */
/* enters dynamic C string data, sorts, finds value, erase, show ...*/
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "takeInLine.h" /* uses/needs file: readLine.h */
typedef struct Person
{
char* name;
char* phone;
} Rec;
void clearRec( Rec* p )
{
free( p->phone );
free( p->name );
}
/* OK ... NOW can include both these 2 */
#include "Cvec.h"
#include "Cvec_func's.h"
void showLines( const Cvec* cv )
{
int i;
for( i = 0; i < cv->size; ++i )
printf( "%s, %s\n", cv->ary[i].name, cv->ary[i].phone );
}
int cmpNames( const Rec* a, const Rec* b )
{
return strcmp( a->name, b->name );
}
char* toCapsFirstLetter( char* str )
{
if( str && strlen(str) )
str[0] = toupper(str[0]);
return str;
}
int main()
{
int i;
Cvec cv;
Rec rc;
initCvec( &cv );
for( ; ; )
{
rc.name = toCapsFirstLetter(takeInLineMaxLen( "Enter name: ", 80 ));
rc.phone = takeInLine( "Enter phone: " );
push_backCvec( &cv, &rc );
if( !more() ) /* make sure stdin is 'empty' before calling more() */
break;
}
printf( "\nshowLines:\n" ); showLines( &cv );
rc.name = cv.ary[cv.size-1].name;
rc.phone = cv.ary[cv.size-1].phone;
printf( "\nAfter sorting by name ..." );
msortCvec( &cv, cmpNames );
printf( "\nshowLines:\n" );
showLines( &cv );
i = findCvec( &cv, &rc, cmpNames );
if( i >= 0 )
{
printf( "\nNOW erasing: '%s, %s'\n", rc.name, rc.phone );
eraseCvec( &cv, i );
printf( "showLines:\n" ); showLines( &cv );
}
else printf( "%s NOT found in lines.\n", rc.name );
/* free all dynamic C strings ... */
clearCvec( &cv );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
/* ClistInt2.c */ /* 2016-10-07 */
/* enters integer data, finds sum, average, sorts, finds value, erase, show ...*/
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "ClistOfInt.h" /* uses/needs custom file: "Clist.h" */
#include "takeInLine.h" /* uses/needs custom file: "readLine.h" */
void showClist( Clist* cl )
{
pNode p = cl->start;
for( ; p != NULL; p = p->next ) printf( "%d ", p->val );
printf( "size = %d", cl->size );
}
int main()
{
int last;
long sum;
pNode p;
Clist cl; /* create ClistOfInt to hold all the int's to be input */
initClist( &cl );
do
{
Node tmp; /* typedef struct ... List has int member 'val' ... */
tmp.val = takeInInt( "Enter next integer to sum: " );
push_backClist( &cl, &tmp );
}
while( more() ); /* make sure stdin is 'empty' before calling more() */
sum = sumClist( &cl );
printf( "\nFor %d numbers entered, sum was %ld and list average was %.2f\n",
cl.size, sum, (float)sum/cl.size );
printf( "\nshowClist: " ); showClist( &cl );
last = cl.end->val;
msortClist( &cl );
printf( "\n\nAfter merge sorting ..." );
printf( "isSortedClist( &cl ) = %d\n", isSortedClist( &cl ) );
printf( "\nshowClist " ); showClist( &cl );
p = findClist( &cl, last );
if( p != NULL )
{
eraseClist( &cl, p );
printf( "\n\nAfter erasing %d ...", last );
printf( "\nshowClist: " ); showClist( &cl );
}
else printf( "%d NOT found in Clist.\n", last );
clearClist( &cl );
printf( "\n\nAfter clearClist ...\n" );
showClist( &cl );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;;
}
/* ClistString2.c */ /* 2016-10-07 */
/* enters dynamic C string data, sorts, finds value, erase, show ...*/
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "ClistOfString.h" /* uses/needs custom files: "Clist.h", "readLine.h" */
#include "takeInLine.h" /* uses/needs custom file: "readLine.h" */
void showLines( const Clist* cl )
{
pNode p = cl->start;
for( ; p != NULL; p = p->next ) printf( "%s\n", p->str );
}
int main()
{
char last[80];
Clist cl;
Node nd;
pNode p;
initClist( &cl );
do
{
nd.str = takeInLine( "Enter line of text: " );
push_backClist( &cl, &nd );
}
while( more() ); /* make sure stdin is 'empty' before calling more() */
printf( "\nshowLines:\n" ); showLines( &cl );
strcpy( last, cl.end->str );
printf( "\nAfter sorting ..." );
msortClist( &cl );
printf( "\nshowLines:\n" );
showLines( &cl );
p = findClist( &cl, last );
if( p )
{
eraseClist( &cl, p );
printf( "\nAfter erasing '%s'\n", last );
printf( "showLines:\n" ); showLines( &cl );
}
else printf( "%s NOT found in my_ary.\n", last );
/* free all dynamic C strings ... */
clearClist( &cl );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
/* ClistPrson2.c */ /* 2016-10-07 */
/* enters dynamic C string data, sorts, finds value, erase, show ...*/
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "takeInLine.h" /* uses/needs custom file: "readLine.h" */
typedef struct Person
{
char* name;
char* phone;
struct Person* next;
} Node;
typedef Node* pNode;
void clearNode( pNode p )
{
free( p->phone );
free( p->name );
}
/* OK ... NOW can include both these 2 */
#include "Clist.h"
#include "Clist_func's.h"
void showLines( const Clist* cl )
{
pNode p = cl->start;
for( ; p != NULL; p = p->next ) printf( "%s, %s\n", p->name, p->phone );
}
int cmpNames( const pNode a, const pNode b )
{
return strcmp( a->name, b->name );
}
char* toTitleCase( char* str )
{
char* p = str;
char prev = ' ';
while( *p )
{
if( prev == ' ' ) *p = toupper( *p );
prev = *p;
++p;
}
return str;
}
int allDigits( const char* str )
{
int len = strlen(str);
while( len-- ) if( !isdigit(str[len] )) return 0;
return 1;
}
int main()
{
Clist cl;
Node nd;
pNode p, plast;
initClist( &cl );
for( ; ; )
{
nd.name = toTitleCase( takeInLineMaxLen( "Enter name: ", 80 ) );
for( ; ; )
{
nd.phone = takeInLine( "Enter phone: " );
if( allDigits(nd.phone) && 10 == strlen(nd.phone) ) break;
/* else ...*/
free( nd.phone );
puts( "Phone number must be 10 digits!" );
}
push_backClist( &cl, &nd );
if( !more() ) /* make sure stdin is 'empty' before calling more() */
break;
}
printf( "\nshowLines:\n" ); showLines( &cl );
plast = cl.end;
printf( "\nAfter sorting by name ..." );
msortClist( &cl, cmpNames );
printf( "\nshowLines:\n" );
showLines( &cl );
p = findClist( &cl, plast, cmpNames );
if( p )
{
printf( "\nNOW erasing: '%s, %s'\n", plast->name, plast->phone );
eraseClist( &cl, p );
printf( "showLines:\n" ); showLines( &cl );
}
else printf( "%s NOT found in lines.\n", plast->name );
/* free all dynamic C strings ... */
clearClist( &cl );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}