/* employeeRec's_msortClist_func's.h.c */ /* this version: 2016-10-13 */
/*
in the following:
a List is a Node ( struct),
a pList (i.e. List*) holds the address of a Node
a Clist is the struct hold ing addresses of 'start' & 'end' Nodes, etc.
a Clist* holds the address of the struct Clist
*/
/* 'C++ list emulation' using a C Clist struct ... (see demo MENU below) */
#include "takeInLIne.h" /* also includes readLine.h, stdio.h, stdlib.h, string.h and defines
functions myAssert and newCopy. etc... */
#define FILENAME "employeeRecords.txt"
#define MENU " 1. Enter a new record. \n" \
" 2. Retrieve a record by name (ignore case). \n" \
" 3. Retrieve a record by phone number. \n" \
" 4. Show all records. \n" \
" 5. Insert sort all records by name (ignore case). \n" \
" 6. Insert sort all records by phone number. \n" \
" 7. Chop exact duplicates from records (use case). \n" \
" 8. Edit/Delete a record. \n" \
" 9. Write new file of sorted unique records. \n" \
"10. Exit \n"
#define PROMPT "Enter a number in range 1 to 10 : "
typedef struct employeeRec
{
char* name; /* since CStrings are '\0' terminated ... can get strlen */
char* address; /* ditto above ... */
char* phone; /* 3 digit area-code + 7 digits + '\0' at end */
struct employeeRec* next;
} Node ;
typedef Node* pNode;
void clearNode( pNode r )
{
free( r->phone );
free( r->address );
free( r->name );
}
/* Now can ... */
#include "Clist.h"
/* and then can ...*/
#include "Clist_func's.h"
void show( const pNode r )
{
char phFormated[] = "(###) ###-####";
char* p = phFormated;
char* s = r->phone;
for( ; *p && *s; ++p ) if( *p == '#' ) { *p = *s; ++s; }
printf
(
"%-22s %-30s %s\n",
r->name, r->address, phFormated
);
}
void showAll( const Clist* list )
{
int i = 0;
pNode p = list->start;
for( ; p != NULL; p = p->next )
{
printf("<%03d> ", ++i);
show( p );
if( i % 5 == 0 && i != list->size ) putchar('\n');
}
printf( "\nEmployee records on file = %d\n\n", list->size );
}
/* ignore case compare function ... */
int strcmpIgnoreCase( const char* s1, const char* s2 )
{
for( ; *s1 != 0 && *s2 != 0; ++s1, ++s2 )
{
if( tolower(*s1) != tolower(*s2) ) break;
}
/* ok ... check the end conditions ... */
return tolower(*s1) - tolower(*s2);
}
int cmpIgnoreCase( const pNode x, const pNode y )
{
int compare1 = strcmpIgnoreCase( x->name, y->name ); /* first compare names */
if( compare1 == 0 ) /* if the same ... */
{
int compare2 = strcmpIgnoreCase( x->address, y->address ); /* then address */
if( compare2 == 0 ) /* if the same ... */
return strcmp( x->phone, y->phone ); /* then phone number ... */
/* else ...*/
return compare2; /* use addresses after all ... */
}
/* else ... */
return compare1; /* use names afer all ... since names were NOT the same */
}
int cmpPhone( const pNode x, const pNode y )
{
int compare1 = strcmp( x->phone, y->phone ); /* first compare phones */
if( compare1 == 0 ) /* if the same ... */
{
int compare2 = strcmp( x->name, y->name ); /* then names */
if( compare2 == 0 ) /* if the same ... */
return strcmp( x->phone, y->phone ); /* then adress ... */
/* else ...*/
return compare2; /* use names after all ... */
}
/* else ... */
return compare1; /* use phones afer all ... since were NOT the same */
}
int cmp( const pNode x, const pNode y )
{
int compare1 = strcmp( x->name, y->name ); /* first compare names */
if( compare1 == 0 ) /* if the same ... */
{
int compare2 = strcmp( x->address, y->address ); /* then address */
if( compare2 == 0 ) /* if the same ... */
return strcmp( x->phone, y->phone ); /* then phone number ... */
/* else ...*/
return compare2; /* use addresses after all ... */
}
/* else ... */
return compare1; /* use names afer all ... since names were NOT the same */
}
/* with these, an address is passed, so NO copy made and/or original updated */
void readFile( Clist* );
int showMenuExecuteChoice( Clist* );
int isValidPhoneNum( const char* );
pNode getNameIgnoreCase( Clist*, const char* );
pNode getNumber( Clist*, const char* );
void takeInNewRec( pNode );
void takeInRecAndFile( Clist* );
void writeSortedUnique( Clist* );
void editDel( Clist* );
void edit( Clist*, pNode );
void del( Clist*, pNode );
int main() /* ************* MAIN BEGINS ***************** */
{
int choice;
Clist cl;
initClist( &cl ); /* passing the address of cl so object gets updated */
readFile( &cl ); /* passing the address of cl so object gets updated */
if( cl.size == 0 )
printf
(
"File %s will be created after data has been entered.\n",
FILENAME
);
/* else showAll( &cl ); //// passing address to avoid making another copy */
printf( "Now cl.start = 0x%p ... cl.size = %d\n\n", (void*)cl.start, cl.size );
do
{
showAll( &cl ); /* passing address to avoid making another copy */
choice = showMenuExecuteChoice( &cl ); /* passing address ... */
putchar( '\n' );
}
while( choice != 10 ); /* i.e. exit on choice of 10 ... */
clearClist( &cl ); /* free all dynamic memory when done with it ... */
printf( "\nNow cl.start = 0x%p ... cl.size = %d\n", (void*)cl.start, cl.size );
/* if using windows ... can do this ... especially while debugging ... */
system( "notepad " FILENAME );
return 0;
} /* ***************** MAIN ENDS ************************ */
void readFile( Clist* list )
{
FILE* fp = fopen(FILENAME, "r");
if( fp )
{
Node d;
while
(
(d.name = readLine(fp)) &&
(d.address = readLine(fp)) &&
(d.phone = readLine(fp))
)
{
push_frontClist( list, &d );
}
fclose( fp );
}
else
printf( "File %s NOT found ...\n", FILENAME );
}
int showMenuExecuteChoice( Clist* list )
{
int num;
char* tmp = NULL;
fputs( MENU, stdout );
num = takeInIntMinMax( PROMPT, 1, 10 );
if( num == 1 ) takeInRecAndFile( list );
else if( num == 2 )
{
pNode pd = NULL;
fputs( "Enter the name to find: ", stdout );
tmp = readLine(stdin);
if( (pd = getNameIgnoreCase( list, tmp )) == NULL )
printf( "%s not found.\n", tmp );
else
show( pd );
free( tmp );
}
else if( num == 3 )
{
pNode pd;
fputs( "Enter the number to find: ", stdout );
tmp = readLine(stdin);
if( (pd = getNumber( list, tmp )) == NULL )
printf( "%s not found.\n", tmp );
else
show( pd );
free( tmp );
}
/* else if( num == 4 ) showAll( list ); */
else if( num == 5 ) isortClist( list, cmpIgnoreCase );
else if( num == 6 ) isortClist( list, cmpPhone );
else if( num == 7 ) uniqueClist( list, cmp );
else if( num == 8 ) editDel ( list );
else if( num == 9 ) writeSortedUnique( list );
/* else is 10 ... so will exit ... */
return num;
}
/* validates that 10 char's are present and all are numeric ... */
int isValidPhoneNum( const char* ph )
{
if( strlen(ph) != 10 ) return 0;
for( ; *ph != 0; ++ph )
if( *ph < '0' || *ph >'9' ) return 0;
return 1;
}
/* returns index ... if found ... otherwise , returns -1 if NOT found */
pNode getNameIgnoreCase( Clist* Clist, const char* nameStr )
{
pNode pr = Clist->start;
for( ; pr != NULL; pr = pr->next )
if( strcmpIgnoreCase(pr->name, nameStr) == 0 ) return pr;
return NULL;
}
pNode getNumber( Clist* Clist, const char* numStr )
{
pNode pr = Clist->start;
for( ; pr != NULL; pr = pr->next )
if( strcmp(pr->phone, numStr) == 0 ) return pr;
return NULL;
}
void takeInNewRec( pNode r )
{
r->name = strToTitleCase(takeInLine( "Enter name: " ));
r->address = strToTitleCase(takeInLine( "Enter address: " ));
for( ; ; )
{
r->phone = takeInLine( "Enter telephone: " );
if( isValidPhoneNum(r->phone) ) return;
/* else ... */
fputs( "Only 10 digit number valid here ... ", stdout );
free( r->phone );
}
}
void takeInRecAndFile( Clist* list )
{
Node d;
takeInNewRec( &d );
/* Now we have good data ... so file and add to vector if ok ? */
if( tolower(takeInChar( "Ok ... (y/n) ? " )) == 'y' )
{
FILE* pFile = fopen( FILENAME, "a" );
myAssert( (pFile != NULL), "Error: " FILENAME " not opened." );
fprintf( pFile, "%s\n", d.name );
fprintf( pFile, "%s\n", d.address );
fprintf( pFile, "%s\n", d.phone );
push_backClist( list, &d );
fclose( pFile );
printf( "Information has been filed in file %s.\n", FILENAME );
}
else
{
puts( "Aborted ..." );
clearNode( &d );
}
}
void writeSortedUnique( Clist* list )
{
pNode pd;
int i = 0;
FILE* fp = fopen( "SU" FILENAME, "w" ); /* compiler concat's these TEXTs */
myAssert( (fp != NULL), "Error: file SU" FILENAME " failed to open." );
/* ok ... file is open ... so write all rec's to file ..*/
/* first ... make sure sorted and unique */
uniqueClist( list, cmp );
for( pd = list->start; pd != NULL; pd = pd->next )
{
fprintf( fp, "<%03d> ", ++i );
fprintf( fp, "%-24s ", pd->name );
fprintf( fp, "%-32s ", pd->address );
fprintf( fp, "%s\n", pd->phone );
if( i % 5 == 0 ) fputs( "\n", fp );
}
fclose( fp ); /* flushes buffer ... so all written to file now ... */
printf( "\n%d records filed in file SU%s list size %d\n\n",
i, FILENAME, list->size );
/* and if have Windows OS ... can do this ... */
system( "notepad SU" FILENAME ); /*compiler concat's text at compile time*/
}
void editDel( Clist* list )
{
for( ; ; )
{
pNode pd;
char* tmp;
int reply = tolower(takeInChar( "Find by Name/Phone/Abort (n/p/a) ? " ));
if( reply == 'n' )
{
fputs( "Enter the name to find: ", stdout );
tmp = readLine(stdin);
if( (pd = getNameIgnoreCase( list, tmp )) == NULL )
printf( "%s not found.\n", tmp );
else
{
show( pd );
reply = tolower(takeInChar( "Edit/Delete/Abort (e/d/a) ? " ));
if( reply == 'e' ) edit( list, pd );
else if( reply == 'd' ) del( list, pd );
else if( reply == 'a' )
{
puts( "Ok, edit/delete aborted ..." );
free( tmp );
break;
}
}
free( tmp );
}
else if( reply == 'p' )
{
fputs( "Enter the number to find: ", stdout );
tmp = readLine(stdin);
if( (pd = getNumber( list, tmp )) == NULL )
printf( "%s not found.\n", tmp );
else
{
show( pd );
reply = tolower(takeInChar( "Edit/Delete/Abort (e/d/a) ? " ));
if( reply == 'e' ) edit( list, pd );
else if( reply == 'd' ) del( list, pd );
else if( reply == 'a' )
{
puts( "Ok, edit/delete aborted ..." );
free( tmp );
break;
}
}
free( tmp );
}
else if( reply == 'a' )
{
puts( "Ok, edit/delete aborted ..." );
break;
}
else fputs( "Only n/p/a are valid ... ", stdout );
}
}
void edit( Clist* list, pNode pd )
{
Node d;
for( ; ; )
{
takeInNewRec( &d );
/* ok ... we have some new data ... */
if( tolower(takeInChar( "Ok ... (y/n) ? " )) == 'y' )
{
/* then edit ... but first free old ... */
clearNode( pd );
pd->name = d.name;
pd->address = d.address;
pd->phone = d.phone;
list->isSorted = 0;
break;
}
else
{
puts( "Aborted ..." );
clearNode( &d );
break;
}
}
}
void del( Clist* list, pNode pd )
{
for( ; ; )
{
int reply = tolower(takeInChar( "Really delete/abort (d/a) ? " ));
if( reply == 'a' )
{
puts( "Delete aborted ..." );
break;
}
else if( reply == 'd' )
{
eraseClist( list, pd );
break;
}
/* else ... */
fputs( "Enter 'd' and WILL delete ... or 'a' to abort ... \n", stdout );
}
}
/* msort_Clist_func_p_NO_VOID.c */ /* this version 2016-10-13 */
/*
http://developers-heaven.net/forum/index.php/topic,46.0.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define HEADER "C program to sort 3 Million random int's from file stored " \
"in a Clist ...\n" \
"Note: uses function pointers ... (*NO* void pointers used in msort compare)\n"
#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
typedef struct myListOfInt
{
int val;
struct myListOfInt* next;
} Node;
typedef Node* pNode;
void clearNode( pNode p )
{
/* empty here ... since no dynamic memory to free here */
p = p;
}
/* now can include these ...*/
#include "Clist.h"
#include "Clist_func's.h"
/* and ... define this ... */
int compare( const pNode a, const pNode b )
{
return a->val - b->val ;
}
void myShowAll( const Clist* cl )
{
int i = 0;
pNode p = cl->start;
for( ; p; p = p->next )
{
printf( "%6d ", p->val );
if( (++i % 20) == 0 )
{
char c;
fputs( "\nPress 'Enter' to continue ... 'a' to abort ... ", stdout );
c = getchar();
if( c != '\n' ) while( getchar() != '\n' ); /* flush stdin */
if( c == 'a' )
{
putchar('\n');
while( i <= (cl->size - 20) ) { ++i; p = p->next; }
for( ; p; p = p->next ) printf( "%6d ", p->val );
break;
}
}
}
}
int main( void ) /* ************************************* */
{
FILE* fp;
/* int i = 0; /// i is used below as an index counter ... */
double ti, tp;
Node r, *r3;
Clist cl;
initClist( &cl ); /* Note: MUST initial to work */
puts( HEADER );
ti = clock();
fp = fopen( "randInt3M.txt", "r" );
while( 1 == fscanf( fp, "%d", &r.val ) )
{
push_backClist( &cl, &r ); /* since good Rec was obtained */
/* // ++i; */
}
tp = clock() - ti;
printf( "%d int's were read from file in %.2f sec's ... ",
cl.size, tp/CLOCKS_PER_SEC );
ti = clock();
msortClist( &cl, compare );
tp = clock() - ti;
printf( "merge sorted in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( "\nand isSortedClist( &cl, compare ) = %d\n",
isSortedClist( &cl, compare ) );
ti = clock();
uniqueClist( &cl, compare );
tp = clock() - ti;
printf( "\nuniqueClist in %.2f sec's ", tp/CLOCKS_PER_SEC );
printf( "... and isSortedClist( &cl, compare ) = %d",
isSortedClist( &cl, compare ) );
printf( "\n... and isUniqueClist( &cl, compare ) = %d\n",
isUniqueClist( &cl, compare ) );
printf( "\nAfter uniqueClist: cl.size = %d\n", cl.size );
r.val = cl.end->val;
ti = clock();
r3 = findClist( &cl, &r, compare );
if( r3 )
{
eraseClist( &cl, r3 );
tp = clock() - ti;
printf( "%d was erased ...", r.val );
printf( "%d is new end val...\n", cl.end->val );
printf( "\nfind/ereaseClist in %.2f sec's\n", tp/CLOCKS_PER_SEC );
}
else printf( "%d was NOT-found/NOT-erased ...", r.val );
myShowAll( &cl );
printf( "Before clearClist: cl.size = %d\n", cl.size );
clearClist( &cl );
printf( "After clearClist: cl.size = %d\n", cl.size );
fputs( "\nPress 'Enter' to continue ... ", stdout );
getchar();
return 0;
} /* **************************************************** */
/* msort_Clist_func_p_NO_VOID_Cstring.c */ /* this version 2016-10-16 */
/*
http://developers-heaven.net/forum/index.php/topic,46.0.html
*/
#define HEADER "C program to sort 3 Million random int's from file stored " \
"in a Clist ...\n" \
"(as C strings) ...\n" \
"Note: uses function pointers ... (*NO* void pointers used in msort compare)\n"
#include "readWord.h"
#include <time.h>
typedef struct myListOfString
{
char* str;
struct myListOfString* next;
} Node;
typedef Node* pNode;
void clearNode( pNode p )
{
free( p->str );
}
/* now can include these ...*/
#include "Clist.h"
#include "Clist_func's.h"
/* and ... define this ... */
int compare( const pNode a, const pNode b )
{
return strcmp(a->str, b->str ) ;
}
void myShowAll( Clist* cl )
{
int i = 0;
pNode p = cl->start;
for( ; p; p = p->next )
{
printf( "%6s ", p->str );
if( (++i % 20) == 0 )
{
char c;
fputs( "\nPress 'Enter' to continue ... 'a' to abort ... ", stdout );
c = getchar();
if( c != '\n' ) while( getchar() != '\n' ) ; /* flush stdin */
if( c == 'a' )
{
putchar( '\n' );
while( i <= (cl->size - 20) ) { ++i; p = p->next; }
for( ; p; p = p->next ) printf( "%6s ", p->str );
break;
}
}
}
}
int main( void ) /* ************************************* */
{
FILE* fp;
double ti, tp;
char lastChr;
Node r, r2, *r3 = NULL;
Clist cl;
initClist( &cl ); /* Note: MUST initial to work */
puts( HEADER );
ti = clock();
fp = fopen( "randInt3M.txt", "r" );
while( (r.str = readWord( fp, 5, " \n", &lastChr )) )
{
push_backClist( &cl, &r ); /* since good Rec was obtained */
}
tp = clock() - ti;
printf( "%d int's were read from file in %.2f sec's ... ",
cl.size, tp/CLOCKS_PER_SEC );
ti = clock();
msortClist( &cl, compare );
tp = clock() - ti;
printf( "merge sorted in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( "\nand isSortedClist( &cl, compare ) = %d\n",
isSortedClist( &cl, compare ) );
ti = clock();
uniqueClist( &cl, compare );
tp = clock() - ti;
printf( "\nuniqueClist in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( " ... and isSortedClist( &cl, compare ) = %d",
isSortedClist( &cl, compare ) );
printf( "\n... and isUniqueClist( &cl, compare ) = %d\n",
isUniqueClist( &cl, compare ) );
printf( "\nAfter uniqueClist: cl.size = %d\n", cl.size );
r2.str = newCopy( cl.end->str ); /* 'newCopy' def'd in readWord/readLine */
ti = clock();
r3 = findClist( &cl, &r2, compare );
if( r3 )
{
eraseClist( &cl, r3 );
tp = clock() - ti;
printf( "%s was erased ...", r2.str);
printf( "%s is new end str...\n", cl.end->str);
printf( "\nfind/ereaseClist in %.2f sec's\n", tp/CLOCKS_PER_SEC );
}
else printf( "%s was NOT-found/NOT-erased ...", r2.str);
myShowAll( &cl );
free( r2.str );
printf( "Before clearClist: cl.size = %d\n", cl.size );
clearClist( &cl );
printf( "After clearClist: cl.size = %d\n", cl.size );
fputs( "\nPress 'Enter' to continue ... ", stdout );
getchar();
return 0;
} /* **************************************************** */
/* msort_ClistOfInt.c */ /* this version 2016-10-13 */
/*
http://developers-heaven.net/forum/index.php/topic,46.0.html
*/
#define HEADER "C progr am to sort 3 Million random int's from file stored " \
"in a C list using ... ClistOfInt ...\n"
#include "ClistOfInt.h"
#include <time.h>
void myShowAll( Clist* cl )
{
int i = 0;
pNode p = cl->start;
for( ; p; p = p->next )
{
printf( "%6d ", p->val );
if( (++i % 20) == 0 )
{
char c;
fputs( "\nPress 'Enter' to continue ... 'a' to abort ... ", stdout );
c = getchar();
if( c != '\n' ) while( getchar() != '\n' ) ; /* flush stdin */
if( c == 'a' )
{
putchar('\n' );
while( i <= (cl->size - 20) ) { ++i; p = p->next; }
for( ; p; p = p->next ) printf( "%6d ", p->val );
break;
}
}
}
}
int main( void ) /* ************************************* */
{
FILE* fp;
double ti, tp;
int valToFind;
Node r, *r3;
Clist cl;
initClist( &cl ); /* Note: MUST initial to work */
puts( HEADER );
ti = clock();
fp = fopen( "randInt3M.txt", "r" );
while( 1 == fscanf( fp, "%d", &r.val ) )
{
push_backClist( &cl, &r ); /* since good Rec was obtained */
/* ++i; */
}
tp = clock() - ti;
printf( "%d int's were read from file in %.2f sec's ... ",
cl.size, tp/CLOCKS_PER_SEC );
ti = clock();
msortClist( &cl );
tp = clock() - ti;
printf( "merge sorted in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( "\nand isSorted( &cl ) = %d\n", isSortedClist( &cl ) );
ti = clock();
uniqueClist( &cl );
tp = clock() - ti;
printf( "\nunique in %.2f sec's ", tp/CLOCKS_PER_SEC );
printf( "... and isSorted( &cl ) = %d", isSortedClist( &cl ) );
printf( "\n... and isUnique( &cl ) = %d\n", isUniqueClist( &cl ) );
printf( "\nAfter unique: cl.size = %d\n", cl.size );
valToFind = cl.end->val;
ti = clock();
r3 = findClist( &cl, valToFind );
if( r3 )
{
eraseClist( &cl, r3 );
tp = clock() - ti;
printf( "%d was erased ...", valToFind);
printf( "%d is new end val...\n", cl.end->val);
printf( "\nfind/ereaseClist in %.2f sec's\n", tp/CLOCKS_PER_SEC );
}
else printf( "%d was NOT-found/NOT-erased ...", valToFind );
myShowAll( &cl );
printf( "Before clearClist: cl.size = %d\n", cl.size );
clearClist( &cl );
printf( "After clearClist: cl.size = %d\n", cl.size );
fputs( "\nPress 'Enter' to continue ... ", stdout );
getchar();
return 0;
} /* **************************************************** */
/* msort_ClistOfString.c */ /* this version 2016-10-20 */
/*
http://developers-heaven.net/forum/index.php/topic,46.0.html
*/
#define HEADER "C program to sort 3 Million random int's from file stored " \
"in a Clist ...\n ... as C strings ... " \
"(Note: using ClistOfString.h in this program)\n"
#include "readWord.h"
#include "ClistOfString.h" /* also includes readLine, but using readWord here */
#include <time.h>
void myShowAll( Clist* cl )
{
int i = 0;
pNode p = cl->start;
for( ; p; p = p->next )
{
printf( "%6s ", p->str );
if( (++i % 20) == 0 )
{
char c, c2;
fputs( "\nPress 'Enter' to continue ... 'a' to abort ... ", stdout );
c2 = c = getchar();
while( c != '\n' ) c = getchar(); /* flush stdin ... */
if( c2 == 'a' )
{
putchar('\n');
while( i <= (cl->size - 20 ) ) { ++i; p = p->next; }
for( ; p; p = p->next ) printf( "%6s ", p->str );
break;
}
}
}
}
int main( void ) /* ********************************************************* */
{
FILE* fp;
double ti, tp;
char lastChr, *s;
int i;
Node r, r2, *r3 = NULL;
Clist cl;
initClist( &cl ); /* Note: MUST initial to work */
puts( HEADER );
ti = clock();
fp = fopen( "randInt3M.txt", "r" );
while( (r.str = readWord( fp, 5, " \n", &lastChr )) )
{
push_backClist( &cl, &r ); /* since good Rec was obtained */
}
tp = clock() - ti;
printf( "%d int's were read from file in %.2f sec's ... ",
cl.size, tp/CLOCKS_PER_SEC );
ti = clock();
msortClist( &cl );
tp = clock() - ti;
printf( "merge sorted in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( "\nand isSorted( &cl ) = %d\n", isSortedClist( &cl ) );
ti = clock();
uniqueClist( &cl );
tp = clock() - ti;
printf( "\nunique in %.2f sec's ", tp/CLOCKS_PER_SEC );
printf( "... and isSorted( &cl ) = %d", isSortedClist( &cl ) );
printf( "\n... and isUnique( &cl ) = %d\n", isUniqueClist( &cl ) );
printf( "\nAfter unique: cl.size = %d\n", cl.size );
r2.str = newCopy( cl.end->str ); /* 'newCopy' def'd in readWord/readLine */
ti = clock();
r3 = findClist( &cl, r2.str );
if( r3 )
{
eraseClist( &cl, r3 );
tp = clock() - ti;
printf( "%s was erased ...", r2.str);
printf( "%s is new end str...\n", cl.end->str);
printf( "\nfind/ereaseClist in %f sec's\n", tp/CLOCKS_PER_SEC );
}
else printf( "%s was NOT-found/NOT-erased ...", r2.str);
myShowAll( &cl );
free( r2.str );
ti = clock();
s = joinClist( &cl, "," );
tp = clock() - ti;
printf( "\njoinClist( &cl, \",\" ) in %f sec's ... ", tp/CLOCKS_PER_SEC );
ti = clock();
i = strlen( s );
tp = clock() - ti;
printf( "\nstrlen(s) = %d in %f sec's ... ", i, tp/CLOCKS_PER_SEC );
puts( "\nFirst 70 char's in joined Clist dynamic C string is :" );
s[70] = 0;
puts( s );
puts( "\nLast 70 char's in joined Clist dynamic C string is :" );
puts( &s[i-70] );
free( s );
printf( "\nBefore clearClist: cl.size = %d\n", cl.size );
clearClist( &cl );
printf( "After clearClist: cl.size = %d\n", cl.size );
fputs( "\nPress 'Enter' to continue ... ", stdout );
getchar();
return 0;
} /* ************************************************************************ */
/* employeeRec's_list.cpp */ /* this version: 2011-08-08 */
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <list>
#include <cstdlib> /* re. atoi */
#include <cctype> /* re. tolower */
using namespace std;
#define FILENAME "employeeRecords.txt"
#define MENU " 1. Enter a new record. \n" \
" 2. Retrieve a record by name (ignore case). \n" \
" 3. Retrieve a record by phone number. \n" \
" 4. Show all records. \n" \
" 5. Sort all records by name (ignore case). \n" \
" 6. Sort all records by phone number. \n" \
" 7. Chop exact duplicates from records (use case). \n" \
" 8. Edit/Delete a record. \n" \
" 9. Write new file of sorted unique records. \n" \
"10. Exit \n"
#define PROMPT "Enter a number in range 1 to 10 : "
struct Employee
{
string name;
string address;
string phone;
} ;
typedef list< Employee > myList;
typedef list< Employee >::iterator myIter;
typedef list< Employee >::const_iterator c_myIter;
int strcmpIgnoreCase( const string&, const string& );
int strcmpWithCase( const string&, const string& );
bool cmpIgnoreCase( const Employee&, const Employee& );
bool cmpWithCase( const Employee&, const Employee& );
bool cmpPhone( const Employee&, const Employee& );
bool operator == ( const Employee&, const Employee& ); // for unique ...
void show( const Employee& r )
{
char phFormated[] = "(###) ###-####";
char* p = phFormated;
for( int i = 0; *p ; ++p ) if( *p == '#' ) { *p = r.phone[i]; ++i; }
cout << left << setw(22) << r.name << " "
<< setw(30) << r.address << " " << phFormated << right << endl;
}
void showAll( const myList& lst )
{
size_t i = 0;
for( c_myIter p = lst.begin(); p != lst.end(); ++p )
{
cout << "<" << setfill('0') << setw(3) << ++i << "> " << setfill(' ');
show( *p );
if( i % 5 == 0 && i != lst.size() ) cout << endl;
}
cout << "\nEmployee records on file = " << lst.size() << endl << endl;
}
/* ignore case compare function ... */
int strcmpIgnoreCase( const string& a, const string& b )
{
size_t i, lenA = a.size(), lenB = b.size();
for( i = 0; i < lenA && i < lenB; ++i )
{
if( tolower(a[i]) != tolower(b[i]) ) break;
}
/* ok ... check the end conditions ... */
if( i < lenA )
{
if( i < lenB ) return tolower(a[i]) - tolower(b[i]);
//else ...
return 1; // i.e. b < a
}
// else // if reach here ... i == lenA
if( i < lenB ) return -1; // i.e. a < b
// else // if reach here ... i == lenA ...AND... i == lenB
return 0; // i.e. a == b
}
/* case compare function ... */
int strcmpWithCase( const string& a, const string& b )
{
size_t i, lenA = a.size(), lenB = b.size();
for( i = 0; i < lenA && i < lenB; ++i )
{
if( a[i] != b[i] ) break;
}
/* ok ... check the end conditions ... */
if( i < lenA )
{
if( i < lenB ) return a[i] - b[i];
//else ...
return 1; // i.e. b < a
}
// else // if reach here ... i == lenA
if( i < lenB ) return -1; // i.e. a < b
// else // if reach here ... i == lenA ...AND... i == lenB
return 0; // i.e. a == b
}
bool cmpIgnoreCase( const Employee& x, const Employee& y )
{
int compare1 = strcmpIgnoreCase( x.name, y.name ); /* first compare names */
if( compare1 == 0 ) /* if the same ... */
{
int compare2 = strcmpIgnoreCase( x.address, y.address ); /* then address */
if( compare2 == 0 ) /* if the same ... */
return x.phone < y.phone; /* then phone number ... */
/* else ...*/
return compare2 < 0; /* use addresses after all ... */
}
/* else ... */
return compare1 < 0; /* use names afer all ... since names were NOT the same */
}
bool cmpWithCase( const Employee& x, const Employee& y )
{
int compare1 = strcmpWithCase( x.name, y.name ); /* first compare names */
if( compare1 == 0 ) /* if the same ... */
{
int compare2 = strcmpWithCase( x.address, y.address ); /* then address */
if( compare2 == 0 ) /* if the same ... */
return x.phone < y.phone; /* then phone number ... */
/* else ...*/
return compare2 < 0; /* use addresses after all ... */
}
/* else ... */
return compare1 < 0; /* use names afer all ... since names were NOT the same */
}
bool cmpPhone( const Employee& x, const Employee& y )
{
int compare1 = strcmpWithCase( x.phone, y.phone ); /* first compare phones */
if( compare1 == 0 ) /* if the same ... */
{
int compare2 = strcmpWithCase( x.name, y.name ); /* then names */
if( compare2 == 0 ) /* if the same ... */
return x.address < y.address; /* then address ... */
/* else ...*/
return compare2 < 0; /* use names after all ... */
}
/* else ... */
return compare1 < 0; /* use phones afer all ... since were NOT the same */
}
bool operator ==( const Employee& x, const Employee& y )
{
if( x.name != y.name ) return false; /* first compare names */
if( x.address != y.address ) return false; /* then address */
if( x.phone != y.phone ) return false; /* then phone number ... */
//else ...
return true;
}
int getChoice( const string& );
int showMenuGetChoice( myList& );
void readFile( myList& );
bool isValidPhoneNum( const string& );
myIter getNameIgnoreCase( myList&, const string& );
myIter getNumber( myList&, const string& );
Employee enterEmployee();
void takeInRecAndFile( myList& );
void writeSortedUnique( myList& );
void editDel( myList& );
void edit( myList&, myIter& );
void del( myList&, myIter& );
int main() /* ********************* MAIN BEGINS ***************************** */
{
int choice;
myList ml;
readFile( ml ); /* passing ml by reference so object gets updated */
if( ml.size() == 0 )
cout << "File " << FILENAME
<< " will be created after data has been entered." << endl;
else
cout << "Now &(*ml.begin()) = " << hex << &(*ml.begin()) << " and "
<< "ml.size = " << dec << ml.size() << endl << endl;
do
{
showAll( ml ); /* passing ml by reference to avoid making another copy */
choice = showMenuGetChoice( ml ); /* passing address ... */
cout << endl;
}
while( choice != 10 ); /* i.e. exit on choice of 10 ... */
cout << "Now &(*ml.begin()) = 0x" << hex << &(*ml.begin()) << " and "
<< "ml.size = " << ml.size() << endl << endl;
/* if using windows ... can do this ... especially while debugging */
system( "notepad " FILENAME );
} /* **************************** MAIN ENDS ********************************* */
int getChoice( const string& text )
{
cout << text << flush;
int reply = tolower( cin.get() );
cin.sync();
return reply;
}
void readFile( myList& lst )
{
ifstream fin( FILENAME );
if( !fin )
{
cout << "File " << FILENAME << " NOT found ..." << endl;
}
else
{
Employee d;
while
(
getline( fin, d.name ) && getline( fin, d.address )
&& getline( fin, d.phone )
)
{
lst.push_back( d );
}
fin.close();
}
}
int showMenuGetChoice( myList& lst )
{
int num;
string tmp;
cout << MENU << flush;
while
(
cout << PROMPT
&& getline( cin, tmp )
&& ( (num = atoi(tmp.c_str())) < 1 || num > 10 )
)
{
cout << "Out of valid range 1..10 " << flush;
}
if( num == 1 ) takeInRecAndFile( lst );
else if( num == 2 )
{
cout << "Enter the name to find: " << flush;
getline(cin, tmp);
myIter it;
if( (it = getNameIgnoreCase( lst, tmp )) == lst.end() )
cout << tmp << " not found." << endl;
else
show( *it );
}
else if( num == 3 )
{
cout << "Enter the number to find: " << flush;
getline(cin, tmp);
myIter it;
if( (it = getNumber( lst, tmp )) == lst.end() )
cout << tmp << " not found." << endl;
else
show( *it );
}
//else if( num == 4 ) showAll( list );
else if( num == 5 ) lst.sort( cmpIgnoreCase );
else if( num == 6 ) lst.sort( cmpPhone );
else if( num == 7 ) { lst.sort( cmpWithCase ); lst.unique(); }
else if( num == 8 ) editDel ( lst );
else if( num == 9 ) writeSortedUnique( lst );
/* else is 10 ... so will exit ... */
return num;
}
/* validates that 10 char's are present and all are numeric ... */
bool isValidPhoneNum( const string& ph )
{
if( ph.size() != 10 ) return false;
for( int i = 0; i < 10; ++i )
if( ph[i] < '0' || ph[i] >'9' ) return false;
return true;
}
/* returns valid iterbif found ... otherwise, returns ml.end() if NOT found */
myIter getNameIgnoreCase( myList& ml, const string& nameStr )
{
for( myIter it = ml.begin(); it != ml.end(); ++it )
if( strcmpIgnoreCase(it->name, nameStr) == 0 ) return it;
return ml.end();
}
myIter getNumber( myList& ml, const string& numStr )
{
for( myIter it = ml.begin(); it != ml.end(); ++it )
if( strcmpWithCase(it->phone, numStr) == 0 ) return it;
return ml.end();
}
Employee enterEmployee()
{
Employee d;
cout << "Enter name: " << flush;
getline( cin, d.name );
cout << "Enter address: "<< flush;
getline( cin, d.address );
for( ; ; )
{
cout << "Enter telephone: " << flush;
getline( cin, d.phone );
if( isValidPhoneNum(d.phone) )
{
break;
}
/* else ... */
cout << "Only 10 digit number valid here ... " << flush;
}
return d;
}
void takeInRecAndFile( myList& lst )
{
ofstream fout( FILENAME, ios::app );
if( !fout )
{
cout << "Error: " << FILENAME << " not opened." << endl;
return;
}
Employee d = enterEmployee();
/* Now we have good data ... so file and add to vector if ok ? */
if( getChoice( "Ok ... (y/n) ? " ) == 'y' )
{
fout << d.name << '\n' << d.address << '\n' << d.phone << endl;
lst.push_back( d );
cout << "Information has been filed in file " << FILENAME << endl;
}
else
{
cout << "Aborted ..." << endl;
}
fout.close();
}
void writeSortedUnique( myList& lst )
{
ofstream fout( "SU" FILENAME ); /* compiler concat's the text's ... */
if( !fout )
{
cout << "Error: file SU" << FILENAME << " failed to open." << endl;
return;
}
/* ok ... file is open ... so write all rec's to file ..*/
/* first ... make sure sorted and unique */
lst.sort( cmpWithCase );
lst.unique();
int i = 0;
for( c_myIter it = lst.begin(); it != lst.end(); ++it )
{
fout << "<" << setfill('0') << setw(3) << ++i << "> "
<< setfill(' ') << left << setw(24) << it->name << " "
<< setw(32) << it->address << " "
<< it->phone << right << endl;
if( i % 5 == 0 ) fout << endl;
}
fout.close(); /* flushes buffer ... so all written to file now ... */
cout << i << " records filed in file SU" << FILENAME
<< ", list size " << lst.size() << endl << endl;
/* and if have Windows OS ... can do this ... */
system( "notepad SU" FILENAME ); /*compiler concat's text at compile time*/
}
void editDel( myList& lst )
{
myIter it;
string tmp;
for( ; ; )
{
int reply = getChoice( "Find by Name/Phone/Abort (n/p/a) ? " );
if( reply == 'n' )
{
cout << "Enter the name to find: " << flush;
getline( cin, tmp );
if( (it = getNameIgnoreCase( lst, tmp )) == lst.end() )
cout << tmp << " not found." << endl;
else
{
show( *it );
reply = getChoice( "Edit/Delete/Abort (e/d/a) ? " );
if( reply == 'e' ) edit( lst, it );
else if( reply == 'd' ) del( lst, it );
else if( reply == 'a' )
{
cout << "Ok, edit/delete aborted ..."<< endl;
break;
}
}
}
else if( reply == 'p' )
{
cout << "Enter the number to find: " << flush;
getline(cin, tmp);
if( (it = getNumber( lst, tmp )) == lst.end() )
cout << tmp << " not found." << endl;
else
{
show( *it );
reply = getChoice( "Edit/Delete/Abort (e/d/a) ? " );
if( reply == 'e' ) edit( lst, it );
else if( reply == 'd' ) del( lst, it );
else if( reply == 'a' )
{
cout << "Ok, edit/delete aborted ..." << flush;
break;
}
}
}
else if( reply == 'a' )
{
cout << "Ok, edit/delete aborted ..." << flush;
break;
}
else cout << "Only n/p/a are valid ... " << flush;
}
}
void edit( myList& lst, myIter& it )
{
Employee d = enterEmployee();
/* ok ... we have some new data ... */
if( getChoice( "Ok ... (y/n) ? " ) == 'y' )
{ /* then edit ... */
it->name =d.name;
it->address =d.address;
it->phone =d.phone;
return;
}
/* else ... */
cout << "Aborted ..." << endl;
}
void del( myList& lst, myIter& it )
{
for( ; ; )
{
int reply = getChoice( "Really delete/abort (d/a) ? " );
if( reply == 'a' )
{
cout << "Delete aborted ..." << flush;
return;
}
/* else ... */
if( reply == 'd' )
{
lst.erase( it );
return;
}
/* else ... */
cout << "Enter 'd' and WILL delete ... or 'a' to abort ..." << endl;
}
}