Desktop Programming > C/C++ & Visual C++

C SOME UTILITY functions ...

(1/4) > >>

David:
This space is reserved for code and links to code for C utility functions ...

After I have collected several C snippets here ...  I hope to make an index with links on this front page.

But for now, please find these little snippets of code below,  (perhaps in related usage groupings of code, on the following pages.)


Update: please see this next link:

http://developers-heaven.net/forum/index.php/topic,2636.0.html

FREE homework help NOW available ...

You can contact me via:
http://sites.google.com/site/andeveryeyeshallseehim/home/he-comes
http://developers-heaven.net/forum/index.php/topic,2587.0.html

You may also like to see:  C++ SOME UTILITY functions ...

http://developers-heaven.net/forum/index.php/topic,2611.0.html


Update 2015-04-08: 

SEE the next link for several newly improved STUDENT take in type utilities  ...
with out of bounds error handling ...
(Some VERY HANDY student utilities.)

http://developers-heaven.net/forum/index.php/topic,2608.msg3158.html#msg3158


1.  /* example of a way to fix fgets TWO sometimes very annoying problems   */
char* fixedFgets( char* str, size_t bufSize, FILE* fin );

2.  /* example of a way to trim leading and trailing ws ... */
char* stripWS( char* s );

3.  /* example of an expedient way in C to handle string input from keyboard operator ...
    especially, if design calls to repeat input until string is of 'acceptable length' */
char* takeInStr( const char* msg, char* buf, unsigned bufLen, unsigned maxStrLen );

4.  /* an example of a common design request ... to Caps on first letters */
char* toCapsOnFirstLets( char* str );

5.  /* a simple student way to handle numeric input ...
   so program won't crash on bad input */
int takeInInt( const char* msg, int myMin, int myMax );

6.  /* loop until user takes in a valid int ... after prompt(s) ...  */
int takeInValidInt( const char prompt[] );

7.  /* a handy utility for many C student coding problems ... */
char takeInChar( const char* msg );

8.  int more(); /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */

9.  /* since using 'static' buf inside, memory persists ... so can return address */
char* takeInStaticString( const char* msg, unsigned max_len );

10. /* accepts only positive (i.e. >= 0) valid int range of values ... */
int takeInValidPosIntViaStaticString( const char* prompt, int high );

11. /*  returns a valid int in range INT_MIN..INT_MAX  */
int takeInValidMinMaxIntViaStaticString( const char* prompt, int myMin, int myMax );

...

And more added below ... like binary search, an iterative and also a recursive example, date and time and valid date and valid dob and days between two dates and ...



--- Code: ---/* returns 'int' value if in range '0'..'9' else returns -1 if NOT a digit */

int getDigit( char c )
{
    if ( c < '0' || c > '9' ) return -1;
    return c - '0';
}

/*
    Note: int( c ), where c is a char in the range '0'..'9'
    would return integers in the range 48..57
    ... but getDigit( c ) returns integers in the range 0..9
*/
--- End code ---



--- Code: ---/* returns int value if in range '0'..'9' else returns -1 if not a number */

int isNum( char c )
{
    if ( c < '0' || c > '9' ) return -1;
    return c - '0';
}
--- End code ---



1.  Six Fast Steps to Programming in C

http://developers-heaven.net/forum/index.php/topic,2022.0.html


2.  CvecOfInt.h, CvecOfString.h, Cvec.h, Cvec_func's.h (with FUNCTION POINTERS)

http://developers-heaven.net/forum/index.php/topic,2580.0.html


3.  Cvec_func's.h example programs ... using FUNCTION POINTERS to facilitate reuse

http://developers-heaven.net/forum/index.php/topic,2581.0.html


4. ClistOfInt.h, ClistOfString.h, Clist.h, Clist_func's.h (with FUNCTION POINTERS)

http://developers-heaven.net/forum/index.php/topic,2582.0.html


5.  Clist_func's.h example programs ... using FUNCTION POINTERS to facilitate reuse

http://developers-heaven.net/forum/index.php/topic,2583.0.html


6.  split.h ... a C emulation of the Python spilt function to parse a string ...

http://developers-heaven.net/forum/index.php/topic,2584.0.html


7.  Binary Search Tree template class in C ++ and Simple C Version

http://developers-heaven.net/forum/index.php/topic,2605.0.html


8.  Beyond Beginning Computer Programming in C ...

http://developers-heaven.net/forum/index.php/topic,2598.0.html


9.  Send in your C++ or C student coding problem, with code inside code tags (#)

http://developers-heaven.net/forum/index.php/topic,2473.0.html


10. Free coding help for beginners in C or C++

http://developers-heaven.net/forum/index.php/topic,2575.0.html


11. Clist Insertion Sort Tutorial ... and also see a recursive merge sort of a list

http://developers-heaven.net/forum/index.php/topic,2440.0.html


12. First steps ... via example programs in C++ and C ...

http://developers-heaven.net/forum/index.php/topic,134.0.html


13. New thread especially for students of C and C++

http://developers-heaven.net/forum/index.php/topic,106.0.html


14. BEGINNING COMPUTER PROGRAMMING (using C++ or C)

http://developers-heaven.net/forum/index.php/topic,127.0.html

David:
/*
    Example of a way to fix fgets sometimes TWO very annoying problems:

    1.  a 'maybe' newline at the end of the input buffer string ...
    2.  the possibility of the input string being TOO LONG for the input buffer C string

*/


--- Code: ---#include <stdio.h>
#include <string.h>

char* fixedFgets( char* str, size_t bufSize, FILE* fin )
{
    if( fgets( str, bufSize, fin ) )
    {
        char *p = strchr( str, '\n' ), c ;
        if( p ) *p = 0; /* strip off '\n' at end ... IF it exists */
        else while( (c = fgetc( fin )) != '\n'  &&  c != EOF ) ; /* flush ... */
        return str;
    }
    else return NULL;
}

--- End code ---


/* example of a way to trim leading and trailing ws ... */


--- Code: ---#include <string.h>
#include <ctype.h>

char* stripWS( char* s )
{
    char *start = s, *end = s;
    while( *end ) ++end ;
    if( end == start ) return s; /* empty string */

    for( --end; s <= end && isspace(*end); --end ) ;
    end[1] = 0;

    while( isspace(*s) ) ++s;
    memmove( start, s, end+2-s ); /* 2 ... to copy terminal 0 */
    return start;
}

--- End code ---


/*
    Take in string into buf string passed in of bufLen, but limit allowed input string length to maxStrLen
    Example of an expedient way in C to handle string input from keyboard operator ...
    especially, if design calls to repeat input until string is of 'acceptable length'

*/

--- Code: ---char* takeInStr( const char* msg, char* buf, unsigned bufLen, unsigned maxStrLen )
{
    unsigned len = 0;
    if( maxStrLen < bufLen )
    {
        for( ; ; ) /* on example of a C 'forever loop' ...
                      until break from loop or return from function */
        {
            printf( msg ); fflush( stdout );
            fixedFgets( buf, bufLen, stdin );
            stripWS( buf );
            len = strlen( buf );
            if( len  &&  len <= maxStrLen ) return buf;
            else
            {
                if( len ) printf( "\nError! myMax input string length here "
                                  "is %d char's long ...\n"
                                  "but your string was %d char's long.\n",
                                  maxStrLen, len );
                else printf( "\nBlank lines NOT valid input here ...\n" );
            }
        }
    }
    /* else ... */
    printf( "\nERROR!  The bufLen of %d needs to be greater than %d\n",
            bufLen, maxStrLen );
    return NULL;
}

--- End code ---


/* an example of a common design request ...  to ensure Caps on all 'first letters' */


--- Code: ---char* toCapsOnFirstLets( char* str )
{
    char *p = str, prev = ' ';
    for( ; *p ; ++p )
    {
        if( prev == ' ' || prev == '\t' )
            *p = toupper( *p );
        prev = *p;
    }
    return str;
}
--- End code ---

David:
/*
   Some simple student ways to handle validating numeric input ...
   and to code so that program won't crash on invalid numeric input
*/


/*
   loop until user takes in a valid int ... after prompt(s) ... 
   int here is also checked and accepted iff in int range myMin..myMax
   
   uses scanf for input

   int takeInIntMinMax( const char* msg, int myMin, int myMax );
*/


--- Code: ---#include <stdio.h>
 
/* loop until user takes in a valid int ... after prompt(s) ...  */
/* int here is also checked and accepted iff in int range myMin..myMax */
int takeInIntMinMax( const char* msg, int myMin, int myMax )
{
    int goodVal = 0, val = 0;
   
    while( !goodVal )
    {
    /* show prompt for input ...
   fflush( stdout) ensures prompt displayed right NOW
*/
        printf( msg ); fflush( stdout );
       
        /* Note logic below ...

   if scanf returns 1 below means ...
   ***there WAS ONE***
   good int data presented at first in input stream
       
           then ... if getchar() == '\n'
   ***that means that '\n' WAS the VERY NEXT CHAR***
   
   which means no space or other chars entered there
   before a '\n' char was entered ...
   so ... ***WAS good int*** data presented
   i.e. no 'junk' was entered by user 'by accident'
        (after int data was entered and before '\n' pressed)
*/

        if( scanf( "%d", &val ) == 1 && getchar() == '\n' )
        {
        goodVal = 1; /* Ok ... good so far ... */
        }
        else
        {
            printf( "\nInteger input only here please ...\n" );
            while( getchar() != '\n' ) ; /* flush stdin ... */
        }
       
        /* NOW check if input val was in the desired range myMin..myMax */

        if( goodVal && ( val < myMin || val > myMax ) )
        {
            goodVal = 0; /* reset to 'false' since val NOT in desired range */
            printf( "\nValid input only in range %d..%d\n", myMin, myMax );
        }
       
    } /* end while ... */   
   
    return val;
}

--- End code ---



/*
   loop until user takes in a valid int ... after prompt(s) ...

   uses scanf for input

   int takeInValidInt( const char prompt[] );
*/


--- Code: ---#include <stdio.h>

/* loop until user takes in a valid int ... after prompt(s) ...  */
int takeInValidInt( const char prompt[] )
{
    for( ; ; ) /* an other example of a C/C++ forever loop ... until 'return' */
    {
        int testInt;
        printf( prompt ); fflush( stdout );
       
       
        if( scanf( "%d", &testInt ) == 1 && getchar() == '\n' )
        {
        return testInt; /* since passed BOTH above checks ... */
        }
       
        /*else ... if reach here means failed either 1st or 2nd of above checks */
        while( getchar() != '\n' ); /* so ... 'flush' stdin ... as you go ... */
       
        puts( "Invalid input! Integers only please ..." );
    }
}

--- End code ---




--- Code: ---#include <stdio.h>
#include <ctype.h> /* re. tolower */

char takeInChar( const char* msg )
{
    char chr;
    printf( msg ); fflush( stdout );
    chr = getchar();
    if( chr != '\n' ) while( getchar() != '\n' ) ; /* flush stdin ... */
    return chr;
}

--- End code ---



--- Code: ---int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
    if( tolower( takeInChar( "\nMore (y/n) ? " )) == 'n' ) return 0;
    /* else ... */
    return 1;
}

--- End code ---

readLine is readily available by including file readLine.h

http://developers-heaven.net/forum/index.php/topic,2580.msg2864.html#msg2864

David:
A little test program featuring taking in a (fully) validated integer, (looping until have an input string that fits into an int), via taking in a STATIC C string and using atoi to convert to an int after validating that all are valid char's in the input string ... (in TWO Files ... a test program ... and a .h file that follows that needs to be included)


--- Code: ---/* test_takeInStaticStringUtilities.h.c */  /* revised 2013-06-08 */


#include "takeInStaticStringUtilities.h"


int main()
{
int count = 0;
double sum = 0.0;

printf( "MAX number of digits, permitted in an 'int' here, is %d\n",
MAX_DIG_IN_INT );

printf( "\nINT_MIN = %d, INT_MAX  = %d\n\n", INT_MIN, INT_MAX );

do
{
sum += takeInValidPosIntViaStaticString(
"Enter next integer >= 0 to sum: ", INT_MAX );
++ count;
}
while( more() ); /* make sure stdin is 'empty' before calling 'more()' */


printf( "\nFor %d numbers entered, sum was %.0f and average was %.2f\n",
count, sum, sum/count );

count = 0;
sum = 0.0;

putchar( '\n' );

do
{
sum += takeInValidMinMaxIntViaStaticString(
"Enter next integer to sum: ", INT_MIN, INT_MAX );
++ count;
}
while( more() ); /* make sure stdin is 'empty' before calling 'more()' */

printf( "\nFor %d numbers entered, sum was %.0f and average was %.2f\n",
count, sum, sum/count );


/* keep 'Window' open until 'Enter' key is pressed ... */
takeInChar( "\nPress 'Enter' to continue/exit ... " );
return 0;
}
--- End code ---




--- Code: ---/* takeInStaticStringUtilities.h */  /* 2013-06-08 */


/* http://developers-heaven.net/forum/index.php/topic,46.0.html */

#ifndef TAKE_IN_STATIC_STR_UTILITIES
#define TAKE_IN_STATIC_STR_UTILITIES

#include <stdio.h>
#include <stdlib.h>  /* re. atoi ... */
#include <string.h> /* re. strlen, strcpy, strchr... */
#include <ctype.h> /* re. tolower... */
#include <limits.h> /* re. INT_MAX, INt_MIN */
#include <math.h> /* re. log10 ... */

#define BIG_BUF_LEN 1024


#define MAX_DIG_IN_INT ( (int) log10( INT_MAX ) + 1 )


#ifndef dwTAKE_IN_CHAR_MORE
#define dwTAKE_IN_CHAR_MORE

int takeInChar( 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( takeInChar( "More (y/n) ? " )) == 'n' ) return 0;
/* else ... */
return 1;
}

#endif


/* since using 'static' buf inside, memory persists ... so can return address */
char* takeInStaticString( const char* msg, unsigned max_len )
{
static char buf[BIG_BUF_LEN];
char* p = NULL;

for( ; ; )
{
fputs( msg, stdout ); fflush( stdout );

fgets( buf, BIG_BUF_LEN, stdin );

/* Now 'fix' fgets input string or stdin
i.e. fix what needs 'fixing') */

p = strchr( buf, '\n' );
if( p ) /* strip off '\n' char if present */
*p = 0;
else /* flush stdin to end of line */
while( getchar() != '\n' );


if( buf[0] && strlen( buf ) <= max_len )
break;
else if( !buf[0] ) printf( "\nBlank line NOT valid input here ... \n" );
else printf( "\nFor '%s', max len of %u char's was exceeded ... \n",
buf, max_len );
}

return buf;
}


/* accepts only positive (i.e. >= 0) valid int range of values ... */
int takeInValidPosIntViaStaticString( const char* prompt, int high )
{
char loc_buf[32], *tmpStr;
int good = 0, i = 0, len = 0, tmpInt = 0;

for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
tmpStr = takeInStaticString( prompt, MAX_DIG_IN_INT );
len =  i = strlen( tmpStr );
good = ( i > 0 );
while( good && --i >= 0 )
{
if( !isdigit( tmpStr[i] ) ) { good = 0; break; }
}

if( good && len == MAX_DIG_IN_INT )
{
sprintf( loc_buf, "%d", INT_MAX );
if( strcmp( tmpStr, loc_buf ) > 0 ) good = 0;
}

if( good && tmpInt <= high )
{
tmpInt = atoi( tmpStr );
break;
}
/*else ...*/
printf( "\nInvalid input! Integers only please, in valid range 0..%d\n",
high );
}
return tmpInt;
}

/*  returns a valid int in range INT_MIN..INT_MAX */
int takeInValidMinMaxIntViaStaticString( const char* prompt, int myMin, int myMax )
{
char loc_buf[32];
int tmpInt;

for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
int good = 1, i = 0, len = 0, sign = 1;
char* tmp = takeInStaticString( prompt, MAX_DIG_IN_INT+1 ); /* leave room for + - */

if( tmp[0] == '+' ) ++tmp;
else if( tmp[0] == '-') { ++tmp; sign = -1; }

len = i = strlen( tmp );
good = ( i > 0 && i <= MAX_DIG_IN_INT );
while( good && --i >= 0 )
{
if( !isdigit( tmp[i] ) ) good = 0;
}

if( good && len == MAX_DIG_IN_INT )
{
if( sign == 1 )
{
sprintf( loc_buf, "%d", INT_MAX );
if( strcmp( tmp, loc_buf ) > 0 ) good = 0;
}
else
{
sprintf( loc_buf, "%d", INT_MIN );
if( strcmp( tmp, &loc_buf[1] ) > 0 ) good = 0;
}
}

if( good )
{
tmpInt = sign * atoi( tmp );
if( tmpInt >= myMin && tmpInt <= myMax ) break;
}
/*else ...*/
printf( "\nInvalid input! Integers please, only in range %d..%d\n",
myMin, myMax );
}
return tmpInt;
}

#endif

--- End code ---



Now a little different set of C utilities all in a .h file and a little test program follows ...

/*
    features ... an expedient way in C to handle string input from keyboard operator ...
    especially, if design calls to repeat input until string is of 'acceptable length'

    using a passed in C string 'buf' with passed in length of 'bufLen'

    char* takeInStr( const char* msg, char* buf, unsigned bufLen, unsigned maxStrLen );

    int takeInValidIntViaStrBuf( const char* msg );

    int takeInValidIntViaStrBufInRangeMinMax( const char* msg, int min, int max );
*/


--- Code: ---/* Cutilities.h */  /* 2016-06-20 */

#ifndef CUTILITIES_H
#define CUTILITIES_H


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <limits.h>

#define MAX_DIG_IN_INT (int)( log10( INT_MAX ) + 1 )


#ifndef dwTAKE_IN_CHAR_MORE
#define dwTAKE_IN_CHAR_MORE

/* a handy utility for many C student coding problems ... */
char takeInChar( const char* msg )
{
    char chr;
    printf( msg ); fflush( stdout );
    chr = getchar();
    if( chr != '\n' ) while( getchar() != '\n' ) ; /* flush stdin ... */
    return chr;
}

int more() /* defaults to 'true'/'yes'/'1' ... unless 'n' or 'N' entered */
{
if( tolower( takeInChar( "More (y/n) ? " )) == 'n' ) return 0;
/* else ... */
return 1;
}

#endif

#ifndef dwFIXEDFGETS
#define dwFIXEDFGETS

/* example of a way to fix fgets TWO, sometimes very annoying, problems */
char* fixedFgets( char* s, size_t bufSize, FILE* fin )
{
    if( fgets( s, bufSize, fin ) )
    {
        char *p = strchr( s, '\n' ),
             c ;
        if( p ) *p = 0; /* strip off '\n' at end ... iF it exists */
        else while( (c = fgetc( fin )) != '\n'  &&  c != EOF ) ; /* flush... */
        return s;
    }
    /*  else ... if reach here ... */
    return NULL;
}


#endif

#ifndef dwTRIM
#define dwTRIM
char* trim( char* s )
{
    char *start = s, *end = s;
    while( *end ) ++end ;
    if( end == s ) return s; /* empty string */

    for( --end; s <= end && isspace(*end); --end ) ;
    end[1] = 0;

    while( isspace(*s) ) ++s;
    memmove( start, s, end+2-s ); /* 2 ... to copy terminal 0 */
    return start;
}
char* rtrim( char* s )
{
    char* end = s;
    while( *end ) ++end ;
    if( end == s ) return s; /* empty string */

    for( --end; s <= end && isspace(*end); --end ) ;
    end[1] = 0;
    return s;
}
char* ltrim( char* s )
{
    char *start = s, *end = s;
    while( *end ) ++end ;
    if( end == s ) return s; /* empty string */

    while( isspace(*s) ) ++s;
    memmove( start, s, end+1-s ); /* 1 ... to copy terminal 0 */
    return start;
}
#endif


#ifndef dwTOCAPSONFIRSTLETS
#define dwTOCAPSONFIRSTLETS

/* an example of a common design request ... */
char* toCapsOnFirstLets( char* str )
{
    char* p = str;
    char prev = ' ';
    while( *p )
    {
        if( prev == ' ' ) *p = toupper( *p );
        prev = *p;
        ++p;
    }
    return str;
}

#endif

#ifndef dwUPDOWN
#define dwUPDOWN
char* strToUpper( char* str )
{
char* p = str;
while( *p != 0 ) { *p = toupper(*p); ++p; }
return str;
}

char* strToLower( char* str )
{
char* p = str;
while( *p != 0 ) { *p = tolower(*p); ++p; }
return str;
}
#endif

/*
    example of an expedient way in C to handle string input from keyboard operator ...
    especially, if design calls to repeat input until string is of 'acceptable length'

*/
char* takeInStr( const char* msg, char* buf, unsigned bufLen, unsigned maxStrLen )
{
    unsigned len = 0;
    if( maxStrLen < bufLen )
    {
        for( ; ; ) /* on example of a C 'forever loop' ...
                      until break from loop or return from function */
        {
            printf( msg ); fflush( stdout );
            fixedFgets( buf, bufLen, stdin );
            trim( buf );
            len = strlen( buf );
            if( len  &&  len <= maxStrLen ) return buf;
            else
            {
                if( len ) printf( "\nError! myMax input string length here "
                                  "is %d char's long ...\n"
                                  "but, your string was %d char's long.\n",
                                  maxStrLen, len );
                else printf( "\nBlank lines NOT valid input here ...\n" );
            }
        }
    }
    /* else ... */
    printf( "\nERROR!  The bufLen of %d needs to be greater than %d\n",
            bufLen, maxStrLen );
    return NULL;
}


/* a simple student way to handle numeric input ...
   so program won't crash on bad input */
int takeInValidIntInRangeMinMax( const char* msg, int myMin, int myMax )
{
    int good = 0, val = 0;
    while( !good )
    {
        printf( msg ); fflush( stdout );

        if( scanf( "%d", &val ) == 1 && getchar() == '\n' ) good = 1;
        else
        {
            printf( "\nInteger input only here please ...\n" );
            while( getchar() != '\n' ) ; /* flush stdin ... */
        }

        if( good &&  val >= myMin && val <= myMax ) break;
        else
        {
            good = 0;
            printf( "\nValid input only in range %d..%d\n", myMin, myMax );
        }
    }
    return val;
}

int takeInValidInt( const char* msg )
{
    int val = 0;
    while( 1 )
    {
        printf( msg ); fflush( stdout );

        if( scanf( "%d", &val ) == 1 && getchar() == '\n' )
        {
        return val;
        }
        /* else ... **/
       
        printf( "\nInteger input only here please ...\n" );
        while( getchar() != '\n' ) ; /* flush stdin ... */ 
    }
}

int takeInValidIntViaStrBuf( const char* msg )
{
char loc_buf[32], loc_buf2[32], *tmpStr;
int good = 1, i = 0, len =0, sign = 1, tmpInt = 0;

for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{

/* NOTE: blank lines NOT allowed as input below... and leave room for + -  */
tmpStr = takeInStr( msg, loc_buf, sizeof(loc_buf), MAX_DIG_IN_INT+1 );

/* handle sign if present ... */
if( tmpStr[0] == '+' ) ++tmpStr;
else if( tmpStr[0] == '-') { ++tmpStr; sign = -1; }

len = i = strlen( tmpStr );

/* make sure has at least 1 dig ... and NOT too many dig's ... */
good = ( i > 0 && i <= MAX_DIG_IN_INT );

/* make sure all digits ... */
while( good && --i >= 0 )
{
if( !isdigit( tmpStr[i] ) ) { good = 0; break; }
}

/* make sure fits intn an int ...*/

if( good && len == MAX_DIG_IN_INT )
{
if( sign == 1 )
{
sprintf( loc_buf2, "%d", INT_MAX );
if( strcmp( tmpStr, loc_buf2 ) > 0 ) good = 0;
}
else
{
sprintf( loc_buf2, "%d", INT_MIN );
if( strcmp( tmpStr, &loc_buf2[1] ) > 0 ) good = 0;
}

}

if( good )
{
tmpInt = atoi( loc_buf );
break;
}
/*else ...*/
printf( "\nInvalid input! Integers please, only in range %d..%d\n",
INT_MIN, INT_MAX );
}

return tmpInt;
}

int takeInValidIntViaStrBufInRangeMinMax( const char* msg, int min, int max )
{
char loc_buf[32], loc_buf2[32], *tmpStr;
int good = 1, i = 0, len =0, sign = 1, tmpInt = 0;

for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{

/* NOTE: blank lines NOT allowed as input below... and leave room for + -  */
tmpStr = takeInStr( msg, loc_buf, sizeof(loc_buf), MAX_DIG_IN_INT+1 );

/* handle sign if present ... */
if( tmpStr[0] == '+' ) ++tmpStr;
else if( tmpStr[0] == '-') { ++tmpStr; sign = -1; }

len = i = strlen( tmpStr );

/* make sure has at least 1 dig ... and NOT too many dig's ... */
good = ( i > 0 && i <= MAX_DIG_IN_INT );

/* make sure all digits ... */
while( good && --i >= 0 )
{
if( !isdigit( tmpStr[i] ) ) { good = 0; break; }
}

/* make sure fits intn an int ...*/

if( good && len == MAX_DIG_IN_INT )
{
if( sign == 1 )
{
sprintf( loc_buf2, "%d", INT_MAX );
if( strcmp( tmpStr, loc_buf2 ) > 0 ) good = 0;
}
else
{
sprintf( loc_buf2, "%d", INT_MIN );
if( strcmp( tmpStr, &loc_buf2[1] ) > 0 ) good = 0;
}
}

if( good )
        {
            tmpInt = atoi(loc_buf);
            if( tmpInt >=  min && tmpInt <= max  ) break;
        }
/* else ... */
printf( "\nERROR!  Valid input range here is %d..%d\n", min, max );
}
return tmpInt;
}


#endif


--- End code ---



--- Code: ---/* test_Cutilities.c */  /*  2013-07-11 */


#include "Cutilities.h"

void test_takeInStr()
{
char loc_buf[32];
char* tmp = takeInStr( "Enter your name(s): ",
loc_buf, sizeof(loc_buf), sizeof(loc_buf)-1 );

printf( "The string that was taken in was : '%s'\n", tmp );

toCapsOnFirstLets( tmp );
printf( "With CAPS On All First Letters   : '%s'\n", tmp );
}

void test_takeInValidInt()
{
int tmp = takeInValidInt( "Enter an int: " );
printf( "You entered %d\n", tmp );
}

void test_takeInValidIntInRangeMinMax()
{
char loc_buf[128];
int min = takeInValidInt( "Enter min value to accept: " );
int max = 0, tmpInt = 0;

while( ( max = takeInValidInt( "Enter max value to accept: " )) < min )
{
printf( "\nERROR!  Valid inout range here if %d..%d\n", min, INT_MAX );
}

/* form message ...*/
sprintf( loc_buf, "Enter integer in range %d..%d: ", min, max );
tmpInt = takeInValidIntInRangeMinMax( loc_buf, min, max );
printf( "You entered %d\n", tmpInt );
}

void test_takeInValidIntViaStringBuf()
{
int tmpInt = takeInValidIntViaStrBuf( "Enter a valid int: " );
printf( "You entered %d\n", tmpInt );
}

void test_takeInValidIntViaStrBufInRangeMinMax()
{
char loc_buf[128];
int min = takeInValidIntViaStrBuf( "Enter min value to accept: " );
int max = 0, tmpInt = 0;

while( ( max = takeInValidIntViaStrBuf( "Enter max value to accept: " )) < min )
{
printf( "\nERROR!  Valid inout range here if %d..%d\n", min, INT_MAX );
}

/* form message ...*/
sprintf( loc_buf, "Enter integer in range %d..%d: ", min, max );

tmpInt = takeInValidIntViaStrBufInRangeMinMax( loc_buf, min, max );
printf( "You entered %d\n", tmpInt );
}





int main()
{
printf( "INT_MIN = %d,  INT_MAX = %d\n\n", INT_MIN, INT_MAX );
printf( "Max mumber of digits permitted in an 'int' here is %d\n\n",
MAX_DIG_IN_INT );

do
{
puts( "Testing 'takeInStr( buf, bufLen, maxStrLen )' ..." );
test_takeInStr();

puts( "\nTesting 'takeInInt( msg )' ..." );
test_takeInValidInt();

puts( "\nTesting 'takeInValidIntInRangeMinMax( msg, min, max )' ..." );
test_takeInValidIntInRangeMinMax();

puts( "\nTesting 'takeInValidIntViaStringBuf( msg )' ..." );
test_takeInValidIntViaStringBuf();

puts( "\nTesting 'takeInValidIntViaStrBufInRangeMinMax( msg, min, max )' ..." );
test_takeInValidIntViaStrBufInRangeMinMax();

putchar( '\n' );
}
while( tolower( takeInChar( "\nMore (y/n) ? " )) != 'n' );
return 0;
}
--- End code ---

David:
Two files of several utilities that you may like to have to include ... the first uses fgets ... the 2nd uses readLine



--- Code: ---/* fixedFgets.h */ /* 2012-06-01 */

/* updated to also have dwUPDOWN strToUpper and strToLower on 2013-04-03 */

#ifndef FIXEDFGETS_H
#define FIXEDFGETS_H

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>


#ifndef MAX_LINE_LEN
#define MAX_LINE_LEN 1023
#endif

#ifndef dwMYASSERT
#define dwMYASSERT
void myAssert( int condition, const char text[] )
{
    if( !condition )
    {
        fprintf(stderr, "%s\n", text );
        fputs( "Press 'Enter' to exit program ... ", stderr );
        getchar();
        exit(1);
    }
}
#endif

#ifndef dwNEWMEMORY
#define dwNEWMEMORY
char* newMem( int bytes )
{
    char* n = (char*) malloc( bytes ); /* cast for C++ compilers */
    myAssert( (n != NULL), "Error: malloc failed in 'newMem' ... " );
    return n;
}
#endif

#ifndef dwNEWCOPY
#define dwNEWCOPY
char* newCopy( const char* str )
{
    char* n = newMem( strlen(str) + 1 );
    strcpy( n, str );
    return n;
}
#endif

#ifndef dwTRIM
#define dwTRIM
char* trim( char* s )
{
    char *start = s, *end = s;
    while( *end ) ++end ;
    if( end == s ) return s; /* empty string */

    for( --end; s <= end && isspace(*end); --end ) ;
    end[1] = 0;

    while( isspace(*s) ) ++s;
    memmove( start, s, end+2-s ); // 2 ... to copy terminal 0 //
    return start;
}
char* rtrim( char* s )
{
    char* end = s;
    while( *end ) ++end ;
    if( end == s ) return s; /* empty string */

    for( --end; s <= end && isspace(*end); --end ) ;
    end[1] = 0;
    return s;
}
char* ltrim( char* s )
{
    char *start = s, *end = s;
    while( *end ) ++end ;
    if( end == s ) return s; /* empty string */

    while( isspace(*s) ) ++s;
    memmove( start, s, end+1-s ); // 1 ... to copy terminal 0 //
    return start;
}
#endif

#ifndef dwUPDOWN
#define dwUPDOWN
char* strToUpper( char* str )
{
char* p = str;
while( *p != 0 ) { *p = toupper(*p); ++p; }
return str;
}

char* strToLower( char* str )
{
char* p = str;
while( *p != 0 ) { *p = tolower(*p); ++p; }
return str;
}
#endif



char* fixedFgets( char* s, size_t bufSize, FILE* fin )
{
    if( fgets( s, bufSize, fin ) )
    {
        char *p = strchr( s, '\n' ), c ;
        if( p ) *p = 0; /* strip off '\n' at end ... IF it exists */
        else while( (c = fgetc( fin )) != '\n'  &&  c != EOF ) ; /* flush... */
        return s;
    }
    else return NULL;
}

char* newFgets( FILE* fin )
{
    char buf[MAX_LINE_LEN+1];
   
    if( fgets( buf, sizeof(buf), fin ) )
    {
        char *p = strchr( buf, '\n' ), c ;
        if( p ) *p = 0; /* strip off '\n' at end ... IF it exists */
        else while( (c = fgetc( fin )) != '\n'  &&  c != EOF ) ; /* flush... */
        return newCopy( buf );
    }
    else return NULL;
}

#endif
--- End code ---



--- Code: ---/* takeIn_readLine_utilities.h */  /* 2015-06-21 */


#ifndef TAKEIN_READLINE_UTILITIES_H
#define TAKEIN_READLINE_UTILITIES_H


#include <math.h>
#include <limits.h>
#include "readLine.h" /* see readLine.h to see all that is included ... */


#define MAX_DIG_IN_INT (int)( log10( INT_MAX ) + 1 )


#ifndef dwTAKE_IN_CHAR_MORE
#define dwTAKE_IN_CHAR_MORE

int takeInChar( 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( takeInChar( "More (y/n) ? " )) == 'n' ) return 0;
/* else ... */
return 1;
}

#endif


#ifndef dwTOCAPSONFIRSTLETS
#define dwTOCAPSONFIRSTLETS

/* an example of a common design request ... */
/* an example of a common design request ... */
char* toCapsOnFirstLets( char* str )
{
    char* p = str;
    char prev = ' ';
    while( *p )
    {
        if( prev == ' ' ) *p = toupper( *p );
        prev = *p;
        ++p;
    }
    return str;
}

#endif

/* using readLine and getting new dynamic memory  ... so can return address */
char* takeInStrMaxLen( const char* msg, unsigned maxLen )
{
char* p = NULL;

for( ; ; )
{
fputs( msg, stdout ); fflush( stdout );

p = readLine( stdin );

if( p[0] && strlen( p ) <= maxLen )
break;
else if( !p[0] ) printf( "\nBlank line NOT valid input here ... \n" );
else printf( "\nFor '%s', max len of %u char's was exceeded ... \n",
p, maxLen );
free( p );
}

return p;
}

char* takeInStr( const char* msg )
{
fputs( msg, stdout ); fflush( stdout );
return readLine( stdin );
}



/* accepts only positive (i.e. >= 0) valid int range of values ... */
int takeInValidPosInt( const char* prompt, int high )
{
char loc_buf[32], *tmpStr;
int good = 0, i = 0, len = 0, tmpInt = 0;

for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
tmpStr = takeInStrMaxLen( prompt, MAX_DIG_IN_INT );
len =  i = strlen( tmpStr );
good = ( i > 0 );
while( good && --i >= 0 )
{
if( !isdigit( tmpStr[i] ) ) { good = 0; break; }
}

if( good && len == MAX_DIG_IN_INT )
{
sprintf( loc_buf, "%d", INT_MAX );
if( strcmp( tmpStr, loc_buf ) > 0 ) good = 0;
}

if( good && tmpInt <= high )
{
tmpInt = atoi( tmpStr );
free( tmpStr );
break;
}
/* else ...*/
printf( "\nInvalid input! Integers only please, in valid range 0..%d\n",
high );
free( tmpStr );
}
return tmpInt;
}

/*  returns a valid int in range INT_MIN..INT_MAX */
int takeInValidMinMaxInt( const char* prompt, int myMin, int myMax )
{
char loc_buf[32];
int tmpInt;

for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
int good = 1, i = 0, len = 0, sign = 1;
char* tmp = takeInStrMaxLen( prompt, MAX_DIG_IN_INT+1 ); /* leave room


for + - */
char* tmpCpy = tmp;

if( tmp[0] == '+' ) ++tmp;
else if( tmp[0] == '-') { ++tmp; sign = -1; }

len = i = strlen( tmp );
good = ( i > 0 && i <= MAX_DIG_IN_INT );
while( good && --i >= 0 )
{
if( !isdigit( tmp[i] ) ) good = 0;
}

if( good && len == MAX_DIG_IN_INT )
{
if( sign == 1 )
{
sprintf( loc_buf, "%d", INT_MAX );
if( strcmp( tmp, loc_buf ) > 0 ) good = 0;
}
else
{
sprintf( loc_buf, "%d", INT_MIN );
if( strcmp( tmp, &loc_buf[1] ) > 0 ) good = 0;
}
}

if( good )
{
tmpInt = atoi( tmpCpy );
if( tmpInt >= myMin && tmpInt <= myMax )
{
free( tmpCpy );
break;
}
}
/* else ...*/
printf( "\nInvalid input! Integers please, only in range %d..%d\n",
myMin, myMax );
free( tmpCpy );
}
return tmpInt;
}

/*  returns a valid int in range INT_MIN..INT_MAX */
int takeInValidInt( const char* prompt )
{
char loc_buf[32];
int tmpInt;

for( ; ; ) /* an example of a C/C++ forever loop ... until 'return' */
{
int good = 1, i = 0, len = 0, sign = 1;
char* tmp = takeInStrMaxLen( prompt, MAX_DIG_IN_INT+1 ); /* leave room


for + - */
char* tmpCpy = tmp;

if( tmp[0] == '+' ) ++tmp;
else if( tmp[0] == '-') { ++tmp; sign = -1; }

len = i = strlen( tmp );
good = ( i > 0 && i <= MAX_DIG_IN_INT );
while( good && --i >= 0 )
{
if( !isdigit( tmp[i] ) ) good = 0;
}

if( good && len == MAX_DIG_IN_INT )
{
if( sign == 1 )
{
sprintf( loc_buf, "%d", INT_MAX );
if( strcmp( tmp, loc_buf ) > 0 ) good = 0;
}
else
{
sprintf( loc_buf, "%d", INT_MIN );
if( strcmp( tmp, &loc_buf[1] ) > 0 ) good = 0;
}
}

if( good )
{
tmpInt = atoi( tmpCpy );
free( tmpCpy );
break;
}
/* else ...*/
printf( "\nInvalid input! Integers please, only in range %d..%d\n",
INT_MIN, INT_MAX );
free( tmpCpy );
}
return tmpInt;
}

#endif

--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version