/* shell.c */ /* 2011-07-31 */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include <stdio.h>
int main()
{
/*
You may need to 'un-comment' the 'while( getchar != '\n' );' line BELOW,
to pause your program, IF (char's and) a '\n' char remains after/if 'input'
// effect of line below is same as 'clear/empty' all char's in stdin //
// while( getchar() != '\n' ); // 'flush' stdin buffer ... //
*/
fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
return 0;
}
/* more.c */ /* 2016-10-07 */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include <stdio.h>
int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
int reply;
fputs( "More (y/n) ? ", stdout ); fflush( stdout );
reply = getchar();
if( reply != '\n' ) while( getchar() != '\n' ); /* flush stdin ... */
if( reply == 'n' || reply == 'N' ) return 0;
/* else ... */
return 1;
}
int main()
{
int count = 0, sum = 0, testInt;
for( ; ; ) /* an example C/C++ forever loop ... until 'break' */
{
fputs( "Enter next integer to sum: ", stdout ); fflush( stdout );
if( scanf( "%d", &testInt ) == 1 && getchar() == '\n' )
{
++count;
sum += testInt;
/* make sure stdin buffer is 'empty' before calling 'more()' */
if( !more() ) break;
}
else
{
while( getchar() != '\n' ); /* 'flush' stdin ... */
puts( "Invalid input! Integers only please ..." );
}
}
printf( "\nFor %d numbers entered, sum was %d and average was %.2f\n",
count, sum, (float)sum/count );
fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
return 0;
}
/* getValidInt.c */ /* revised 2018-12-20 */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* re. strlen, strcpy, strchr... */
#include <ctype.h> /* re, tolower... */
#include <math.h> /* re. log10 ... */
#include <limits.h> /* re. INT_MIN, INT_MAX*/
#define BIG_BUF_LEN 1024
#define MAX_DIG_IN_INT ((int)log10(INT_MAX) + 1)
#define MAX_NAME_LEN 79
char* getLine( const char* msg )
{
static char buf[BIG_BUF_LEN];
char* p;
printf( msg );
fgets( buf, BIG_BUF_LEN, stdin );
/* fix fgets ... */
p = strchr( buf, '\n' );
if( p )
*p = 0; /* strip off '\n' char if present */
else
while( getchar() != '\n' ); /* flush stdin to end of line */
return buf;
}
/* since using 'static' buf inside, memory persists ... so can return address */
char* getLineMaxLen( const char* msg, unsigned maxLen )
{
char* line;
for( ; ; )
{
line = getLine( msg );
if( line[0] && strlen( line ) <= maxLen )
break;
else if( !line[0] )
printf( "\nBlank line NOT valid here ... \n" );
else
printf( "\nMax len of %u char's was exceeded ... \n", maxLen );
}
return line;
}
int getChar( const char* msg )
{
int reply;
fputs( msg, stdout ); fflush( stdout );
reply = getchar();
if( reply != '\n' )
while( getchar() != '\n' ) ; /* 'flush' stdin buffer */
return reply;
}
int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
if( tolower( getChar( "More (y/n) ? " )) == 'n' ) return 0;
/* else ... */
return 1;
}
/* Simple ... NO VALID range checking done here. */
int getInt( const char* prompt )
{
int testInt;
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
fputs( prompt, stdout ); fflush( stdout );
if( scanf( "%d", &testInt ) && getchar() == '\n' )
return testInt;
/* else ...*/
while( getchar() != '\n' ); /* 'flush' stdin ... as we go */
puts( "Invalid input! Integers only please ..." );
}
}
/* returns a valid int in range INT_MIN..INT_MAX */
int getValidInt( const char* prompt )
{
char loc_buf[16];
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
int good = 1, i, len, sign = 1;
char* tmp = getLine( prompt );
char* tmpCpy = tmp;
if( tmp[0] == '+' ) ++tmp;
else if( tmp[0] == '-') { ++tmp; sign = -1; }
len = i = strlen( tmp );
good = ( len > 0 && len <= MAX_DIG_IN_INT );
while( good && --i >= 0 )
good = isdigit( tmp[i] );
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 )
return atoi( tmpCpy );;
/* else ...*/
printf( "\n'%s' is NOT valid input here!\n", tmpCpy ) ;
}
}
/* returns a valid int in range min..max */
int getValidIntMinMax( const char* prompt, int min, int max )
{
int tmpInt;
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
tmpInt = getValidInt( 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 getValidIntPosMax( const char* prompt, int max )
{
return getValidIntMinMax( prompt, 0, max );
}
int main()
{
char name[MAX_NAME_LEN+1];
char gender;
int count = 0, id, testInt;
double sum = 0.0;
printf( "Max number of digits in a positive int is %d\n", MAX_DIG_IN_INT );
printf( "\nINT_MIN = %d, INT_MAX = %d\n\n", INT_MIN, INT_MAX );
do
{
strcpy( name, getLineMaxLen( "Enter name: ", MAX_NAME_LEN ));
id = getValidIntMinMax( "Enter ID in range 101..999: ", 101, 999 );
for( ; ; )
{
gender = toupper(getChar( "Enter gender (m/f): " ));
if( gender == 'M' || gender == 'F' )
break;
/* else ... */
printf( "\nTo proceed, you must enter either m or f ... try again.\n" );
}
testInt = getValidIntMinMax( "Enter next integer score to sum in range 0..100: ", 0, 100 );
sum += testInt;
++ count;
printf( "Hi %s, your ID is: %d, your sex is: %c\n", name, id, gender );
}
while( more() ); /* make sure stdin is 'empty' before calling 'more()' */
printf( "\nFor %d scores entered, sum was %.0f and average was %.2f\n",
count, sum, sum/count );
sum = 0.0;
count = 0;
do
{
testInt = getInt( "Enter next integer to sum: " );
sum += testInt;
++ count;
}
while( more() ); /* make sure stdin is 'empty' before calling 'more()' */
printf( "\nFor %d values entered, sum was %.0f and average was %.2f\n",
count, sum, sum/count );
/* keep 'Window' open until 'Enter' key is pressed ... */
getChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
/* arrayInt.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 <stdio.h>
#define MAX_SIZE 6 /* using a small size here for simple testing purposes ... */
int getInt( const char prompt[] )
{
int testInt;
while( 1 ) /* an example of a C/C++ forever loop ... until 'return' */
{
fputs( prompt, stdout ); fflush( stdout );
if( fscanf( stdin, "%d", &testInt ) == 1 && getchar() == '\n' )
return testInt;
/* else ...*/
while( getchar() != '\n' ); /* 'flush' stdin ... as we go ... */
puts( "Invalid input! Integers only please ..." );
}
}
int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
int c, reply;
fputs( "More (y/n) ? ", stdout ); fflush( stdout );
reply = c = getchar();
while( c != '\n' ) c = getchar(); /* 'flush' stdin buffer ... */
if( reply == 'n' || reply == 'N' ) return 0;
/* else ... */
return 1;
}
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 ] = getInt( "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 );
fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
return 0;
}
/* CvecInt.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" */
int getValidInt( const char prompt[] )
{
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
int numGood, testInt;
fputs( prompt, stdout ); fflush( stdout );
numGood = fscanf( stdin, "%d", &testInt );
while( getchar() != '\n' ); /* 'flush' stdin ... as we go ... */
if( numGood == 1 ) return testInt;
/*else ...*/
puts( "Invalid input! Integers only please ..." );
}
}
int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
int c, reply;
fputs( "More (y/n) ? ", stdout ); fflush( stdout );
reply = c = getchar();
while( c != '\n' ) c = getchar(); /* 'flush' stdin buffer ... */
if( reply == 'n' || reply == 'N' ) return 0;
/* else ... */
return 1;
}
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 = getValidInt( "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 msortCvec ... " );
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 = getValidInt( "\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 );
fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
return 0;
}
/* ClistInt.c */ /* 2016-10-06 */
/* 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" */
int getValidInt( const char prompt[] )
{
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
int numGood, testInt;
fputs( prompt, stdout ); fflush( stdout );
numGood = fscanf( stdin, "%d", &testInt );
while( getchar() != '\n' ); /* 'flush' stdin ... as we go ... */
if( numGood == 1 ) return testInt;
/*else ...*/
puts( "Invalid input! Integers only please ..." );
}
}
int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
int c, reply;
fputs( "More (y/n) ? ", stdout ); fflush( stdout );
reply = c = getchar();
while( c != '\n' ) c = getchar(); /* 'flush' stdin buffer ... */
if( reply == 'n' || reply == 'N' ) return 0;
/* else ... */
return 1;
}
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 = getValidInt( "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( "isSorted( &cl ) = %d\n", isSorted( &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 );
fputs( "\n\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
return 0;
}
/* CvecString.c */ /* testing CvecOfString.h */ /* 2016-06-21 */
/* enter 'word' data, concat, sort, find value, erase, show, unique ... */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#define VEC_CHUNK_SIZE 3
#include "CvecOfString.h" /* that also includes readLine.h that includes
stdio.h, stdlib.h, string.h, ctype.h and the
functions myAssert, newCopy, etc..
and then includes Cvec.h */
int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
int c;
fputs( "More (y/n) ? ", stdout ); fflush( stdout );
c = getchar();
if( c != '\n' ) while( getchar() != '\n' ) ; /* 'flush' stdin buffer */
if( c == 'n' || c == 'N' ) return 0;
/* else ... */
return 1;
}
int main()
{
int index;
char* last;
char* concatStr;
Cvec cv; /* create CvecOfString to hold all the C strings to be input */
initCvec( &cv ); /* Note: MUST inital cv for it to work */
do
{
Rec tmp; /* typedef struct ... Rec has CString member 'str' ... */
printf( "Enter next 'just one word' to concat: " ); fflush( stdout );
tmp.str = readLine( stdin );
push_backCvec( &cv, &tmp );
}
while( more() ); /* make sure stdin is 'empty' before calling more() */
concatStr = joinCvec( &cv, "," ); /* returns concated string in new memory */
printf( "\nFor %d words entered, joined words are: %s\n",
cv.size, concatStr );
free( concatStr );
printf( "\nshowCvec: " ); showCvec( &cv );
printf( "\nsize = %d, cap = %d\n", cv.size, cv.cap );
last = newCopy( cv.ary[ cv.size-1 ].str ); /* new copy in new memory */
/* isortCvec( &cv ); */
msort( &cv );
printf( "\n\nAfter sorting ..." );
printf( "\nshowCvec; " ); showCvec( &cv );
printf( "\nsize = %d, cap = %d\n", cv.size, cv.cap );
printf( "\nisSorted( &cv ) = %d\n", isSorted( &cv ) );
index = findCvec( &cv, last );
if( index >= 0 )
{
eraseCvec( &cv, index );
printf( "\nAfter eraseCvec of the element %s ...", last );
printf( "\nshowCvec: " ); showCvec( &cv );
printf( "\nsize = %d, cap = %d\n", cv.size, cv.cap );
}
else printf( "%s NOT found in Cvec.\n", last );
free( last );
uniqueCvec( &cv );
printf( "\n\nAfter uniqueCvec ..." );
printf( "\nsize = %d, cap = %d\n", cv.size, cv.cap );
/* now clean up all remaining still allocated dynamic memory */
/*//for( index = 0; index < cv.size; ++index ) free ( cv.ary[index].str );
//free( cv.ary ); */
clearCvec( &cv );
printf( "\nsize = %d, cap = %d\n", cv.size, cv.cap );
fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
return 0;
}
/* Cvec_func's.c */ /* testing Cvec_func's.h */ /* 2016-10-08 */
/* enter 'word' data, concat, sort, find value, erase, show, unique ... */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "readLine.h" /* readLine.h includes:
stdio.h, stdlib.h, string.h, ctype.h
and the functions: takeInChar, more,
myAssert, newnMem, newCopy, newsubstr etc.. */
typedef struct
{
char* str;
} Rec ;
void clearRec( Rec* rc )
{
free( rc->str );
}
#define VEC_CHUNK_SIZE 3
#include "Cvec.h"
void showCvec( const Cvec* cv )
{
int i;
for( i = 0; i < cv->size; ++i ) printf( "%s ", cv->ary[i].str );
}
int myRecCmp( const Rec* a, const Rec* b )
{
return strcmp( a->str, b->str );
}
#include "Cvec_func's.h"
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;
}
int main()
{
int index;
char* last;
char* concatStr;
Rec tmpRec;
Cvec cv; /* create CvecOfString to hold all the C strings to be input */
initCvec( &cv ); /* Note: MUST inital cv for it to work */
do
{
Rec tmp; /* typedef struct ... Rec has CString member 'str' ... */
if( cv.size )
{ printf( " Enter next 'word' to concat: " ); fflush( stdout ); }
else
{ printf( "Enter first 'word' to concat: " ); fflush( stdout ); }
tmp.str = readLine( stdin );
push_backCvec( &cv, &tmp );
}
while( more() ); /* make sure stdin is 'empty' before calling more() */
concatStr = joinCvec( &cv, "," ); /* returns concated string in new memory */
printf( "\nFor %d words entered, joined words are: %s\n",
cv.size, concatStr );
free( concatStr );
printf( "\nshowCvec: " ); showCvec( &cv );
printf( "\nsize = %d, cap = %d\n", cv.size, cv.cap );
last = newCopy( cv.ary[ cv.size-1 ].str ); /* new copy in new memory */
tmpRec.str = last;
/* isortCvec( &cv ); */
msortCvec( &cv, myRecCmp );
printf( "\n\nAfter sorting ..." );
printf( "\nshowCvec; " ); showCvec( &cv );
printf( "\nsize = %d, cap = %d\n", cv.size, cv.cap );
printf( "\nisSortedCvec( &cv, myRecCmp ) = %d\n", isSortedCvec( &cv, myRecCmp ) );
index = findCvec( &cv, &tmpRec, myRecCmp );
if( index >= 0 )
{
eraseCvec( &cv, index );
printf( "\nAfter eraseCvec of the element %s ...", last );
printf( "\nshowCvec: " ); showCvec( &cv );
printf( "\nsize = %d, cap = %d\n", cv.size, cv.cap );
}
else printf( "%s NOT found in Cvec.\n", last );
free( last );
uniqueCvec( &cv, myRecCmp );
printf( "\n\nAfter uniqueCvec ..." );
printf( "\nshowCvec: " ); showCvec( &cv );
printf( "\nsize = %d, cap = %d\n", cv.size, cv.cap );
/* now clean up all remaining still allocated dynamic memory */
/*//for( index = 0; index < cv.size; ++index ) free ( cv.ary[index].str );
//free( cv.ary ); */
clearCvec( &cv );
printf( "\nsize = %d, cap = %d\n", cv.size, cv.cap );
fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
return 0;
}
/* ClistString.c */ /* test program for new ClistOfString.h */ /* 2016-10-08 */
/* join list of 'words', msort, isort, insert_sorted, find, erase, show, unique */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "ClistOfString.h" /* that also includes readLine.h that includes:
stdio.h, stdlib.h, string.h, ctype.h ...
and functions: myAssert, newCopy, takeInChar, more, etc...
and then includes Clist.h */
void showMyClist( Clist* cl )
{
pNode p = cl->start;
for( ; p != NULL; p = p->next ) printf( "%s ", p->str );
printf( "\nsizeClist = %d\n", cl->size );
}
int main()
{
char* last;
char* concatStr;
pNode p;
Clist cl; /* create ClistOfString to hold all the words's to be input */
initClist( &cl );
do
{
Node tmp; /* typedef struct ... List has char* member 'str' ... */
printf( "Enter next word to join: " ); fflush( stdout );
tmp.str = readLine( stdin );
push_backClist( &cl, &tmp );
}
while( more() ); /* make sure stdin is 'empty' before calling more() */
concatStr = joinClist( &cl, "," );
printf( "\nFor %d 'words' entered, joined words are: %s\n",
cl.size, concatStr );
free( concatStr );
printf( "\nshowClist: " ); showClist( &cl );
last = newCopy( cl.end->str ); /* new copy in new memory */
isortClist( &cl );
/* msort( &cl ); */
printf( "\n\nAfter sorting ..." );
printf( "\nshowClist " ); showClist( &cl );
printf( "\nisSortedClist( &cl ) = %d\n", isSortedClist( &cl ) );
p = findClist( &cl, last );
if( p != NULL )
{
eraseClist( &cl, p );
printf( "\nAfter erasing Clist of the element %s ...", last );
printf( "\nshowClist: " ); showClist( &cl );
}
else printf( "%s NOT found in Clist.\n", last );
free( last );
uniqueClist( &cl );
printf( "\n\nAfter unique ..." );
printf( "\nmy_showClist " );
showMyClist( &cl );
do
{
Node tmp; /* typedef struct ... List has char* member 'str' ... */
printf( "Enter next word to push_front: " ); fflush( stdout );
tmp.str = readLine( stdin );
push_frontClist( &cl, &tmp );
}
while( more() );
printf( "\n\nAfter push_front ..." );
printf( "\nmy_showClist " );
showMyClist( &cl );
printf( "Enter next word to insert_sorted: " ); fflush( stdout );
p = (pNode) malloc( sizeof(Node) );
p->str = readLine( stdin );
myAssert( (p != NULL), "Error! malloc failed next word to insert_sorted" );
insert_sortedClist( &cl, p );
printf( "\n\nAfter insert_sorted ..." );
printf( "\nmy_showClist " );
showMyClist( &cl );
clearClist( & cl );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
/* Clist_func's.c */ /* test program for new Clist_func's.h */ /* 2016-10-08 */
/* join list of 'words', msort, isort, insert_sorted, find, erase, show, unique */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "ClistOfString.h" /* that also includes readLine.h that includes:
stdio.h, stdlib.h, string.h, ctype.h ...
and the functions: myAssert, newCopy, takeInChar, more, etc...
and then includes Clist.h */
void showMyClist( Clist* cl )
{
pNode p = cl->start;
for( ; p != NULL; p = p->next ) printf( "%s ", p->str );
printf( "\nsizeClist = %d\n", cl->size );
}
int main()
{
char* last = NULL;
char* concatStr;
Node tmp; /* typedef struct ... Node has char* member 'str' */
pNode p;
Clist cl; /* create ClistOfString to hold all the words's to be input */
initClist( &cl );
for( ; ; )
{
printf( "Enter next word to join: " ); fflush( stdout );
tmp.str = readLine( stdin );
if( strlen( tmp.str ) )
{
push_backClist( &cl, &tmp );
if( !more() ) /* make sure stdin is 'empty' before calling more() */
break;
}
else
{
free( tmp.str );
puts( "Empty entries NOT accepted here ... " );
}
}
concatStr = joinClist( &cl, "," );
printf( "\nFor %d 'words' entered, joined words are: %s\n",
cl.size, concatStr );
free( concatStr );
printf( "\nshowClist: " ); showClist( &cl );
if( !last )
last = newCopy( cl.end->str ); /* new copy in new memory */
isortClist( &cl );
/* msort( &cl ); */
printf( "\n\nAfter sorting ..." );
printf( "\nshowClist " ); showClist( &cl );
printf( "\nisSortedClist( &cl ) = %d\n", isSortedClist( &cl ) );
p = findClist( &cl, last );
if( p != NULL )
{
eraseClist( &cl, p );
printf( "\nAfter erasing Clist of the element %s ...", last );
printf( "\nshowClist: " ); showClist( &cl );
}
else printf( "%s NOT found in Clist.\n", last );
free( last );
uniqueClist( &cl );
printf( "\n\nAfter unique ..." );
printf( "\nshowMyClist " );
showMyClist( &cl );
do
{
Node tmp; /* typedef struct ... List has char* member 'str' ... */
printf( "Enter next word to push_front: " ); fflush( stdout );
tmp.str = readLine( stdin );
push_frontClist( &cl, &tmp );
}
while( more() );
printf( "\n\nAfter push_front ..." );
printf( "\nshowMyClist " );
showMyClist( &cl );
printf( "Enter next word to insert_sorted: " ); fflush( stdout );
p = (pNode) malloc( sizeof(Node) );
p->str = readLine( stdin );
myAssert( (p != NULL), "Error! malloc failed next word to insert_sorted" );
insert_sortedClist( &cl, p );
printf( "\n\nAfter insert_sorted ..." );
printf( "\nshowMyClist " );
showMyClist( &cl );
clearClist( & cl );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
// bankAccount.c // 2011-02-16 //
// http://developers-heaven.net/forum/index.php/topic,46.0.html
#include <stdio.h>
int getValidInt( const char prompt[] )
{
for( ;; ) // an example of a C/C++ forever loop ... until 'return'
{
int testInt, numGoodValues;
printf( "%s", prompt ); fflush( stdout );
numGoodValues = scanf( "%d", &testInt );
while( getchar() != '\n' ) ; /* flush stdin buffer ... */
if( numGoodValues == 1 ) return testInt;
// else ...
puts( "Invalid input! Integers only please ..." );
}
}
int more()// defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered
{
int c, reply;
fputs( "More (y/n) ? ", stdout ); fflush( stdout );
reply = c = getchar();
while( c != '\n' ) c = getchar(); /* flush stdin buffer ... */
if( reply == 'n' || reply == 'N' ) return 0;
// else ...
return 1;
}
int transactions( int* deposits, int* withdrawals )
{
int net = 0;
puts( "(Enter a negative value to indicate withdrawal)" );
for( ;; )
{
int amount = getValidInt( "Enter dollars for this transaction (0 to exit) : " );
if( amount > 0 ) ++ *deposits;
else if( amount < 0 ) ++ *withdrawals;
else return net;
net += amount;
}
}
void showResults( int balance, int deposits, int withdrawals, int net_change )
{
printf( "Opening balance : %d\n", balance );
printf( "Number of deposits : %d\n", deposits );
printf( "Number of withdrawals : %d\n", withdrawals );
printf( "Closing balance : %d\n", balance + net_change );
}
int main()
{
do
{
int balance = getValidInt( "Please enter your new starting balance (dollars) : " );
int deposits = 0, withdrawals = 0;
int net_change = transactions( &deposits, &withdrawals ); /* passing addresses ... */
showResults( balance, deposits, withdrawals, net_change );
}
while( more() ); // make sure cin stream is 'empty' before calling 'more()' ...
return 0;
}
/* incomeTax.c */ /* 2011-08-29 */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include <stdio.h>
#define STD_DEDUCT 11000 // in dollars
#define NO_TAX_ON 11000 // in dollars
#define STEP_UP_2 22000 // tax step size in dollars
#define TAX_RATE 0.11 // beginning tax rate of taxable income
#define MAX_FRAC 0.33 // of taxable income
int getValidInt( const char prompt[] )
{
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
int numGood, testInt;
fputs( prompt, stdout ); fflush( stdout );
numGood = fscanf( stdin, "%d", &testInt );
while( getchar() != '\n' ); /* 'flush' stdin ... as we go ... */
if( numGood == 1 ) return testInt;
/*else ...*/
puts( "Invalid input! Integers only please ..." );
}
}
int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
int c, reply;
fputs( "More (y/n) ? ", stdout ); fflush( stdout );
reply = c = getchar();
while( c != '\n' ) c = getchar(); /* 'flush' stdin buffer ... */
if( reply == 'n' || reply == 'N' ) return 0;
/* else ... */
return 1;
}
int getTotDeductions()
{
return getValidInt( "Enter the total sum of all allowable deductions: " );
}
double incomeTax()
{
int grossIncome = getValidInt( "Enter gross income in dollars: " );
int deduction = getTotDeductions();
int netIncome, taxIncome;
double rate, tax = 0.0, taxIncomeTmp;
if( deduction < STD_DEDUCT ) deduction = STD_DEDUCT;
if( deduction >= grossIncome ) netIncome = 0;
else netIncome = grossIncome - deduction;
taxIncome = netIncome - NO_TAX_ON;
if( taxIncome < 0 ) taxIncome = 0;
rate = TAX_RATE;
taxIncomeTmp = taxIncome;
while( taxIncomeTmp >= STEP_UP_2 && tax < taxIncome*MAX_FRAC
&& rate < MAX_FRAC )
{
tax += rate*STEP_UP_2;
/* printf( "%14.2f\n", rate*STEP_UP_2 ); */
rate *= (1+TAX_RATE);
taxIncomeTmp -= STEP_UP_2;
}
if( taxIncomeTmp > 0 ) tax += rate*taxIncomeTmp;
if( tax > taxIncome*MAX_FRAC ) tax = taxIncome*MAX_FRAC;
printf( "Your deduction: %d\n", deduction );
printf( "Your netincome: %d\n", netIncome );
printf( "Your taxincome: %d\n", taxIncome );
printf( "Your tax rate: %0.6f\n", ( taxIncome > 0 ? tax/taxIncome : 0 ) );
return tax;
}
int main()
{
do
{
double tax = incomeTax();
printf( "Your income tax this year is: %.2f\n", tax );
}
while( more() ); // make sure stdout is 'empty' before calling more()
return 0;
}
/* familyData3File.c */ /* 2016-10-16 */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "readLine.h" /* Now includes functions: takeInChar, more ... */
#define THIS_YEAR 2016
#define MAX 99 /* max number of family records allowed in array of ... */
#define FNAME "familyData3File.txt"
#define MENU "\na A dd data\n" \
"s S how all data\n" \
"o O rder/s O rt all data\n" \
"u U pdate file\n" \
"q Q uit\n" \
"Your choice A, S, U, O, Q: "
typedef struct
{
char* fname;
char* lname;
char* dob; /* enter in YYYYMMDD format like this example 19080524 */
} FamilyData;
int showMenuGetChoice()
{
return takeInChar( MENU );
}
void show( const FamilyData data[], int size )
{
int i;
printf( "The %d family data are:\n", size );
for( i = 0; i < size; ++ i )
printf( "%s %s %s\n", data[i].fname, data[i].lname, data[i].dob );
}
int readFile( FamilyData data[], int maxSize )
{
int size = 0;
FILE* fin = fopen( FNAME, "r" );
if( fin )
{
while( (data[size].fname = readLine( fin )) != NULL
&& (data[size].lname = readLine( fin )) != NULL
&& (data[size].dob = readLine( fin )) != NULL )
{
++ size;
if( size == maxSize)
{
printf( "The MAX number %d of family data handled "
"here has been reached.\n", MAX );
break;
}
}
fclose( fin );
}
else
{
printf( "There was an error opening file %s\n", FNAME );
printf( "Perhaps it has NOT been created yet ...\n"
"but will be created at the end of this program?\n\n" );
}
return size;
}
int updateFile( const FamilyData data[], int size )
{
int i;
FILE* f = fopen( FNAME, "w" );
myAssert( (f != NULL), "Error! File NOT opened to write!" );
for( i = 0; i < size; ++ i )
fprintf( f, "%s\n%s\n%s\n", data[i].fname, data[i].lname, data[i].dob );
fclose( f );
return i;
}
int isLeapYear( int y )
{
if( y % 4 != 0 ) return 0;
if( y % 100 == 0 && y % 400 != 0 ) return 0;
return 1;
}
int daysInMonth( int m, int y )
{ /* ------------===----------- > jan feb mar apr may jun
---------------------- > jul aug sep oct nov dec */
static int daysInMonth[] = { 0, 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };
int days = daysInMonth[m];
if( m == 2 && isLeapYear( y )) ++days;
return days;
}
int isValidDate( const char* dob )
{
char buffer[5] = { 0 };
int y, m, d;
if( strlen( dob ) != 8 ) return 0;
strncpy( buffer, dob, 4 );
y = atoi( buffer );
if( y < 1600 || y > THIS_YEAR ) return 0; /* since not valid year here */
strncpy( buffer, dob+4, 2 );
buffer[2] = 0; /* 0 terminate ... */
m = atoi( buffer );
if( m < 1 || m > 12 ) return 0; /* since not valid month ... */
d = atoi( dob+6 );
if( d < 1 || d > daysInMonth( m, y )) return 0; /* since not valid day */
/* else ... if reach here ... must be valid date, so ... */
return 1;
}
int addMembers( FamilyData data[], int iStart )
{
if( iStart == MAX )
{
printf( "The MAX number %d of family data handled "
"here has been reached.\n", MAX );
return iStart;
}
do
{
char * firstName, * lastName, * dob;
fputs( "Enter first name: ", stdout ); fflush( stdout );
firstName = readLine( stdin );
firstName[0] = toupper( firstName[0] );
fputs( "Enter last name: ", stdout ); fflush( stdout );
lastName = readLine( stdin );
lastName[0] = toupper( lastName[0] );
fputs( "Enter dob: ", stdout ); fflush( stdout );
dob = readLine( stdin );
printf( "Your entered %s %s %s ... ",
firstName, lastName, dob );
if( tolower(takeInChar( "Ok (y/n) ? ")) != 'y' ||
!isValidDate( dob ))
{
if( !isValidDate( dob ) )
printf( "DOB: %s is NOT valid. ", dob );
free( dob ); free( lastName ); free( firstName );
fputs( "Aborted ... try entry again ... ", stdout );
continue;
}
data[iStart].lname = lastName; /* copy pointers (addresses) ... */
data[iStart].fname = firstName;
data[iStart].dob = dob;
++ iStart;
if( iStart == MAX)
{
printf( "The MAX number %d of family data handled "
"here has been reached.\n", MAX );
break;
}
/* make sure stdin is 'empty' before calling 'choose( "More" )' */
} while( more() );
return iStart;
}
void clean( FamilyData data[], int num )
{
int i;
for( i = num-1; i >= 0; -- i )
{
free( data[i].dob );
free( data[i].lname );
free( data[i].fname );
}
}
int compareLnameDOB( const FamilyData* a, const FamilyData* b )
{
int tmp = strcmp(a->lname, b->lname);
if( tmp != 0 ) return tmp;
return strcmp(a->dob, b->dob);
}
/* sorted by last name ... then DOB */
void isortLnameDOB( FamilyData ary[], int size )
{
int i, j;
/* start with an array of just the first 2 elements (if exists) */
for( i = 1; i < size; ++i )
{
/* get copy of this pointer on each outer loop */
FamilyData cmp = ary[i];
/* get index of element just to the left of the above 'cmp'
to start comparisons */
j = i-1;
while( j >= 0 && compareLnameDOB(&cmp, &ary[j]) < 0 )
{
ary[j+1] = ary[j]; /* copy pointer 'up' ... */
--j; /* decrement j in preparation for next inner loop ... */
}
ary[j+1] = cmp; /* insert pointer at index j+1
(since j was decremented above) */
}
}
int compareFnameDOB( const FamilyData* a, const FamilyData* b )
{
int tmp = strcmp(a->fname, b->fname);
if( tmp != 0 ) return tmp;
return strcmp(a->dob, b->dob);
}
/* sorted by first names ... then DOB ... */
void isortFnameDOB( FamilyData ary[], int size )
{
int i, j;
/* start with an array of just the first 2 elements (if exists) */
for( i = 1; i < size; ++i )
{
/* get copy of this pointer on each outer loop */
FamilyData cmp = ary[i];
/* get index of element just to the left of the above 'cmp'
to start comparisons */
j = i-1;
while( j >= 0 && compareFnameDOB(&cmp, &ary[j]) < 0 )
{
ary[j+1] = ary[j]; /* copy pointer 'up' ... */
/* decrement j in preparation for next inner loop ... */
--j;
}
/* insert pointer at index j+1 (since j was decremented above) */
ary[j+1] = cmp;
}
}
int compareDOBfname( const FamilyData* a, const FamilyData* b )
{
int tmp = strcmp(a->dob, b->dob);
if( tmp != 0 ) return tmp;
return strcmp(a->fname, b->fname);
}
/* sorted by DOB ... then fname ... */
void isortDOBfname( FamilyData ary[], int size )
{
int i, j;
for( i = 1; i < size; ++i ) /* start with an array of just
the first 2 elements (if exists) */
{
FamilyData cmp = ary[i]; /* get copy of this 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 && compareDOBfname(&cmp, &ary[j]) < 0 )
{
ary[j+1] = ary[j]; /* copy pointer 'up' ... */
--j; /* decrement j in preparation for next inner loop ... */
}
ary[j+1] = cmp; /* insert pointer at index j+1
(since j was decremented above) */
}
}
void sort( FamilyData fm[], int size )
{
switch( takeInChar( "Sort by 1. DOB & firstname, "
"2. firstname & DOB, 3. lastname & DOB : ") )
{
case '1': isortDOBfname( fm, size ); break;
case '2': isortFnameDOB( fm, size ); break;
case '3': isortLnameDOB( fm, size ); break;
default: puts( "Sort request NOT valid here!" );
}
}
int main()
{
FamilyData data[MAX];
int choice;
int loop = 1;
int count = readFile( data, MAX );
if( count ) show( data, count );
while( loop )
{
switch( (choice = showMenuGetChoice()) )
{
case 'a': case 'A': count = addMembers( data, count ); break;
case 's': case 'S': putchar( '\n' ); show( data, count ); break;
case 'o': case 'O': sort( data, count ); break;
case 'u': case 'U': updateFile( data, count ); break;
case 'q': case 'Q': loop = 0; break;
default: printf( "'%c' is NOT a valid choice here!", choice );
}
}
clean( data, count );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
/* Cvec_of_struct_with_Clist.c */ /* a demo/test program */ /* 2016-10-08 */
/*
A simulation of a 'road' ... using a Cvec to hold each road section
-> each Rec (record/struct) in the Cvec holds the ...
-> new speed limit and also ...
-> a Clist of points ... for that speed and section of the road.
-> the last Rec holds the final speed and the final point(s) in the 'road'
-> In a loop until done, the program asks/gets from the user ...
-> each new speed ... and then, for this new section with that speed,
-> a Clist of points
-> After 'road' data is all entered, the program calculates and displays
-> the distance travelled
-> the time taken
-> the average speed travelled for the distance and time
-> Note: this program assumes that 'the speed limit' equals
... the average speed travelled during each new section
... and sub section
*/
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* re. memcpy */
typedef struct ClistOfPoint
{
int x;
int y;
struct ClistOfPoint* next;
} Node ; /* i.e. ... a node/element/record in the Clist ... */
typedef Node* pNode;
void clearNode( pNode p )
{
/* no dynamic C strings, etc... to free here ... */
p = p;
}
void showNode( pNode p ) /* show this point ... */
{
printf( "(%d, %d) ", p->x, p->y );
}
#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 "Clist.h"
/* and now can define ... */
void showClist( Clist* list ) /* show all points in this Clist ... */
{
if( list->size )
{
pNode p = list->start;
for( ; p != NULL; p = p->next )
{ showNode( p ); putchar( '\n' ); } /* each point on a new line */
printf( "Node size = %d\n", list->size );
}
else puts( "The list is empty ... " );
}
/* and now ... getting ready for the Cvec of Rec's */
typedef struct
{
int speed;
Clist points;
} Rec ;
void clearRec( Rec* rc ) /* clear this Rec ... */
{
clearClist( & rc->points ); /* clear this list of points */
}
/* Ok ... NOW can include ... */
#include "Cvec.h"
/* fuctions used by main ... */
int getValidInt( const char prompt[] );
int more( const char prompt[] );
float getDist( const Node span[] );
int cal_and_show_stats ( Cvec* cv );
int main() /* /////////////////////////////////////////////////////////////// */
{
Cvec cv;
Rec cr;
int i, spans;
initCvec( & cv );
do /* for each 'section' ... */
{
initClist( &cr.points ); /* for each new Clist of points ... */
cr.speed = getValidInt( "Enter next speed: " );
putchar( '\n' );
do /* now get all points at this speed in this section ... */
{
Node lr; /* 'lr' used to hold x and y of each new point ... */
lr.x = getValidInt( "Enter next x: " );
lr.y= getValidInt( "Enter next y: " );
push_backClist( &cr.points, &lr ); /* Ok ... add this point ... */
}
while( more( "points" ) );
push_backCvec( &cv, &cr ); /* ok ... add this 'section' ... */
putchar( '\n' ); /* get ready/space for next section*/
}
while( more( "sections" ) ); /* make sure stdin 'empty' before call more() */
puts( "\n\nShowing vector ..." );
for( i = 0; i < cv.size; ++i )
{
printf( "Points for section %d, with speed %d\n", i+1, cv.ary[i].speed );
showClist( & cv.ary[i].points ); /* now ... show this set of points ... */
putchar( '\n' );
}
spans = cal_and_show_stats( &cv );
printf( "Number of sections = %d, number of spans = %d\n", cv.size, spans );
clearCvec( &cv ); /* now free all dynamic memory ... */
fputs( "\nPress 'Enter' to continue/exit ... ", stdout); fflush( stdout );
getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
return 0;
} /* //////////////////////////////////////////////////////////////////////// */
int getValidInt( const char prompt[] )
{
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
int numGood, testInt;
fputs( prompt, stdout ); fflush( stdout );
numGood = fscanf( stdin, "%d", &testInt );
while( getchar() != '\n' ); /* 'flush' stdin ... as we go ... */
if( numGood == 1 ) return testInt;
/*else ...*/
puts( "Invalid input! Integers only please ..." );
}
}
/* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
int more( const char prompt[] )
{
int c, reply;
printf( "More %s (y/n) ? ", prompt ); fflush( stdout );
reply = c = getchar();
while( c != '\n' ) c = getchar(); /* 'flush' stdin buffer ... */
if( reply == 'n' || reply == 'N' ) return 0;
/* else ... */
return 1;
}
float getDist( const Node span[] ) /* return sqrt( deltaX*deltaX + deltaY*deltaY ); */
{
return sqrt( (span[0].x-span[1].x)*(span[0].x-span[1].x)
+ (span[0].y-span[1].y)*(span[0].y-span[1].y) );
}
int cal_and_show_stats( Cvec* cv ) /* ... and return count of spans */
{
float dd, d = 0, t = 0;
int spans = 0;
if( cv->size > 1 || (cv->size && cv->ary[0].points.size > 1) )
{
int i;
Node span[2]; /* Note: a 'span' is an array of 2 points ... */
Node* p = cv->ary[0].points.start; /* get address of first point ... */
span[0].x = p->x; /* get x of 1st point in span ... */
span[0].y = p->y; /* get y of 1st point in span ... */
for( i = 0 ; i < cv->size ; )
{
if( p->next != NULL )
{
p = p->next;
span[1].x = p->x; /* get x of 2nd point in span ... */
span[1].y = p->y; /* get y of 2nd point in span ... */
dd = getDist( span ); /* get distance of this span ... */
d += dd; /* add to total distance ... */
t += dd/cv->ary[i].speed; /* find/add time taken ... to total */
++ spans;
}
else
{
++i;
if( i == cv->size ) break;
p = cv->ary[i].points.start;
span[1].x = p->x;
span[1].y = p->y;
dd = getDist( span );
d += dd;
t += dd/cv->ary[i].speed;
++ spans;
}
printf( "So far, distance = %f, time = %f "
"and average speed = %f\n", d, t, d/t );
span[0].x = span[1].x; /* update ... 1st point in next span ...*/
span[0].y = span[1].y;
}
}
printf( "\n\nFinals:\n"
"Total distance = %f and time = %f and average speed = %f\n",
d, t, d/t );
return spans;
}
/* Clist_of_struct.c */ /* 2016-10-08 */
/* an interesting student problem to find a record in a list of records ... */
/* using ... 'none' to 'all' ... of multiple search pararmeters */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
#include "readLine.h" /* includes stdio.h, stdlib.h, string.h, takeInChar, more, etc... */
#define FILE_NAME "student.dat"
const char* CODES =
"ALL NONE n=lastName i=Id d=Dob(yymmdd) g=Gender(m,f) s=Status(F,S,J,S,G)";
typedef struct myStudent
{
char* lname; /* last name */
int id,
dob; /* yyyymmdd */
char gender, /* 'M' or 'F' */
status; /* 'F' or 'S' or 'J' or 'G' */
struct myStudent* next;
} Node ;
typedef Node* pNode;
void clearNode( Node* p )
{
free( p->lname );
}
#define Student Node /* from here on ... equate 'Node' with 'Student' */
/* Ok ... now can ... */
#include "Clist.h"
int getValidInt( const char* prompt );
void showStudent( const Student* s );
void showClist( const Clist* s );
void inputStudent( Student* s );
int hasChNotInStr( const char* t, const char* s );
int matchList( const Student* m, const Student* t, const char* matchStr );
void showMatching( const Clist* s );
void saveToFile( const Clist* myList );
void fillFromFile( FILE* fin, Clist* myList );
int main() /* ////////// BEGIN MAIN ///////////////////// */
{
FILE* fin;
Clist myLst; /* create an empty list to hold Students ... */
initClist( &myLst );
fin = fopen( FILE_NAME, "r" );
if( fin )
fillFromFile( fin, &myLst );
else /* get some data to work with ... */
{
do
{
Student tmp;
inputStudent( &tmp );
push_backClist( &myLst, &tmp );
} /* make sure stdin is 'empty' before calling 'more' */
while( more() );
saveToFile( &myLst ); /* create/store file ... */
}
if( myLst.size)
{
showClist( & myLst );
putchar( '\n' );
}
do
{
showMatching( &myLst );
}
while( more() );
clearClist( &myLst );
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
} /* ///////////////// END MAIN ///////////////////////// */
int getValidInt( const char* prompt )
{
for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
int numGood, testInt;
fputs( prompt, stdout ); fflush( stdout );
numGood = fscanf( stdin, "%d", &testInt );
while( getchar() != '\n' ); /* 'flush' stdin ... as we go ... */
if( numGood == 1 ) return testInt;
/*else ...*/
puts( "Invalid input! Integers only please ..." );
}
}
void showStudent( const Student* s )
{
printf( "%s %d %d %c %c", s->lname, s->id, s->dob, s->gender, s->status );
}
void showClist( const Clist* s )
{
pNode i = s->start;
for( ; i != NULL; i = i->next )
{ showStudent( i ); putchar( '\n' ); }
}
void inputStudent( Student* s )
{
for( ;; )
{
s->id = getValidInt( "Enter id number : " );
s->dob = getValidInt( "Enter dob (yyyymmdd) : " );
s->gender = toupper(takeInChar( "Enter gender (M/F) : " ));
s->status = toupper(takeInChar( "Enter status (F/S/J/S/G) : " ));
fputs( "Enter last name : ", stdout ); fflush( stdout );
s->lname = strToUpper(readLine( stdin ));
printf( "You entered: %s %d %d %c %c\n",
s->lname, s->id, s->dob, s->gender, s->status );
if( toupper(takeInChar("Is this entry ok (y/n) ? ")) == 'Y' )
break;
/* else ... */
free( s->lname );
puts( "Ok ... this entry aborted ... try again ... " );
}
}
int hasChNotInStr( const char* t, const char* s )
{
for( ; *t ; ++t )
if( strchr( s, *t ) == NULL ) return 1;
/* else ... */
return 0;
}
int matchList( const Student* m, const Student* t, const char* matchStr )
{
if( strchr( matchStr, 'N' )) if( strcmp(m->lname, t->lname) != 0 ) return 0;
if( strchr( matchStr, 'I' )) if( m->id != t->id) return 0;
if( strchr( matchStr, 'D' )) if( m->dob!= t->dob ) return 0;
if( strchr( matchStr, 'G' )) if( m->gender != t->gender ) return 0;
if( strchr( matchStr, 'S' )) if( m->status != t->status ) return 0;
/* else ...i */
return 1;
}
/* match string is like this "nidgs" to match on all ... */
void showMatching( const Clist* s )
{
Student find;
pNode p;
const char* valid = "NIDGS";
char* matchOn;
int aMatch = 0;
for( ; ; )
{
puts( CODES );
fputs( "Enter 'match criteria string' ... "
"i.e. all, some or none of 'nidgs' : ", stdout );
fflush( stdout );
matchOn = strToUpper(readLine( stdin ));
if( strcmp( matchOn, "ALL" ) == 0 )
{ free(matchOn); matchOn = newCopy(valid); break; }
else if( strcmp(matchOn, "NONE" ) == 0 )
{ *matchOn = 0; break; }
else if( !hasChNotInStr( matchOn, valid ) )
break;
/* else ... */
printf( "%s is not valid here ...\n\n", matchOn );
}
/* printf( "\n\n ... now matchOn = %s \n\n", matchOn ); */
find.lname = NULL;
if( strchr( matchOn, 'N' ))
{
fputs( "Enter last name to find: ", stdout ); fflush( stdout );
find.lname = readLine( stdin ); strToUpper( find.lname );
}
if( strchr( matchOn, 'I' ))
{
find.id = getValidInt( "Enter id to find: " );
}
if( strchr( matchOn, 'D' ))
{
find.dob = getValidInt( "Enter dob to find: " );
}
if( strchr( matchOn, 'G' ))
{
find.gender = toupper( takeInChar("Enter gender to find: ") );
}
if( strchr( matchOn, 'S' ))
{
find.status = toupper( takeInChar("Enter status to find: ") );
}
/* Now ... show all records that match all selection criteria ... */
for( p = s->start; p != NULL; p = p->next )
{
if( matchList( p, &find, matchOn ))
{
aMatch = 1;
printf( "%s %d %d %c %c\n",
p->lname, p->id, p->dob, p->gender, p->status );
}
}
if( !aMatch ) puts( "No matches ... " );
putchar( '\n' );
free( matchOn );
if( find.lname != NULL )
free( find.lname );
}
void saveToFile( const Clist* myList )
{
FILE* fout = fopen( FILE_NAME, "w" );
if( fout )
{
pNode i = myList->start;
for( ; i != NULL; i = i->next )
fprintf( fout, "%s %d %d %c %c\n",
i->lname, i->id, i->dob, i->gender, i->status );
fclose( fout );
}
else
printf( "There was a problem opening file %s for output.\n", FILE_NAME );
}
void fillFromFile( FILE* fin, Clist* myList )
{
char nameBuf[80];
char* line;
while( (line = readLine(fin)) )
{
Student tmp;
/*
char *p = line, *q;
while( *p != ' ' ) ++p;
*p = 0;
tmp.lname = newCopy( line );
q = ++p;
while( *p != ' ' ) ++p;
*p = 0;
tmp.id = atoi( q );
q = ++p;
while( *p != ' ' ) ++p;
*p = 0;
tmp.dob = atoi( q );
tmp.gender = * ++p ;
++p;
tmp.status = * ++p ;
*/
sscanf( line, "%s %d %d %c %c", nameBuf,
&tmp.id, &tmp.dob, &tmp.gender, &tmp.status );
tmp.lname = newCopy( nameBuf );
push_backClist( myList, &tmp );
free( line );
}
fclose( fin );
}
JOE 1 19900101 M S
SAM 2 19910101 M F
JIL 3 19900101 F S
SUE 4 19910101 F F
TAM 5 19811203 F G
JUN 6 19890101 F J
TOM 7 19900101 M J
/* phnBook1.c */ /* using a dynamic array to hold Contacts ... version 1 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 1024 /* pick an extra large size, to ensure? large enough ... */
const int BEGIN_SIZE = 8; /* pick begin size to minimize calls to realloc ... */
int SIZE = 0; /* Global variable used to keep track of number of Contacts */
int CAP = 0; /* Global variable used to keep track of capacity for Contacts */
typedef struct myContact
{
char firstName[21]; /* NOTE! max num of char's for firstname is 20 */
char lastName[21]; /* NOTE! MUST LEAVE ROOM for terminal '\0' char */
char phoneNumber[11]; /* NOTE! max num of char's for phoneNumber is 10 */
} Contact ;
Contact* addContact( Contact* );
void deleteContact( Contact* );
void showAllContacts( Contact* );
void sortByFirstName( Contact* );
/* shows 'msg' string and returns right sized C string 'getstr' passed in ... */
void getString( const char* msg, char* getstr, int maxSize, int minSize )
{
char *p, buffer[BUFSIZE];
int len;
for( ; ; ) /* loop forever ... until break ... */
{
printf( msg );
fflush( stdout );
fgets( buffer, BUFSIZE, stdin );
p = strchr( buffer, '\n' );
if( p != NULL ) *p = 0; /* eliminate '\n' char at end of C string */
len = strlen(buffer);
if( len <= maxSize && len >= minSize ) break;
/* else... */
printf( "\nERROR! Input must have length in range %d..%d\n",
minSize, maxSize );
}
/* when reach here ... a good len was input ... */
strcpy(getstr, buffer); /* getstr is retuned 'by ref' ... */
}
int main( void )
{
int iSelection = 0, numGood;
Contact* phonebook = NULL;
printf( "Size of each record = sizeof(Contact) = %d bytes ...\n",
sizeof(Contact) );
while( iSelection != 5 )
{
printf( "\n\t\t\tContact Menu" );
printf( "\n\n\t(1)\tAdd Contact" );
printf( "\n\t(2)\tDelete Contact" );
printf( "\n\t(3)\tShow All Contacts" );
printf( "\n\t(4)\tSort All Contacts" );
printf( "\n\t(5)\tExit ..." );
printf( "\n\nWhat would you like to do? " );
numGood = scanf( "%d", &iSelection );
while( getchar() != '\n' ) ; /* flush stdin ... including '\n' ... */
if( numGood != 1 )
{
printf( "\nEntry ERROR! Please enter an integer ...\n" );
continue; /* go to top of while loop right now ... */
}
if(iSelection == 1)
{
phonebook = addContact( phonebook ); /* update address of new memory */
if( phonebook == NULL )
{
printf("\nError getting new memory in addContact ... "
"Press 'Enter' to exit ... "); fflush( stdout );
getchar();
return -1;
}
}
else if(iSelection == 2) deleteContact( phonebook );
else if(iSelection == 3) showAllContacts( phonebook );
else if(iSelection == 4) sortByFirstName( phonebook );
else if(iSelection == 5)
{
printf("\nWill exit now ... Press 'Enter' to continue ... ");
fflush( stdout );
getchar();
free( phonebook );
}
else printf( "\n%d NOT implemented yet ...\n", iSelection );
}
return 0;
}
Contact* addContact( Contact* phonebook )
{
void* p;
if( SIZE == CAP ) /* if needed, reserve new memory to hold next Contact */
{
if( CAP != 0 ) CAP += CAP; /* double capacity ... */
else CAP = BEGIN_SIZE;
p = realloc( phonebook, sizeof(Contact)*CAP );
if( p == NULL ) { free( phonebook ); return NULL; }
else phonebook = (Contact*) p; /* update with new address ... */
}
getString( "First Name : ", phonebook[SIZE].firstName, 20, 1 );
getString( "Last Name : ", phonebook[SIZE].lastName, 20, 1 );
getString( "Phone Number : ", phonebook[SIZE].phoneNumber, 10, 10 );
printf("Contact successfully added ...\n");
++SIZE;
return phonebook; /* return updated address ... */
}
void deleteContact( Contact* phonebook )
{
int i = 0;
char deleteFirstName[21];
char deleteLastName[21];
getString( "First Name : ", deleteFirstName, 20, 0 );
getString( "Last Name : ", deleteLastName, 20, 0 );
for( i = 0; i < SIZE; ++i )
{
if( strcmp(deleteFirstName, phonebook[i].firstName) == 0 )
{
if( strcmp(deleteLastName, phonebook[i].lastName) == 0 )
{
int j;
for( j = i; j < SIZE-1; ++j ) /* while more data ... */
{ /* copy down ... (1st one copied down is over deleted) */
strcpy(phonebook[j].firstName, phonebook[j+1].firstName);
strcpy(phonebook[j].lastName, phonebook[j+1].lastName);
strcpy(phonebook[j].phoneNumber, phonebook[j+1].phoneNumber);
}
printf("\nContact deleted ...\n");
--SIZE; /* update SIZE */
return; /* exit right now ... */
}
}
}
/* else ... */
printf("Contact NOT found ...\n"); /* ... and exit void function */
}
void showAllContacts( Contact* phonebook )
{
int i = 0;
printf( "\nContacts:\n" );
for( i = 0; i < SIZE; ++i )
{
printf("(%d)\n", i+1);
printf("Name: %s %s\n", phonebook[i].firstName, phonebook[i].lastName);
printf("Number: %s\n", phonebook[i].phoneNumber);
}
printf( "size = %d, capacity = %d\n", SIZE, CAP );
}
void sortByFirstName( Contact* phonebook )
{
int i, swap, size = SIZE;
do
{
swap = 0;
for( i = 1; i < size; ++i )
{
if( strcmp(phonebook[i-1].firstName, phonebook[i].firstName) > 0 )
{
Contact tmp;
memcpy( &tmp, &phonebook[i], sizeof(Contact) );
memcpy( &phonebook[i], &phonebook[i-1], sizeof(Contact) );
memcpy( &phonebook[i-1], &tmp, sizeof(Contact) );
/*
tmp = phonebook[i];
phonebook[i] = phonebook[i-1];
phonebook[i-1] = tmp;
*/
/*
strcpy(tmp.firstName, phonebook[i].firstName);
strcpy(tmp.lastName, phonebook[i].lastName);
strcpy(tmp.phoneNumber, phonebook[i].phoneNumber);
strcpy(phonebook[i].firstName, phonebook[i-1].firstName);
strcpy(phonebook[i].lastName, phonebook[i-1].lastName);
strcpy(phonebook[i].phoneNumber, phonebook[i-1].phoneNumber);
strcpy(phonebook[i-1].firstName, tmp.firstName);
strcpy(phonebook[i-1].lastName, tmp.lastName);
strcpy(phonebook[i-1].phoneNumber, tmp.phoneNumber);
*/
swap = 1;
}
}
--size;
}while( swap );
printf( "Contacts sorted now ...\n" );
}
/* phnBook1_aryPtrs.c */ /* using a dynamic array of pointers to each new Contact
... version 1_aryPtrs */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 1024 /* pick an extra large size, to ensure? large enough ... */
const int BEGIN_SIZE = 8; /* pick begin size to minimize calls to realloc ... */
int SIZE = 0; /* Global variable used to keep track of number of Contacts */
int CAP = 0; /* Global variable used to keep track of capacity for Contacts */
typedef struct myContact
{
char firstName[21]; /* NOTE! max num of char's for firstname is 20 */
char lastName[21]; /* NOTE! MUST LEAVE ROOM for terminal '\0' char */
char phoneNumber[11]; /* NOTE! max num of char's for phoneNumber is 10 */
} Contact ;
Contact** addContact( Contact** );
void deleteContact( Contact** );
void showAllContacts( Contact** );
void sortByFirstName( Contact** );
Contact** freeContacts( Contact** );
/* shows 'msg' string and returns right sized C string 'getstr' passed in ... */
void getString( const char* msg, char* getstr, int maxSize, int minSize )
{
char *p, buffer[BUFSIZE];
int len;
for( ; ; ) /* loop forever ... until break ... */
{
printf( msg );
fflush( stdout );
fgets( buffer, BUFSIZE, stdin );
p = strchr( buffer, '\n' );
if( p != NULL ) *p = 0; /* eliminate '\n' char at end of C string */
len = strlen(buffer);
if( len <= maxSize && len >= minSize ) break;
/* else... */
printf( "\nERROR! Input must have length in range %d..%d\n",
minSize, maxSize );
}
/* when reach here ... a good len was input ... */
strcpy(getstr, buffer); /* getstr is retuned 'by ref' ... */
}
int main( void )
{
int iSelection = 0, numGood;
Contact** phonebook = NULL;
printf( "Size of each record = sizeof(Contact) = %d bytes ...\n",
sizeof(Contact) );
printf( "Size of pointer to each record = sizeof(Contact*) = %d bytes ...\n",
sizeof(Contact*) );
while( iSelection != 5 )
{
printf( "\n\t\t\tContact Menu" );
printf( "\n\n\t(1)\tAdd Contact" );
printf( "\n\t(2)\tDelete Contact" );
printf( "\n\t(3)\tShow All Contacts" );
printf( "\n\t(4)\tSort All Contacts" );
printf( "\n\t(5)\tExit ..." );
printf( "\n\nWhat would you like to do? " );
numGood = scanf( "%d", &iSelection );
while( getchar() != '\n' ) ; /* flush stdin ... including '\n' ... */
if( numGood != 1 )
{
printf( "\nEntry ERROR! Please enter an integer ... \n" );
continue; /* go to top of while loop right now ... */
}
if(iSelection == 1)
{
phonebook = addContact( phonebook ); /* update address of new memory */
if( phonebook == NULL )
{
printf("\nError getting new memory in addContact ... "
"Press 'Enter' to exit ... "); fflush( stdout );
getchar();
return -1;
}
}
else if(iSelection == 2) deleteContact( phonebook );
else if(iSelection == 3) showAllContacts( phonebook );
else if(iSelection == 4) sortByFirstName( phonebook );
else if(iSelection == 5)
{
printf("\nWill exit now ... Press 'Enter' to continue ... ");
fflush( stdout );
getchar();
phonebook = freeContacts( phonebook );
}
else printf( "\n%d NOT implemented yet ...\n", iSelection );
}
return 0;
}
Contact** addContact( Contact** phonebook )
{
void* p;
if( SIZE == CAP ) /* if needed,
reserve new memory to hold next pointer to Contact */
{
if( CAP != 0 ) CAP += CAP; /* double capacity ... */
else CAP = BEGIN_SIZE;
p = realloc( phonebook, sizeof(Contact*)*CAP );
if( p == NULL ) { freeContacts( phonebook ); return NULL; }
else phonebook = (Contact**) p; /* update with new address ... */
}
/* get pointer (and new memory) for this contact */
phonebook[SIZE] = malloc( sizeof(Contact) );
if( phonebook[SIZE] == NULL ) { freeContacts( phonebook ); return NULL; }
getString( "First Name : ", phonebook[SIZE]->firstName, 20, 1 );
getString( "Last Name : ", phonebook[SIZE]->lastName, 20, 1 );
getString( "Phone Number : ", phonebook[SIZE]->phoneNumber, 10, 10 );
printf("Contact successfully added ...\n");
++SIZE;
return phonebook; /* return updated address ... */
}
void deleteContact( Contact** phonebook )
{
int i = 0;
char deleteFirstName[21];
char deleteLastName[21];
getString( "First Name : ", deleteFirstName, 20, 0 );
getString( "Last Name : ", deleteLastName, 20, 0 );
for( i = 0; i < SIZE; ++i )
{
if( strcmp(deleteFirstName, phonebook[i]->firstName) == 0 )
{
if( strcmp(deleteLastName, phonebook[i]->lastName) == 0 )
{
int j;
free( phonebook[i] ); /* free this memory block first ... */
for( j = i; j < SIZE-1; ++j ) /* while more data ... */
{ /* copy down (1st pointer copied down is over deleted ... ) */
phonebook[j] = phonebook[j+1];
}
printf("Contact deleted ...\n");
--SIZE; /* now update SIZE ... */
return; /* and exit right now ... */
}
}
}
/* else ... */
printf("Contact NOT found ...\n"); /* ... and exit void function */
}
void showAllContacts( Contact** phonebook )
{
int i = 0;
printf( "\nContacts:\n" );
for( i = 0; i < SIZE; ++i )
{
printf("(%d)\n", i+1);
printf("Name: %s %s\n", phonebook[i]->firstName, phonebook[i]->lastName);
printf("Number: %s\n", phonebook[i]->phoneNumber);
}
printf( "size = %d, capacity = %d\n", SIZE, CAP );
}
void sortByFirstName( Contact** phonebook )
{
int i, swap, size = SIZE;
do
{
swap = 0;
for( i = 1; i < size; ++i )
{
if( strcmp(phonebook[i-1]->firstName, phonebook[i]->firstName) > 0 )
{
Contact* tmp = phonebook[i]; /* swap pointers ... */
phonebook[i] = phonebook[i-1];
phonebook[i-1] = tmp;
swap = 1;
}
}
--size;
}while( swap );
printf( "Contacts sorted now ...\n" );
}
Contact** freeContacts( Contact** c )
{
--SIZE;
for( ; SIZE > 0; --SIZE ) free( c[SIZE] ); /* first ... free all these */
free( c ); /* now free memory for array to hold pointers to each Contact */
CAP = SIZE = 0; /* recall: SIZE and CAP are Globals ... */
return NULL;
}
/* phnBook1_withfile.c */ /* using a dynamic array to hold Contacts ... version 1 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h> /* re. tolower ... */
#define FNAME "myContacts.txt" /* default file name ... */
#define MENU "\nContact Menu ...\n" \
"\t(1)\tAdd Contact\n" \
"\t(2)\tEdit/Delete Contact\n" \
"\t(3)\tShow All Contacts\n" \
"\t(4)\tsOrt All Contacts\n" \
"\t(5)\tFile All Contacts\n" \
"\t(6)\tLoad Contacts from file\n" \
"\t(7)\teXit ...\n" \
"Please enter a character from 1..7 or A,E,D,S,O,F,L,X : "
#define BUFSIZE 1024 /* pick an extra large size, to ensure? large enough ... */
const int BEGIN_SIZE = 1; /* BUT set BEGIN_SIZE to minimize calls to realloc */
int SIZE = 0; /* Global variable used to keep track of number of Contacts */
int CAP = 0; /* Global variable used to keep track of capacity for Contacts */
typedef struct myContact
{
char firstName[21]; /* NOTE! max num of char's for firstname is 20 */
char lastName[21]; /* NOTE! MUST LEAVE ROOM for terminal '\0' char */
char phoneNumber[11]; /* NOTE! max num of char's for phoneNumber is 10 */
} Contact ;
int fileContacts( const char*, Contact* );
Contact* loadContacts( const char*, Contact* );
Contact* addContact( Contact* );
void editDeleteContact( Contact*, char );
void printFormatted( const char* phone );
void showAllContacts( const Contact* );
int cmpNames( const Contact*, const Contact* );
void sortByNames( Contact* );
int cmpPhones( const Contact*, const Contact* );
void sortByPhones( Contact* );
int getChar( const char* msg );
void getFileName( char* filename );
int fileExists( const char* filename );
/* get a string from keyboard of length minSize to maxSize characters */
/* show 'msg' string and return right sized C string 'getstr' passed in */
void getString( const char* msg, char* getstr, int maxSize, int minSize );
/* get ALL line from file, and return all char's upto maxSize length in inStr */
/* 'safe fix to using fgets' to read a whole line less end '\n' char if exists */
/* Note: if input string exceeds maxSize-1 characters ... it gets truncated */
char* myFgets( char* inStr, int maxSize, FILE* fin );
int main( void ) /* ****************** BEGIN MAIN *************************** */
{
Contact* c = NULL;
char filename[BUFSIZE];
int reply = 'y';
printf( "Size of each record = sizeof(Contact) = %d bytes ...\n",
sizeof(Contact) );
while( !( reply == '7' || reply == 'x') )
{
printf( MENU ); fflush( stdout );
reply = getChar( "" );
if(reply == '1' || reply == 'a')
{
c = addContact( c ); /* update address of new memory */
if( c == NULL )
{
printf("\nError getting new memory in addContact ... "
"Press 'Enter' to exit ... "); fflush( stdout );
getchar();
return -1;
}
}
else if(reply == '2' || reply == 'e' || reply == 'd')
editDeleteContact( c, reply );
else if(reply == '3' || reply == 's')
showAllContacts( c );
else if(reply == '4' || reply == 'o')
{
int ans = getChar( "sOrt by names or phone (n/p) ? " );
if( ans == 'n' ) sortByNames( c );
else if( ans == 'p' ) sortByPhones( c );
else puts( "You didn't enter either 'n' or 'p' ..." );
}
else if(reply == '5' || reply == 'f')
{
getFileName( filename );
if( fileExists( filename ) )
{
int ans = getChar("Do you want to overwrite that file (y/n) ? ");
if( ans == 'y' )
{
int count = fileContacts( filename, c );
if( count == SIZE )
printf( "All %d records in the array were filed to",
count );
else
{
printf
(
"An error occured! "
"Only %d of %d records in the array were filed to",
count, SIZE
);
reply = 'x';
}
printf( " '%s'\n", filename );
}
else puts( "File write aborted ..." );
}
else
{
int count = fileContacts( filename, c );
if( count == SIZE )
printf( "All %d records in the array were filed to",
count);
else
{
printf
(
"An error occured! "
"Only %d of %d records in the array were filed to",
count, SIZE
);
reply = 'x';
}
printf( " '%s'\n", filename );
}
}
else if(reply == '6' || reply == 'l')
{
getFileName( filename );
if( fileExists(filename) )
{
int ans;
if( SIZE )
{
ans = getChar( "Do you want to append/overwrite "
"the array in memory (a/o) ? ");
if( ans == 'o' )
{
free( c );
SIZE = CAP = 0;
c = loadContacts( filename, c );
}
else if( ans == 'a' )
{
puts( "Ok ... will append to array ..." );
c = loadContacts( filename, c );
}
else puts( "You didn't enter either of 'A' or 'O' ... " );
}
else c = loadContacts( filename, c );
if( c && (ans == 'a' || ans == 'o') )
printf( "%d records are now in array memory.", SIZE );
else if( ans == 'a' || ans == 'o' )
{
puts( "There was an error allocating memory ..." );
reply = 'x';
}
}
else
{
printf( "The file '%s' does not exist yet ...\n", filename );
puts( "Select choice 'File All Contacts' "
"after you have added some contacts." );
}
}
else if(reply == '7' || reply == 'x' )
{
if( getChar("Do you really want to eXit (y/n) ? ") == 'y' )
{
if( getChar("\nWill eXit now ... "
"Press 'Enter' to continue/Enter 'a' to abort ... ")
== 'a' )
{
reply = 'y';
puts( "Exit aborted ..." );
}
else free( c );
}
else
{
reply = 'y';
puts( "Exit aborted ..." );
}
}
else if( reply != '\n' )
printf( "\nChoice '%c' NOT implemented yet ...\n", reply );
}
return 0;
} /* ***************************** END MAIN ********************************* */
int fileContacts( const char* filename, Contact* c )
{
FILE* fout = fopen( filename, "w" );
if( fout )
{
int i = 0;
for( i = 0; i < SIZE; ++i )
fprintf
(
fout,
"%s\n%s\n%s\n",
c[i].firstName, c[i].lastName, c[i].phoneNumber
);
fclose( fout );
return i;
}
/* else ... */
printf( "\nThere was an error trying to open file '%s' to write ...\n",
filename );
return 0;
}
Contact* loadContacts( const char* filename, Contact* c )
{
FILE* fin = fopen( filename, "r" );
if( fin )
{
int i = 0;
Contact tmp;
while
(
myFgets( tmp.firstName, sizeof(tmp.firstName), fin ) &&
myFgets( tmp.lastName, sizeof(tmp.lastName), fin ) &&
myFgets( tmp.phoneNumber, sizeof(tmp.phoneNumber), fin )
)
{
void* p;
if( SIZE == CAP ) /* if needed, reserve new memory to hold next Contact */
{
if( CAP != 0 ) CAP += CAP; /* double capacity ... */
else CAP = BEGIN_SIZE;
p = realloc( c, sizeof(Contact)*CAP );
if( p == NULL ) { free( c ); return NULL; }
else c = (Contact*) p; /* update with new address ... */
}
strcpy( c[SIZE].firstName, tmp.firstName );
strcpy( c[SIZE].lastName, tmp.lastName );
strcpy( c[SIZE].phoneNumber, tmp.phoneNumber );
++SIZE;
++i;
}
fclose( fin );
printf( "\n%d records were read from file %s ...\n", i, filename );
return c; /* return updated address ... */
}
/* else ... */
return NULL;
}
Contact* addContact( Contact* c )
{
void* p;
if( SIZE == CAP ) /* if needed, reserve new memory to hold next Contact */
{
if( CAP != 0 ) CAP += CAP; /* double capacity ... */
else CAP = BEGIN_SIZE;
p = realloc( c, sizeof(Contact)*CAP );
if( p == NULL ) { free( c ); return NULL; }
else c = (Contact*) p; /* update with new address ... */
}
getString( "First Name : ", c[SIZE].firstName, 20, 1 );
getString( "Last Name : ", c[SIZE].lastName, 20, 1 );
getString( "Phone Number : ", c[SIZE].phoneNumber, 10, 10 );
if( getChar("Ok to add (y/n) ? ") != 'y' )
{
puts( "Not added ..." );
return c;
}
printf("Contact successfully added ...\n");
++SIZE;
return c; /* return updated address ... */
}
void editDeleteContact( Contact* c, char reply )
{
int i = 0;
Contact ed;
if( reply == '2' ) reply = getChar("Edit or Delete (e/d) ? ");
puts( "Enter an 'empty' record to exit ..." );
getString( "First Name : ", ed.firstName, 20, 0 );
getString( "Last Name : ", ed.lastName, 20, 0 );
getString( "Phone Number : ", ed.phoneNumber, 10, 0 );
for( i = 0; i < SIZE; ++i )
{
if
(
strcmp(ed.firstName, c[i].firstName) == 0 &&
strcmp(ed.lastName, c[i].lastName) == 0 &&
strcmp(ed.phoneNumber, c[i].phoneNumber)==0
)
{
if( reply == 'd' &&
getChar("Do you really want to delete (y/n) ? ") == 'y' )
{
int j;
for( j = i; j < SIZE-1; ++j ) /* while more data ... */
{ /* copy down ... (1st one copied down is over deleted) */
strcpy(c[j].firstName, c[j+1].firstName);
strcpy(c[j].lastName, c[j+1].lastName);
strcpy(c[j].phoneNumber, c[j+1].phoneNumber);
}
printf("\nContact deleted ...\n");
--SIZE; /* update SIZE */
return; /* exit right now */
}
else if( reply == 'e' &&
getChar("Do you really want to edit (y/n) ? ") == 'y' )
{
getString( "First Name : ", ed.firstName, 20, 1 );
getString( "Last Name : ", ed.lastName, 20, 1 );
getString( "Phone number : ", ed.phoneNumber, 10, 10 );
if( getChar( "Ok to change (y/n) ? " ) == 'y' )
{
strcpy(c[i].firstName, ed.firstName);
strcpy(c[i].lastName, ed.lastName);
strcpy(c[i].phoneNumber, ed.phoneNumber);
return; /* exit right now */
}
else { puts("Aborted ..."); return; } /* exit right now */
}
else { puts("Aborted ..."); return; } /* exit right now */
}
}
/* else ... */
printf("Contact NOT found ...\n"); /* ... and exit void function */
}
void printFormatted( const char* phone )
{
char* p = "xxx-xxx-xxxx";
for( ; *p != 0; ++p )
{
if( *p == 'x' ) putchar( *phone++ );
else putchar( *p );
}
}
void showAllContacts( const Contact* c )
{
int i = 0;
printf( "\nContacts:\n" );
for( i = 0; i < SIZE; ++i )
{
printf("(%2d) ", i+1);
printFormatted( c[i].phoneNumber );
printf(" : %s, %s\n",c[i].lastName, c[i].firstName);
}
printf( "size = %d, capacity = %d\n", SIZE, CAP );
}
int cmpNames( const Contact* a, const Contact* b )
{
int last = strcmp( a->lastName, b->lastName );
if( last == 0 )
{
int first = strcmp( a->firstName, b->firstName );
if( first == 0 ) return strcmp( a->phoneNumber, b->phoneNumber );
else return first;
}
else return last;
}
int cmpPhones( const Contact* a, const Contact* b )
{
int phone = strcmp( a->phoneNumber, b->phoneNumber );
if( phone == 0 )
{
int last = strcmp( a->lastName, b->lastName );
if( last == 0 ) return strcmp( a->firstName, b->firstName );
else return last;
}
else return phone;
}
/* a simple example of a bubble sort is coded here ... */
void sortByNames( Contact* c )
{
int i, swap, size = SIZE; /* recall that SIZE is a global variable */
Contact tmp;
do
{
swap = 0;
for( i = 1; i < size; ++i )
{
if( cmpNames(&c[i-1], &c[i]) > 0 )
{
memcpy( &tmp, &c[i], sizeof(Contact) );
memcpy( &c[i], &c[i-1], sizeof(Contact) );
memcpy( &c[i-1], &tmp, sizeof(Contact) );
swap = 1;
/* // or swap like this ... //
tmp = c[i];
c[i] = c[i-1];
c[i-1] = tmp;
*/
/* // or swap like this ... //
strcpy(tmp.firstName, c[i].firstName);
strcpy(tmp.lastName, c[i].lastName);
strcpy(tmp.phoneNumber, c[i].phoneNumber);
strcpy(c[i].firstName, c[i-1].firstName);
strcpy(c[i].lastName, c[i-1].lastName);
strcpy(c[i].phoneNumber, c[i-1].phoneNumber);
strcpy(c[i-1].firstName, tmp.firstName);
strcpy(c[i-1].lastName, tmp.lastName);
strcpy(c[i-1].phoneNumber, tmp.phoneNumber);
*/
}
}
--size;
}while( swap );
printf( "Contacts sorted by last name, first name, phone number now ...\n" );
}
/* a simple example of a bubble sort is coded here ... */
void sortByPhones( Contact* c )
{
int i, swap, size = SIZE; /* recall that SIZE is a global variable */
Contact tmp;
do
{
swap = 0;
for( i = 1; i < size; ++i )
{
if( cmpPhones(&c[i-1], &c[i]) > 0 )
{
memcpy( &tmp, &c[i], sizeof(Contact) );
memcpy( &c[i], &c[i-1], sizeof(Contact) );
memcpy( &c[i-1], &tmp, sizeof(Contact) );
swap = 1;
}
}
--size;
}while( swap );
printf( "Contacts sorted by phone number, last name, first name now ...\n" );
}
int getChar( const char* msg )
{
int c, reply;
printf( "%s", msg ); fflush( stdout );
c = reply = getchar();
while( c != '\n' ) c = getchar(); /* 'flush' stdin ... */
return tolower( reply );
}
void getFileName( char* filename )
{
if( getChar("Use default file or input file name (d/i) ? ") == 'd' )
strcpy( filename, FNAME );
else
{
printf( "Input file name to use: " ); fflush( stdout );
myFgets( filename, BUFSIZE, stdin );
}
}
int fileExists( const char* filename )
{
FILE* f = fopen( filename, "r" );
if( f )
{
fclose( f );
return 1;
}
/* else ... */
return 0;
}
/* get a string from keyboard of length minSize to maxSize characters */
/* show 'msg' string and return right sized C string 'getstr' passed in */
void getString( const char* msg, char* getstr, int maxSize, int minSize )
{
char *p, buffer[BUFSIZE];
int len;
for( ; ; ) /* loop forever ... until break ... */
{
printf( msg );
fflush( stdout );
fgets( buffer, BUFSIZE, stdin );
p = strchr( buffer, '\n' );
if( p != NULL ) *p = 0; /* eliminate '\n' char at end of C string */
len = strlen(buffer);
if( len <= maxSize && len >= minSize ) break;
/* else... */
printf( "\nERROR! Length was %d ... Valid length is in range %d..%d\n",
len, minSize, maxSize );
}
/* when reach here ... a good len was input ... */
strcpy(getstr, buffer); /* getstr is retuned 'by ref' ... */
}
/* get ALL line from file, and return all char's upto maxSize length in inStr */
/* 'safe fix to using fgets' to read a whole line less end '\n' char if exists */
/* Note: if input string exceeds maxSize-1 characters ... it gets truncated */
char* myFgets( char* inStr, int maxSize, FILE* fin )
{
char myBuf[BUFSIZE] = { 0 }; /* fill with '\0' char's ... */
if( fgets(myBuf, BUFSIZE, fin) ) /* i.e. fgets(myBuf, BUFSIZE, fin) != NULL */
{
char* p = strchr( myBuf, '\n' );
if( p ) *p = 0; /* eliminate '\n' char at end of C string, if exists */
else /* 'flush' any remaining char's in this extra long input string */
{
int c = fgetc(fin);
while( c != '\n' && c != EOF ) c = fgetc(fin);
}
strncpy(inStr, myBuf, maxSize); /* now only copy first maxSize char's */
if( inStr[maxSize-1] != 0 ) inStr[maxSize-1] = 0; /* inStr is truncated */
return inStr;
}
else return NULL;
}
/* phnBook2.c */ /* using dynamic C strings in each Contact ... version 2 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 1024 /* pick an extra large size, to ensure? large enough ... */
#define MENU "Contact Menu ...\n" \
"\t(1)\tAdd Contact\n" \
"\t(2)\tDelete Contact\n" \
"\t(3)\tShow All Contacts\n" \
"\t(4)\tExit ...\n" \
"What would you like to do? "
const int BEGIN_SIZE = 8; /* pick begin size to minimize calls to realloc ... */
int SIZE = 0; /* Global variable used to keep track of number of Contacts */
int CAP = 0; /* Global variable used to keep track of capacity for Contacts */
typedef struct myContact
{
char* firstName;
char* lastName;
char* phoneNumber; /* num of char's for phoneNumber is 10 + terminal 0 */
} Contact ;
Contact* addContact( Contact* );
void deleteContact( Contact* );
void showAllContacts( const Contact* );
char* newCopy( const char* s )
{
char* p = malloc( strlen(s) + 1 );
if( p == NULL )
{
printf( "\nERROR! malloc failed in 'newCopy' ... " );
printf( "\nPress 'Enter' to exit ... " );
fflush( stdout );
getchar();
exit(1);
}
/* else ... if reach here ... memory was allocated ... */
strcpy( p, s );
return p; /* return address to new memory ... */
}
char* getString( const char* msg, int maxSize, int minSize )
{
char *p, buffer[BUFSIZE];
int len;
for( ; ; ) /* loop forever ... until break ... */
{
printf( msg );
fflush( stdin );
fgets( buffer, BUFSIZE, stdin );
p = strchr( buffer, '\n' );
if( p != NULL ) *p = 0; /* eliminate '\n' char at end of C string */
len = strlen(buffer);
if( len <= maxSize && len >= minSize ) break;
/* else... */
printf( "\nERROR! Input must have length in range %d..%d\n",
minSize, maxSize );
}
/* when reach here ... a good len was input ... */
return newCopy(buffer);
}
int main( void )
{
int i, iSelection = 0, numGood;
Contact* phonebook = NULL;
printf( "Size of each record = sizeof(Contact) = %d bytes ...\n", sizeof(Contact) );
while( iSelection != 4 )
{
printf( MENU );
fflush( stdout );
numGood = scanf( "%d", &iSelection );
while( getchar() != '\n' ) ; /* flush stdin ... */
if( numGood != 1 )
{
printf( "\nEntry ERROR! Please enter an integer in range 1..4\n" );
continue; /* goto top of while loop right now ... */
}
if( iSelection == 1 )
{
phonebook = addContact(phonebook); /* update address of new memory */
if( phonebook == NULL )
{
printf( "\nError getting new memory in addContact ... "
"Press 'Enter' to exit ... " );
fflush( stdout );
getchar();
return -1;
}
}
else if( iSelection == 2 ) deleteContact(phonebook);
else if( iSelection == 3 ) showAllContacts(phonebook);
else if( iSelection == 4 )
{
printf( "\nWill exit now ...\n" );
for( i = SIZE-1; i >= 0; --i )
{
free( phonebook[i].phoneNumber );
free( phonebook[i].lastName );
free( phonebook[i].firstName );
}
free(phonebook);
}
else printf( "\n%d NOT implemented yet ...\n", iSelection );
}
return 0;
}
Contact* addContact( Contact* phonebook )
{
void* p;
if( SIZE == CAP )
{
if( CAP != 0 ) CAP += CAP; /* double capacity ... */
else CAP = BEGIN_SIZE;
p = realloc( phonebook, sizeof(Contact)*CAP );
if( p == NULL ) { free(phonebook); return NULL; }
else phonebook = (Contact*) p; /* update with new address ... */
}
/* NOTE: just pointers to new copy of C string are copied below ... */
phonebook[SIZE].firstName = getString( "First Name : ", 100, 1 );
phonebook[SIZE].lastName = getString( "Last Name : ", 100, 1 );
phonebook[SIZE].phoneNumber = getString( "Phone Number : ", 10, 10 );
printf( "\nContact successfully added ...\n" );
++SIZE;
return phonebook; /* return updated address ... */
}
void deleteContact( Contact* phonebook )
{
int x = 0;
char* deleteFirstName;
char* deleteLastName;
/* NOTE: just pointers to new copy of C string are copied below ... */
deleteFirstName = getString( "First Name : ", 100, 0 );
deleteLastName = getString( "Last Name : ", 100, 0 );
for( x = 0; x < SIZE; ++x )
{
if( strcmp(deleteFirstName, phonebook[x].firstName) == 0 )
{
if( strcmp(deleteLastName, phonebook[x].lastName) == 0 )
{
int i = x ;
free( phonebook[i].phoneNumber ); /* free dynamic C string */
free( phonebook[i].lastName );
free( phonebook[i].firstName );
for( ; i < SIZE-1; ++i )
{ /* copy pointers down ... */
phonebook[i].firstName = phonebook[i+1].firstName;
phonebook[i].lastName = phonebook[i+1].lastName;
phonebook[i].phoneNumber = phonebook[i+1].phoneNumber;
}
printf( "\nContact deleted from Array of Contacts ...\n" );
--SIZE;
free( deleteLastName ); /* free all tmp memory used here ... */
free( deleteFirstName );
return;
}
}
}
/* else ... */
printf("\nContact NOT found ...\n\n");
free(deleteLastName); /* free all tmp memory used here ... */
free(deleteFirstName);
}
void showAllContacts( const Contact* phonebook )
{
int x = 0;
printf( "\nContacts:\n" );
for( x = 0; x < SIZE; ++x )
{
printf( "(%d)\n", x+1);
printf( "Name: %s %s\n", phonebook[x].firstName, phonebook[x].lastName );
printf( "Number: %s\n", phonebook[x].phoneNumber );
}
printf( "size = %d, capacity = %d\n", SIZE, CAP );
}
/* phnBook3.c */ /* using Cvec, a struct of struct,
to eliminate global variables */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFSIZE 1024 /* pick an extra large size, to ensure? large enough ... */
#define MENU "Contact Menu ...\n" \
"\t(1)\tAdd Contact\n" \
"\t(2)\tDelete Contact\n" \
"\t(3)\tShow All Contacts\n" \
"\t(4)\tExit ...\n" \
"What would you like to do? "
const int BEGIN_SIZE = 8; /* pick begin size to minimize calls to realloc */
typedef struct
{
char* firstName;
char* lastName;
char* phoneNumber; /* num of char's for phoneNumber is 10 + terminal 0 */
} Contact ;
void freeContact( Contact* c )
{
free( c->phoneNumber );
free( c->lastName );
free( c->firstName );
}
typedef struct
{
Contact* ary;
int size;
int cap;
} Cvec;
void clearCvec( Cvec* cv )
{
int i;
for( i = cv->size-1; i >= 0; --i ) freeContact( &cv->ary[i] );
free( cv->ary );
cv->size = cv->cap = 0;
}
void addContact( Cvec* );
void deleteContact( Cvec* );
void showAllContacts( const Cvec* );
char* newCopy( const char* s )
{
char* p = malloc( strlen(s) + 1 );
if( p == NULL )
{
printf( "\nERROR! malloc failed in 'newCopy' ... " );
printf( "\nPress 'Enter' to exit ... " );
fflush( stdout );
getchar();
exit(1);
}
/* else ... if reach here ... memory was allocated ... */
strcpy( p, s );
return p; /* return address to new memory ... */
}
char* getString( const char* msg, int maxSize, int minSize )
{
char *p, buffer[BUFSIZE];
int len;
for( ; ; ) /* loop forever ... until break ... */
{
printf( msg );
fflush( stdin );
fgets( buffer, BUFSIZE, stdin );
p = strchr( buffer, '\n' );
if( p != NULL ) *p = 0; /* eliminate '\n' char at end of C string */
len = strlen(buffer);
if( len <= maxSize && len >= minSize ) break;
/* else... */
printf( "\nERROR! Input must have length in range %d..%d\n",
minSize, maxSize );
}
/* when reach here ... a good len was input ... */
return newCopy(buffer);
}
int main( void )
{
int iSelection = 0, numGood;
Cvec cv;
cv.size = cv.cap = 0; /* BOTH NEED to be '0' to start dynamic array ok */
printf( "Size of each record = sizeof(Contact) = %d bytes ...\n", sizeof(Contact) );
while( iSelection != 4 )
{
printf( MENU );
fflush( stdout );
numGood = scanf( "%d", &iSelection );
while( getchar() != '\n' ) ; /* flush stdin ... */
if( numGood != 1 )
{
printf( "\nEntry ERROR! Please enter an integer in range 1..4\n" );
continue; /* goto top of while loop right now ... */
}
if( iSelection == 1 )
{
addContact(&cv); /* updates address of new memory */
if( cv.ary == NULL )
{
printf( "\nError getting new memory in addContact ... "
"Press 'Enter' to exit ... " );
fflush( stdout );
getchar();
return -1;
}
}
else if( iSelection == 2 ) deleteContact(&cv); /* updates cv */
else if( iSelection == 3 ) showAllContacts(&cv); /* passes address */
else if( iSelection == 4 )
{
printf( "\nWill exit now ...\n" );
clearCvec( &cv );
}
else printf( "\n%d NOT implemented yet ...\n", iSelection );
}
return 0;
}
void addContact( Cvec* cv )
{
void* p;
if( cv->size == cv->cap )
{
if( cv->cap != 0 ) cv->cap += cv->cap; /* double capacity ... */
else cv->cap = BEGIN_SIZE;
p = realloc(cv->ary, sizeof(Contact) * (cv->cap));
if( p == NULL ) { clearCvec(cv); cv->ary = NULL; return; }
else cv->ary = (Contact*) p; /* update with new address ... */
}
cv->ary[cv->size].firstName = getString( "First Name : ", 100, 1 );
cv->ary[cv->size].lastName = getString( "Last Name : ", 100, 1 );
cv->ary[cv->size].phoneNumber = getString( "Phone Number : ", 10, 10 );
printf( "\nContact successfully added ...\n" );
++ cv->size;
}
void deleteContact( Cvec* cv )
{
int x = 0;
char* deleteFirstName;
char* deleteLastName;
deleteFirstName = getString( "First Name : ", 100, 0 );
deleteLastName = getString( "Last Name : ", 100, 0 );
for( x = 0; x < cv->size; ++x )
{
if( strcmp(deleteFirstName, cv->ary[x].firstName) == 0 )
{
if( strcmp(deleteLastName, cv->ary[x].lastName) == 0 )
{
int i = x ;
freeContact( &cv->ary[i] );
for( ; i < cv->size-1; ++i )
{ /* copy pointers down ... */
/*
cv->ary[i].firstName = cv->ary[i+1].firstName;
cv->ary[i].lastName = cv->ary[i+1].lastName;
cv->ary[i].phoneNumber = cv->ary[i+1].phoneNumber;
*/
memcpy( &cv->ary[i], &cv->ary[i+1], sizeof(Contact) );
}
printf( "\nContact deleted from Array of Contacts ...\n" );
-- cv->size;
free( deleteLastName ); /* free all tmp memory used here ... */
free( deleteFirstName );
return;
}
}
}
/* else ... */
printf("\nContact NOT found ...\n\n");
free(deleteLastName); /* free all tmp memory used here ... */
free(deleteFirstName);
}
void showAllContacts( const Cvec* cv )
{
int x = 0;
printf( "\nContacts:\n" );
for( x = 0; x < cv->size; ++x )
{
printf( "(%d)\n", x+1);
printf( "Name: %s %s\n", cv->ary[x].firstName, cv->ary[x].lastName );
printf( "Number: %s\n", cv->ary[x].phoneNumber );
}
printf( "size = %d, capacity = %d\n", cv->size, cv->cap );
}
/* phnBook4.c */ /* 2016-10-12 */
/* using readLine.h and Cvec.h and Cvec_func's.h ... */
#include "readLine.h" /* includes <stdio.h>, <stdlib.h>, <string.h>, etc... */
#define MENU "Contact Menu ...\n" \
"\t\t\t(1)\tAdd Contact\n" \
"\t\t\t(2)\tDelete Contact\n" \
"\t\t\t(3)\tShow All Contacts\n" \
"\t\t\t(4)\tsOrt All Contacts\n" \
"\t\t\t(5)\teXit ...\n" \
"Enter your choice 1..5 > "
#define VEC_CHUNK_SIZE 2 /* if not defined here, defaults to initial cap = 8 */
/* first ... define Rec ... */
typedef struct myContact
{
char* firstName;
char* lastName;
char* phoneNumber; /* num of char's for phoneNumber is 10 + terminal 0 */
} Rec ;
/* and then define void freeVrec( Rec* ); ... */
void clearRec( Rec* rc )
{
free( rc->phoneNumber );
free( rc->lastName );
free( rc->firstName );
}
/* now can ... */
#include "Cvec.h"
#include "Cvec_func's.h"
/* you also need to define 'equals'... via a 'your_cmp_equals' 2 Rec's function */
int cmp_equals( const Rec* a, const Rec* b ) /* for findCvec( .. ) to work */
{
if( strcmp(a->firstName, b->firstName) == 0
&& strcmp(a->lastName, b->lastName) == 0 ) return 0; /* def'n equals */
else return 1;
}
int my_sort_cmp( const Rec* a, const Rec* b ) /* for msortCvec( .. ) to work */
{
int eq = strcmp(a->lastName, b->lastName);
if( eq == 0 ) return strcmp(a->firstName, b->firstName);
/* else ...*/
return eq;
}
void addContact( Cvec* );
void deleteContact( Cvec* );
void showAllContacts( Cvec* );
char* takeInLine( const char* msg )
{
printf( msg );
return readLine( stdin );
}
char* takeInLineMinMax( const char* msg, int min, int max )
{
char* line;
int len;
for( ; ; ) /* loop forever ... until break ... */
{
line = takeInLine( msg ); /* using readLine.h included above ... */
len = strlen(line);
if( min <= len && len <= max )
return line;
/* else... */
printf( "\nERROR! Input must have length in range %d..%d\n", min, max );
free( line );
}
}
char* takeInLineSize( const char* msg, int len )
{
char* line;
for( ; ; ) /* loop forever ... until break ... */
{
line = takeInLine( msg ); /* using readLine.h included above ... */
if( (int)strlen(line) == len ) return line;
/* else... */
printf( "\nERROR! Input must have length %d\n", len );
free( line );
}
}
int isValidPhoneNum( const char* s )
{
int i = strlen( s ) - 1;
for( ; i >= 0; --i ) if( !isdigit( s[i] ) ) return 0;
/* else ... if reach here .. */
return 1;
}
/* 's' is the C string passed in ... and WAS validated as 10 digits long */
void printFormattedPhoneNum( const char* s )
{
const char* p = "xxx-xxx-xxxx";
/* printf( "Number: " ); */
for( ; *p != 0 ; ++p )
{
if( *p == 'x' )
{
putchar( *s );
++s;
}
else putchar( *p );
}
/* putchar( '\n' ); */
}
void printRec( Rec* rc )
{
printFormattedPhoneNum( rc->phoneNumber );
printf( ": %s %s", rc->firstName, rc->lastName );
}
int main( void )
{
int reply;
Cvec phonebook;
initCvec( &phonebook );
printf( "Size of each record = sizeof(Rec) = %d bytes ...\n", (int)sizeof(Rec) );
do
{
reply = toupper(takeInChar( MENU ));
if( reply == '1' || reply == 'A' )
addContact( &phonebook ); /* Cvec updated since address passed */
else if( reply == '2' || reply == 'D' )
deleteContact( &phonebook ); /* Cvec updated ... */
else if( reply == '3' || reply == 'S' )
showAllContacts( &phonebook ); /* no copy made ... address passed */
else if( reply == '4' || reply == 'O' )
{ puts( "Now sorted ..." ); msortCvec( &phonebook, my_sort_cmp ); }
else if( reply == '5' || reply == 'X' )
{
clearCvec( &phonebook ); /* Cvec updated ... */
printf( "\nWill exit now ... Press 'Enter' to continue ... " );
fflush( stdout );
getchar();
}
else if( reply == '\n' ) printf( "\nYou need to enter something ...\n" );
else printf( "\nChoice '%c' NOT implemented here ...\n", reply );
}
while( !(reply == '5' || reply == 'X') );
return 0;
} /* end of main ... */
void addContact( Cvec* phonebook )
{
do
{
Rec r;
r.firstName = takeInLineMinMax( "First Name : ", 1, 80 ); /* pointer copied */
r.lastName = takeInLineMinMax( "Last Name : ", 1, 80 );
strToTitleCase(r.firstName);
strToTitleCase(r.lastName);
for( ; ; )
{
r.phoneNumber = takeInLineSize( "Phone Number : ", 10 );
if( isValidPhoneNum( r.phoneNumber ) ) break;
/* else ... */
printf( "\n%s is not all digits ...\n", r.phoneNumber );
free( r.phoneNumber );
}
if( tolower(takeInChar( "Ok (y/n) ? ")) == 'y' )
{
push_backCvec( phonebook, &r ); /* copies Rec pointers into array memory */
printRec( &r );
printf( " was successfully added ...\n" );
}
else
{
printRec( &r );
printf( " NOT added ...\n" );
clearRec( &r );
}
}
while( more() ) ;
}
void deleteContact( Cvec* phonebook )
{
int i;
Rec r;
r.firstName = takeInLineMinMax( "First Name : ", 0, 100 ); /* pointer copied */
r.lastName = takeInLineMinMax( "Last Name : ", 0, 100);
i = findCvec( phonebook, &r, cmp_equals ); /* uses def'n 'cmp_equals function' */
if( i != -1 ) /* findCvec returns index if found ... or -1 if not found */
{
eraseCvec( phonebook, i ); /* 'phonebook' is already an address */
printf( "Contact deleted from Cvec ...\n" );
}
else printf("Contact NOT found ...\n");
clearRec( &r ); /* free memory of dynamic C strings in this Rec 'r' ... */
}
void showAllContacts( Cvec* phonebook )
{
int x = 0;
printf( "\nContacts:" );
for( x = 0; x < phonebook->size; ++x )
{
printf( "\n(%d)\n", x+1);
printf( "Name: %s %s\n",
phonebook->ary[x].firstName, phonebook->ary[x].lastName );
/* printf( "Number: %s\n", phonebook->ary[x].phoneNumber ); */
printf( "Number: " );
printFormattedPhoneNum( phonebook->ary[x].phoneNumber );
}
printf( "\nsize = %d, capacity = %d\n", phonebook->size, phonebook->cap );
}
/* readShowCvecOfStructStudentFile.c */ /* 2016-10-08 */
/* a Cvec of struct that contains a Clist */
/* http://developers-heaven.net/forum/index.php/topic,46.0.html */
const char* MY_FILE = "studentData.txt";
/* data file is structured like this ... */
/*
Smith, Jane
97 83 97 87 66 76 37 85 97 93
Jones, Bob (Robert)
98 91 96 98 62 65 86 68 65 9
Costello, Judy Ann
98 90 96 99 72 85 55 9 75 99
*/
#include "readLine.h" /* includes stdio.h, stdlib.h, string.h, etc ... */
typedef struct myNode
{
int val;
struct myNode* next;
} Node ;
typedef Node* pNode;
void clearNode( pNode p )
{
/* no dynamic memory to free ... */
p = p;
}
#include "Clist.h"
#include "Clist_func's.h"
int compareLst( const pNode a, const pNode b )
{
if( b->val < a->val ) return -1;
if( b->val > a->val ) return 1;
return 0;
}
typedef struct myStudent
{
char* name; /* to hold the name of a Student... */
Clist marks; /* to hold a list of integer marks for a Student object */
} Rec ;
void clearRec( Rec* r )
{
clearClist( & r->marks );
free( r->name );
}
#include "Cvec.h"
#include "Cvec_func's.h"
int compareVec( const Rec* a, const Rec* b )
{
return strcmp( a->name, b->name );
}
int main()
{
FILE* fin;
char *line1, *line2;
int i;
pNode pls;
Cvec myStuds;
initCvec( &myStuds );
fin = fopen( MY_FILE, "r" );
myAssert( (fin != NULL), "File failed to open." );
/* while still more students in file, get next student 2 lines of data ... */
while( (line1 = readLine(fin)) && (line2 = readLine(fin)) )
{
char* p;
Rec tmp; /* construct an empty tmp Student Rec */
/* first get this student's name */
tmp.name = line1;
initClist( &tmp.marks );
/* then get this student's marks ...
get marks ... into this student's list of marks ... */
p = strtok( line2, " " );
for( ; ; )
{
Node lst;
lst.val = atoi( p );
push_backClist( &tmp.marks, &lst );
p = strtok( NULL, " " );
if( !p ) break;
}
push_backCvec( &myStuds, &tmp ); /* append this rec to vector */
free( line2 );
}
fclose( fin );
/* ok ... now show SORTED file content's to the screen ... */
printf( "Here is the student data (now sorted) that was in the file %s"
" ...\n\n", MY_FILE );
msortCvec( &myStuds, compareVec );
for( i = 0; i < myStuds.size; ++i )
{
int sum = 0;
printf( "%s\n", myStuds.ary[i].name ); /* show this student name ... */
/* now show all marks SORTED in descending order for this student ... */
msortClist( &myStuds.ary[i].marks, compareLst );
for( pls = myStuds.ary[i].marks.start; pls != NULL; pls = pls->next )
{
printf( "%4d", pls->val ); /* show this mark to right of 4 char field */
sum += pls->val;
}
printf( ", Sum = %d, Average = %.1f\n",
sum, ((double)sum)/myStuds.ary[i].marks.size );
}
clearCvec( &myStuds );
printf( "\nPress 'Enter' to continue/exit ... " ); fflush( stdout );
getchar(); /* keep 'Window' open until 'Enter' key is pressed ... */
return 0;
}
/* readShowArrayOfStructStudent.c */ /* Note: array sizes pre-fixed at compile time */
#include "readLine.h" /* includes stdio.h, stdlib.h, string.h, etc ... */
#define MAX_ARY_SIZE 100 /* adjust here, so able to hold expected size */
#define MAX_GRADES 20 /* adjust here, so able to hold expected size */
const char* FNAME = "studentData.txt"; /* or, use your own data file name */
typedef struct myStudent
{
char* name;
int grades[MAX_GRADES];
int grades_size;
} Student ;
/* returns size of array actually loaded up to max_size ... */
int load( Student ary[], int max_size );
void show( Student ary[], int size );
/* compare function re. qsort ... */
int compare( const void* a, const void* b )
{
const Student* x = (Student*) a;
const Student* y = (Student*) b;
return strcmp( x->name, y->name ); /* sort names in ascending order ... */
}
int compareGrds( const void* a, const void* b )
{
const int* x = (int*) a;
const int* y = (int*) b;
if( *x > *y ) return -1; /* sort marks in descending order ... */
if( *x < *y ) return 1;
return 0;
}
int main()
{
Student students[MAX_ARY_SIZE]; /* reserve space for array of Student records */
int i, size = load( students, MAX_ARY_SIZE ); // get file data into array ...
if( !size ) { puts("File failed to read any data." ); goto EXIT_NOW; }
show( students, size ); /* show Student data on console screen ... */
printf( "\nAfter sort ...\n\n" );
qsort( students, size, sizeof(Student), compare );
for( i = 0; i < size; ++ i )
qsort( students[i].grades, students[i].grades_size, sizeof(int), compareGrds );
show( students, size ); /* show Student data on console screen ... */
for( i = size-1; i >= 0; --i )
free( students[i].name );
EXIT_NOW:
printf( "\nPress 'Enter' to continue/exit ... " ); fflush( stdout );
getchar(); /* keep window open until 'Enter' key is pressed ... */
return 0;
}
int load( Student ary[], int max_size )
{
FILE* fin = fopen( FNAME, "r" );
char *line1, *line2;
int i = 0;
if( !fin ) return 0;
while( i < max_size && (line1 = readLine(fin)) && (line2 = readLine(fin)) )
{
int j = 0;
char* p = strtok( line2, " " );
ary[i].name = line1; /* get name into array for this ith index ... */
while( j < MAX_GRADES )
{
ary[i].grades[j++] = atoi( p ); /* j is incremented AFTER assignment */
p = strtok(NULL, " ");
if( !p ) break;
}
free( line2 );
ary[i].grades_size = j; /* j will be a value in the range 0..MAX_GRADES */
++i;
}
fclose( fin );
return i;
}
void show( Student ary[], int ary_size )
{
int i, j;
for( i = 0; i < ary_size; ++i )
{
printf( "%s\n", ary[i].name );
for( j = 0; j < ary[i].grades_size; ++j )
printf( "%4d", ary[i].grades[j] );
putchar( '\n' );;
}
}