/* employeeRec's_msortCvec_func's.h.c */ /* this version 2016-10-08 */
/* this version does NOT use void pointers in cmp func's ... */
#define FILE_NAME "employeeRecords.txt"
#define MENU " 1. Enter a new record. \n" \
" 2. retrieve a record by Name. \n" \
" 3. retrieve a record by Phone number. \n" \
" 4. Show all records. \n" \
" 5. Merge sort all records by name (ignore case). \n" \
" 6. Merge sort all records by phone number( use case). \n" \
" 7. Chop exact duplicates from records (use case). \n" \
" 8. eDit/Delete a record. \n" \
" 9. Write new file of sorted unique records (use case). \n" \
"10. eXit \n"
#define PROMPT "Enter a number in range 1 to 10 : "
#include "takeInLine.h" /* also includes "readLine.h" // includes stdio.h, stdlib.h, string.h
and myAssert and newCopy functions */
typedef struct employeeRecord
{
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 */
} Rec ;
void clearRec( Rec* r )
{
free( r->phone );
free( r->address );
free( r->name );
}
/* now can ... */
#include "Cvec.h"
/* then can ... */
#include "Cvec_func's.h" /* this ver. does NOT use void pointers in cmp func's */
void show( const Cvec* cv, int i ) /* phone number formated to (###) ###-#### */
{
char phFormated[] = "(###) ###-####";
char* s = phFormated; /* get pointer to 1st char in string */
char* p = cv->ary[i].phone; /* get pointer to 1st char in string */
for( ; *p && *s; ++s )
if( *s == '#' ) *s = *p++; /* traverse s, increment p when *s == '#' */
printf
(
"<%03d> %-24s %-32s %s\n",
i+1, cv->ary[i].name, cv->ary[i].address, phFormated
);
}
void showAll( const Cvec* cv )
{
int i;
for( i = 0; i < cv->size; ++i )
{
show( cv, i );
if( (i+1)%3 == 0 && (i+1) != cv->size ) putchar('\n');
}
printf( "\nEmployee records on file = %d, present vector capacity = %d\n\n",
cv->size, cv->cap );
}
int myCmpName( const Rec* a, const Rec* b )
{
int compareAdd, compareNam = strcmp(a->name, b->name);
if( compareNam ) return compareNam;
compareAdd = strcmp( a->address, b->address );
if( compareAdd ) return compareAdd;
return strcmp( a->phone, b->phone );
}
int myCmpPhone( const Rec* a, const Rec* b )
{
int compareName, comparePh = strcmp(a->phone, b->phone);
if( comparePh ) return comparePh;
compareName = strcmp( a->name, b->name );
if( compareName ) return compareName;
return strcmp( a->address, b->address );
}
/* ignore case C string compare function ... */
int compareStrsIgnoreCase( 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 myCmpNameIgnoreCase ( const Rec* a, const Rec* b )
{
int compareAdd, compareNam = compareStrsIgnoreCase(a->name, b->name);
if( compareNam ) return compareNam;
compareAdd = compareStrsIgnoreCase( a->address, b->address );
if( compareAdd ) return compareAdd;
return strcmp( a->phone, b->phone );
}
void readFile( Cvec* cv );
int showMenuExecuteChoice( Cvec* cv );
int isValidPhoneNum( char ph[] );
int getNameIgnoreCase( Cvec* cv, char nameStr[] );
int getNumber( Cvec* cv, char numStr[] );
void takeInNewRec( Rec* );
void takeInRecAndFile( Cvec* cv );
void writeSortedUnique( Cvec* cv );
void del( Cvec*, int );
void editDel( Cvec * cv );
void edit( Cvec* cv, int i ); /* at index i ... */
int main() /* ******************************************* */
{
int choice;
Cvec cv;
initCvec( &cv );
readFile( &cv ); /* we are passing the address of cv, so cv is updated */
if( cv.size == 0 )
printf
(
"File %s will be created after data has been entered.\n",
FILE_NAME
);
/* else showAll( &cv ); // // passing address to avoid making another copy */
printf( "Now with address of cv.ary = 0x%p, cv.size = %d, cv.cap = %d\n",
(void*)cv.ary, cv.size, cv.cap );
do
{
putchar( '\n' );
showAll( &cv ); /* passing address to avoid making another copy */
choice = showMenuExecuteChoice( &cv ); /* passing address ... */
}
while( choice != 10 ); /* i.e. exit on choice of 10 ... */
clearCvec( &cv ); /* free all dynamic memory when done with it ... */
printf( "\nNow with cv.ary = 0x%p, cv.size = %d\n", (void*)cv.ary, cv.size );
/* if using windows ... can do this ... especially while debugging ... */
system( "notepad " FILE_NAME );
return 0;
} /* **************************************************** */
void readFile( Cvec* cv )
{
FILE* fp;
if( (fp = fopen(FILE_NAME, "r")) )
{
Rec d;
while
(
(d.name = readLine(fp)) &&
(d.address = readLine(fp)) &&
(d.phone = readLine(fp))
)
{
push_backCvec( cv, &d );
}
fclose( fp );
}
else
printf( "File %s does not exist yet in this folder ...\n", FILE_NAME );
}
int showMenuExecuteChoice( Cvec* cv )
{
char* tmp = NULL;
int num = takeInIntMinMax( MENU, 1, 10 );
if( num == 1 )
takeInRecAndFile( cv );
else if( num == 2 )
{
int index;
fputs( "Enter the name to find: ", stdout );
tmp = readLine(stdin);
if( (index = getNameIgnoreCase( cv, tmp )) == -1 )
printf( "%s not found.\n", tmp );
else
show( cv, index );
free( tmp );
}
else if( num == 3 )
{
int index;
tmp = takeInLine( "Enter the number to find: " );
if( (index = getNumber( cv, tmp )) == -1 )
printf( "%s not found.\n", tmp );
else
show( cv, index );
free( tmp );
}
/*else if( num == 4 ) showAll( cv );*/
else if( num == 5 ) msortCvec( cv, myCmpNameIgnoreCase );
else if( num == 6 ) msortCvec( cv, myCmpPhone );
else if( num == 7 ) uniqueCvec( cv, myCmpName ); /* sort by case */
else if( num == 8 ) editDel ( cv );
else if( num == 9 ) writeSortedUnique( cv );
/* else if num == 10, will exit do..while( num!=10 ) calling loop */
/* else will do calling loop again ...*/
return num;
}
/* validates that 10 char's are present and all are numeric ... */
int isValidPhoneNum( 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 */
int getNameIgnoreCase( Cvec* cv, char nameStr[] )
{
int i;
for( i = 0; i < cv->size; ++i)
if( compareStrsIgnoreCase(cv->ary[i].name, nameStr) == 0 )
return i;
return -1;
}
int getNumber( Cvec* cv, char numStr[] )
{
int i;
for( i = 0; i < cv->size; ++i)
if( strcmp(cv->ary[i].phone, numStr) == 0 )
return i;
return -1;
}
void takeInNewRec( Rec* r )
{
r->name = strToTitleCase(takeInLineMaxLen( "Enter name: ", 80 ));
r->address = strToTitleCase(takeInLineMaxLen( "Enter address: ", 80 ));
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( Cvec* cv )
{
Rec 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( FILE_NAME, "a" );
myAssert( (pFile != NULL), "Error: " FILE_NAME " not opened." );
fprintf( pFile, "%s\n", d.name );
fprintf( pFile, "%s\n", d.address );
fprintf( pFile, "%s\n", d.phone );
push_backCvec( cv, &d );
printf( "Information has been filed in file %s.\n", FILE_NAME );
fclose( pFile );
}
else
{
puts( "Aborted ..." );
clearRec( &d );
}
}
void writeSortedUnique( Cvec* cv )
{
int i;
FILE* fp = fopen( "SU" FILE_NAME, "w" ); /* compiler concat's these TEXTs */
myAssert( (fp != NULL), "Error: file SU" FILE_NAME " failed to open." );
/* ok ... file is open ... so write all rec's to file ..*/
uniqueCvec( cv,myCmpName ); /* first make sure sorted and unique (use case) */
for( i = 0; i < cv->size; ++i )
{
fprintf( fp, "<%03d> ", i+1 );
fprintf( fp, "%-24s ", cv->ary[i].name );
fprintf( fp, "%-32s ", cv->ary[i].address );
fprintf( fp, "%s\n", cv->ary[i].phone );
if( (i+1) % 5 == 0 ) fputs( "\n", fp );
}
fclose( fp ); /* flushes buffer ... so all written to file now ... */
printf( "\n%d records filed in file SU%s\n\n", i, FILE_NAME );
/* and if have Windows OS ... can do this ... */
system( "notepad SU" FILE_NAME ); /*compiler concat's text at compile time*/
}
void editDel( Cvec* cv )
{
for( ; ; )
{
char* tmp;
int i, reply = tolower(takeInChar( "Find by Name/Phone/Abort (n/p/a) ? " ));
if( reply == 'n' )
{
tmp = takeInLine( "Enter the name to find: " );
if( (i = getNameIgnoreCase( cv, tmp )) == -1 )
printf( "%s not found.\n", tmp );
else
{
show( cv, i );
reply = tolower(takeInChar( "Edit/Delete/Abort (e/d/a) ? " ));
if( reply == 'e' ) edit( cv, i );
else if( reply == 'd' ) del( cv, i );
else if( reply == 'a' )
{
puts( "Ok, edit/delete aborted ..." );
free( tmp );
break;
}
}
free( tmp );
}
else if( reply == 'p' )
{
tmp = takeInLine("Enter the number to find: " );
if( (i = getNumber( cv, tmp )) == -1 )
printf( "%s not found.\n", tmp );
else
{
show( cv, i );
reply = tolower(takeInChar( "Edit/Delete/Abort (e/d/a) ? " ));
if( reply == 'e' ) edit( cv, i );
else if( reply == 'd' ) del( cv, i );
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( Cvec* cv, int i )
{
Rec d;
for( ; ; )
{
takeInNewRec( &d );
if( takeInChar( "Ok ... (y/n) ? " ) == 'y' )
{
/* then edit ... but first free old ... */
clearRec( & cv->ary[i] );
cv->ary[i].name = d.name;
cv->ary[i].address = d.address;
cv->ary[i].phone = d.phone;
break;
}
else
{
puts( "Aborted ..." );
clearRec( &d );
break;
}
}
}
void del( Cvec* cv, int i )
{
for( ; ; )
{
int reply = tolower(takeInChar( "Really delete/abort (d/a) ? " ));
if( reply == 'a' )
{
puts( "Delete aborted ..." );
break;
}
else if( reply == 'd' )
{
eraseCvec( cv, i );
break;
}
/* else ... */
fputs( "Enter 'd' and WILL delete ... or 'a' to abort ... \n", stdout );
}
}
/* msort_Cvec_func_p_NO_VOID.c */ /* this version 2016-10-09 */
/*
http://developers-heaven.net/forum/index.php/topic,46.0.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define FNAME "randInt3M.txt"
#define THREE_MEG 3000000
#define HEADER "C program to sort 3 Million random int's from file stored " \
"in a Cvec ...\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 myRecOfInt
{
int val;
} Rec;
void clearRec( Rec* r )
{
/* empty here ... since no dynamic memory to free here */
r = r;
}
/* now can include these ...*/
#include "Cvec.h"
#include "Cvec_func's.h"
/* and ... define this ... */
int compare( const Rec* a, const Rec* b )
{
return a->val - b->val ;
}
void myShowAll( Cvec* cv )
{
int i;
for( i = 0; i < cv->size; )
{
printf( "%6d ", cv->ary[i].val );
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 < cv->size - 20 ) ++i;
for( ; i < cv->size; ++i ) printf( "%6d ", cv->ary[i].val );
break;
}
}
}
}
int main( void ) /* ************************************* */
{
FILE* fp = NULL;
double ti, tp;
int i;
Rec r;
Cvec cv;
initCvec( &cv ); /* Note: MUST initial to work */
reserveCvec( &cv, THREE_MEG );
puts( HEADER );
ti = clock();
fp = fopen( FNAME, "r" );
if( !fp ) /* create file ... */
{
fp = fopen( FNAME, "w" );
if(fp)
{
for( i = 1; i <= THREE_MEG; ++ i )
{
fprintf( fp, "%6d ", rand() );
if( (i % 10)== 0 ) fprintf( fp, "\n" );
}
}
fclose(fp);
printf( "File %s was created.\n", FNAME );
}
fp = fopen( FNAME, "r" );
if( fp )
{
while( 1 == fscanf( fp, "%d", &r.val ) )
{
push_backCvec( &cv, &r ); /* since good Rec was obtained */
}
tp = clock() - ti;
printf( "%d int's were read from file in %.2f sec's ... ",
cv.size, tp/CLOCKS_PER_SEC );
ti = clock();
msortCvec( &cv, compare );
tp = clock() - ti;
printf( "merge sorted in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( "\nand isSortedCvec( &cl, compare ) = %d\n",
isSortedCvec( &cv, compare ) );
ti = clock();
uniqueCvec( &cv, compare );
tp = clock() - ti;
printf( "\nunique in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( " ... and isSortedCvec( &cv, compare ) = %d ",
isSortedCvec( &cv, compare ) );
printf( "\n... and isUniqueCvec( &cv, compare ) = %d\n",
isUniqueCvec( &cv, compare ) );
printf( "\nAfter uniqueCvec: cv.size = %d, cv.cap = %d\n\n", cv.size, cv.cap );
r.val = cv.ary[cv.size-1].val;
ti = clock();
i = findCvec( &cv, &r, compare );
if( i != -1 )
{
eraseCvec( &cv, i );
tp = clock() - ti;
printf( "%d was erased ...", r.val);
printf( "%d is new end val...\n", cv.ary[cv.size-1].val);
printf( "find/ereaseCvec in %.2f sec's\n\n", tp/CLOCKS_PER_SEC );
}
else printf( "%d was NOT-found/NOT-erased ...\n\n", r.val );
myShowAll( &cv );
printf( "Before clearCvec: cv.size = %d, cv.cap = %d\n", cv.size,cv.cap );
clearCvec( &cv );
printf( "After clearCvec: cv.size = %d, cv.cap = %d\n", cv.size,cv.cap );
}
else
printf( "There was a problem reading file %s\n", FNAME );
fputs( "\nPress 'Enter' to continue ... ", stdout );
getchar();
return 0;
} /* **************************************************** */
/* msort_Cvec_func_p_NO_VOID_Cstring.c */ /* this version 2016-10-09 */
/*
http://developers-heaven.net/forum/index.php/topic,46.0.html
*/
#define FNAME "randInt3M.txt"
#define THREE_MEG 3000000
#define HEADER "C program to sort 3 Million random int's from file stored " \
"in a Cvec ...\n" \
"(as C strings) ...\n" \
"Note: uses function pointers ... " \
"(*NO* void pointers used in msort compare)\n"
#include "readWord.h" /* includes <stdio.h>, <stdlib.h>, <strung.h> and ...
defines myAssert, newCopy ... as well as readWord */
#include <time.h>
typedef struct myRecOfString
{
char* str;
} Rec;
void clearRec( Rec* p )
{
free( p->str );
}
/* now can include these ...*/
#include "Cvec.h"
#include "Cvec_func's.h"
/* and ... define this ... */
int compare( const Rec* a, const Rec* b )
{
return strcmp(a->str, b->str ) ;
}
void myShowAll( Cvec* cv )
{
int i;
for( i = 0; i < cv->size; )
{
printf( "%6s ", cv->ary[i].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 < cv->size - 20 ) ++i;
for( ; i < cv->size; ++i ) printf( "%6s ", cv->ary[i].str );
break;
}
}
}
}
int main( void ) /* ********************************************************* */
{
FILE* fp;
double ti, tp;
char lastChr;
int i;
Rec r, r2;
Cvec cv;
initCvec( &cv ); /* Note: MUST initial to work */
reserveCvec( &cv, THREE_MEG );
puts( HEADER );
ti = clock();
fp = fopen( FNAME, "r" );
while( (r.str = readWord( fp, 5, " \n", &lastChr )) )
{
push_backCvec( &cv, &r ); /* since good Rec was obtained */
/* // if( cv.size == 100000 ) break; // */
}
tp = clock() - ti;
printf( "%d int's were read from file in %.2f sec's ... ",
cv.size, tp/CLOCKS_PER_SEC );
ti = clock();
msortCvec( &cv, compare );
tp = clock() - ti;
printf( "merge sorted in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( "\nand isSortedCvec( &cv, compare ) = %d\n",
isSortedCvec( &cv, compare ) );
ti = clock();
uniqueCvec( &cv, compare );
tp = clock() - ti;
printf( "\nuniqueCvec in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( " ... and isSortedCvec( &cv, compare ) = %d ",
isSortedCvec( &cv, compare ) );
printf( "\n... and isUniqueCvec( &cv, compare ) = %d\n",
isUniqueCvec( &cv, compare ) );
printf( "\nAfter uniqueCvec: cv.size = %d, cv.cap = %d\n", cv.size, cv.cap );
/* Note: 'newCopy' is now defined in readWord, as well as in readLine */
r2.str = newCopy( cv.ary[cv.size-1].str );
ti = clock();
i = findCvec( &cv, &r2, compare );
if( i != -1 )
{
eraseCvec( &cv, i );
tp = clock() - ti;
printf( "%s was erased ...", r2.str);
printf( "%s is new end str...\n", cv.ary[cv.size-1].str);
printf( "\nfind/ereaseCvec in %.2f sec's\n", tp/CLOCKS_PER_SEC );
}
else printf( "%s was NOT-found/NOT-erased ...", r2.str);
myShowAll( &cv );
free( r2.str );
printf( "\nBefore clearCvec: cv.size = %d\n", cv.size );
clearCvec( &cv );
printf( "After clearCvec: cv.size = %d\n", cv.size );
takeInChar( "\nPress 'Enter' to continue ... " );
return 0;
} /* ************************************************************************ */
/* msort_CvecOfInt.c */ /* this version 2016-10-09 */
/*
http://developers-heaven.net/forum/index.php/topic,46.0.html
*/
#define FNAME "randInt3M.txt"
#define VEC_CHUNK_SIZE 3000000 /* init Cvec cap to hold 3 Million random int's */
#define HEADER "C program to sort 3 Million random int's from file stored " \
"in C vector Cvec ...\n"
#include "CvecOfInt.h"
#include <time.h>
void myShowAll( Cvec* cv )
{
int i;
for( i = 0; i < cv->size; )
{
printf( "%6d ", cv->ary[i].val );
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 < cv->size - 20 ) ++i;
for( ; i < cv->size; ++i ) printf( "%6d ", cv->ary[i].val );
break;
}
}
}
}
int main( void ) /* ************************************* */
{
FILE* fp;
double ti, tp;
int i, valToFind;
Rec r;
Cvec cv;
initCvec( &cv ); /* Note: MUST initial Cvec v ... for Cvec to work */
puts( HEADER );
ti = clock();
fp = fopen( FNAME, "r" );
while( 1 == fscanf( fp, "%d", &r.val ) )
push_backCvec( &cv, &r ); /* since good Rec was obtained */
tp = clock() - ti;
printf( "%d int's were read from file in %.2f sec's ... ",
cv.size, tp/CLOCKS_PER_SEC );
ti = clock();
msortCvec( &cv );
tp = clock() - ti;
printf( "merge sorted in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( "\nand isSortedCvec( &v ) = %d\n", isSortedCvec( &cv ) );
ti = clock();
uniqueCvec( &cv );
tp = clock() - ti;
printf( "\nuniqueCvec in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( " ... and isSortedCvec( &cv ) = %d ", isSortedCvec( &cv ) );
printf( "\n... and isUniqueCvec( &cv ) = %d\n",
isUniqueCvec( &cv ) & cv.isSorted );
printf( "\nAfter uniqueCvec: cv.size = %d, cv.cap = %d\n\n", cv.size, cv.cap );
valToFind = cv.ary[cv.size-1].val;
ti = clock();
i = findCvec( &cv, valToFind );
if( i != -1 )
{
eraseCvec( &cv, i );
tp = clock() - ti;
printf( "%d was erased ...", valToFind);
printf( "%d is new end val...\n", cv.ary[cv.size-1].val);
printf( "find/ereaseCvec in %.2f sec's\n\n", tp/CLOCKS_PER_SEC );
}
else printf( "%d was NOT-found/NOT-erased ...\n\n", valToFind );
myShowAll( &cv );
printf( "Before clearCvec: cv.size = %d, cv.cap = %d\n", cv.size, cv.cap );
clearCvec( &cv );
printf( "After clearCvec: cv.size = %d, cv.cap = %d\n", cv.size, cv.cap );
fclose( fp );
fputs( "\nPress 'Enter' to continue ... ", stdout );
getchar();
return 0;
} /* **************************************************** */
/* msort_CvecOfString.c */ /* this version 2016-10-09 */
/*
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 Cvec ...\n ... as C strings ... " \
"(Note: using CvecOfString.h in this program)\n"
#include "readWord.h"
#include "CvecOfString.h" /* also includes readLine, but using readWord here */
#include <time.h>
void myShowAll( Cvec* cv )
{
int i;
for( i = 0; i < cv->size; )
{
printf( "%6s ", cv->ary[i].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 < cv->size - 20 ) ++i;
for( ; i < cv->size; ++i ) printf( "%6s ", cv->ary[i].str );
break;
}
}
}
}
int main( void ) /* ********************************************************* */
{
FILE* fp;
double ti, tp;
char lastChr, *s;
int i;
Rec r, r2;
Cvec cv;
initCvec( &cv ); /* Note: MUST initial to work */
reserveCvec( &cv, 3000000 );
puts( HEADER );
ti = clock();
fp = fopen( "randInt3M.txt", "r" );
while( (r.str = readWord( fp, 5, " \n", &lastChr )) )
{
push_backCvec( &cv, &r ); /* since good Rec was obtained */
/* // if( cv.size == 32768*4 ) break; // *11 ... to get all num's 0..32767 // */
}
tp = clock() - ti;
printf( "%d int's were read from file in %.2f sec's ... ",
cv.size, tp/CLOCKS_PER_SEC );
ti = clock();
msortCvec( &cv );
tp = clock() - ti;
printf( "merge sorted in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( "\nand isSortedCvec( &cv ) = %d\n", isSortedCvec( &cv ) );
ti = clock();
uniqueCvec( &cv );
tp = clock() - ti;
printf( "\nuniqueCvec in %.2f sec's", tp/CLOCKS_PER_SEC );
printf( " ... and isSortedCvec( &cv ) = %d ", isSortedCvec( &cv ) );
printf( "\n... and isUniqueCvec( &cv ) = %d\n", isUniqueCvec( &cv ) );
printf( "\nAfter uniqueCvec: cv.size = %d, cv.cap = %d\n\n", cv.size, cv.cap );
r2.str = newCopy( cv.ary[cv.size-1].str ); /* 'newCopy' def'd in readWord/readLine */
ti = clock();
i = findCvec( &cv, r2.str );
if( i != -1 )
{
eraseCvec( &cv, i );
tp = clock() - ti;
printf( "%s was erased ...", r2.str);
printf( "%s is new end str...\n", cv.ary[cv.size-1].str);
printf( "\nfind/ereaseCvec in %f sec's\n", tp/CLOCKS_PER_SEC );
}
else printf( "%s was NOT-found/NOT-erased ...", r2.str);
myShowAll( &cv );
free( r2.str );
ti = clock();
s = joinCvec( &cv, "," );
tp = clock() - ti;
printf( "\njoinCvec( &cv, \",\" ) 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 Cvec dynamic C string is :" );
s[70] = 0;
puts( s );
puts( "\nLast 70 char's in joined Cvec dynamic C string is :" );
puts( &s[i-70] );
free( s );
printf( "\nBefore clearCvec: cv.size = %d\n", cv.size );
clearCvec( &cv );
printf( "After clearCvec: cv.size = %d\n", cv.size );
takeInChar( "\nPress 'Enter' to continue ... ");
return 0;
} /* ************************************************************************ */
/* employeeRec's_vector.cpp */ /* this version: 2011-08-08 */
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm> /* re. vector sort, unique */
#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 vector< Employee > myVec;
typedef vector< Employee >::iterator myIter;
typedef vector< 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 myVec& vec )
{
size_t i = 0;
for( c_myIter p = vec.begin(); p != vec.end(); ++p )
{
cout << "<" << setfill('0') << setw(3) << ++i << "> " << setfill(' ');
show( *p );
if( i % 5 == 0 && i != vec.size() ) cout << endl;
}
cout << "\nEmployee records on file = " << vec.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( myVec& );
void readFile( myVec& );
bool isValidPhoneNum( const string& );
myIter getNameIgnoreCase( myVec&, const string& );
myIter getNumber( myVec&, const string& );
Employee enterEmployee();
void takeInRecAndFile( myVec& );
void writeSortedUnique( myVec& );
void editDel( myVec& );
void edit( myVec&, myIter& );
void del( myVec&, myIter& );
int main() /* ********************* MAIN BEGINS ***************************** */
{
int choice;
myVec 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( myVec& vec )
{
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 )
)
{
vec.push_back( d );
}
fin.close();
}
}
int showMenuGetChoice( myVec& vec )
{
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( vec );
else if( num == 2 )
{
cout << "Enter the name to find: " << flush;
getline(cin, tmp);
myIter it;
if( (it = getNameIgnoreCase( vec, tmp )) == vec.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( vec, tmp )) == vec.end() )
cout << tmp << " not found." << endl;
else
show( *it );
}
//else if( num == 4 ) showAll( vector );
else if( num == 5 ) sort( vec.begin(), vec.end(), cmpIgnoreCase );
else if( num == 6 ) sort( vec.begin(), vec.end(), cmpPhone );
else if( num == 7 )
{
sort( vec.begin(), vec.end(), cmpWithCase );
vec.erase( unique(vec.begin(), vec.end()), vec.end() );
}
else if( num == 8 ) editDel ( vec );
else if( num == 9 ) writeSortedUnique( vec );
/* 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( myVec& 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( myVec& 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( myVec& vec )
{
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;
vec.push_back( d );
cout << "Information has been filed in file " << FILENAME << endl;
}
else
{
cout << "Aborted ..." << endl;
}
fout.close();
}
void writeSortedUnique( myVec& vec )
{
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 */
sort( vec.begin(), vec.end(), cmpWithCase );
vec.erase( unique(vec.begin(), vec.end()), vec.end() );
int i = 0;
for( c_myIter it = vec.begin(); it != vec.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
<< ", vector size " << vec.size() << endl << endl;
/* and if have Windows OS ... can do this ... */
system( "notepad SU" FILENAME ); /*compiler concat's text at compile time*/
}
void editDel( myVec& vec )
{
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( vec, tmp )) == vec.end() )
cout << tmp << " not found." << endl;
else
{
show( *it );
reply = getChoice( "Edit/Delete/Abort (e/d/a) ? " );
if( reply == 'e' ) edit( vec, it );
else if( reply == 'd' ) del( vec, 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( vec, tmp )) == vec.end() )
cout << tmp << " not found." << endl;
else
{
show( *it );
reply = getChoice( "Edit/Delete/Abort (e/d/a) ? " );
if( reply == 'e' ) edit( vec, it );
else if( reply == 'd' ) del( vec, 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( myVec& vec, 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( myVec& vec, myIter& it )
{
for( ; ; )
{
int reply = getChoice( "Really delete/abort (d/a) ? " );
if( reply == 'a' )
{
cout << "Delete aborted ..." << flush;
return;
}
/* else ... */
if( reply == 'd' )
{
vec.erase( it );
return;
}
/* else ... */
cout << "Enter 'd' and WILL delete ... or 'a' to abort ..." << endl;
}
}