Last Update: Mon Oct 6 01:05:36 EDT 1997

This is just an arbitrary collection of functions, and generally require modifications involving actually defining the macro constants, all of which are in CAPITALS. Depending on how you distribute these in modules ( ".c" files), the declarations of functions may have to be changed from or to extern. There is no gurantee that a called function will exist in this collection. The point is simply code examples, not that they be immediately useful.

/* io.c
 *
 * I/O routines of generality and programatic specificity.
 * Containing:
 *
 *	char *Gets( arr, arrsz ) 
 *	int gtnum( ar, sz, low, high )
 *	int gtyesno( ar, sz )
 *	int gtdate( dtype, ar, sz )
 *	float gtfloat( msg )
 *	float gtbigfloat( msg )
 *	int Gtstr( padch, msg, s, sz )
 *	int lprintf( l, f ) 
 *	void display( fn, n ) 
 *	int linedisplay( fn, n ) 
 *	int menuselect( menu, low, high )
 */
#include "header.hh"


/* A safe version of gets() that will not overflow the array for a
 * user entry, thereby avoiding Segmentation violation if idiot user leans
 * on keyboard and hits return.
 * Gets a string into arr without LF and ending with NUL, and filtering out
 * all control characters.
 */

char *Gets( arr, arrsz ) /* A safe version of gets() */
char *arr;
int arrsz;
{
	extern void filaray();

	int c, k;

	/* Before use, clean arr by filling it with nul characters */
	filaray( NUL, arr, arrsz );

	k = 0;
	--arrsz;	/* Last index of arr is arrsz-1 */
	/* Break if ascii control or extended ascii */
	while( ( c = getchar() ) >= SP && c < DEL )    {
		if( k < arrsz )
			arr[k++] = (char)c;	
		/* Otherwise we gobble up any remaining chars */
	}
	arr[k] = NUL;

	return( arr );
}


/* Error checking get number for a menu selection used by
 * menuselect()
 */
int gtnum( ar, sz, low, high )
char *ar;
int sz, low, high;
{
	int code;

	errno = 0;
	Gets( ar, sz );
	if( errno == EINTR )    {
		errno = 0;
		/*
		return( ERROR );
		*/
	}
	if( *ar == 'e' )    {
		return( EXITSIG );
	}
	if( !isdigit( *ar ) )
		return( ERROR );
	if( (*ar == NUL) || (sscanf( ar, "%d", &code ) != 1) )    {
		printf( "Unrecognized choice: %s\n", ar );
		sleep( 2 );
		return( ERROR );
	}
	if( code > high || code < low )    {
		printf( "\n\n\t\t\t*** OUT OF BOUNDS ***\n\n\n" );
		sleep( 2 );
		return( ERROR );
	}

	return( code );
}

int gtyesno( ar, sz )
char *ar;
int sz;
{
	char *Gets();

	errno = 0;
	while( 1 )    {
		Gets( ar, sz );
		/* We return to the calling function with
		 * a value to cause looping back to the printf that
		 * says what question is to be answered.
		 */
		if( errno == EINTR )    {
			errno = 0;
			return( ERROR );
		}
		if( *ar == 'e' )    {
			return( EXITSIG );
		}
		else if( *ar  == 'y' || *ar == 'Y' )    {
			return( TRUE );
		}
		else if( *ar  == 'n' || *ar == 'N' )    {
			return( FALSE );
		}
		else    {
			printf( "\n\t\t\tANSWER THE QUESTION! (y/n)\n\n" );
			return( ERROR );
		}
	}
}


int gtdate( dtype, ar, sz )
char *dtype, *ar;
int sz;
{
	extern void gtsysdate();
	extern int system(), isdate();

	char *Gets();


	while( 1 )    {
		gtsysdate();
		printf( "Today: %s\n", c_datestr );
		system( TODAYPROG );
		printf( "\nENTER %s DATE (mm/dd/yy)> ", dtype );
		errno = 0;
		Gets( ar, sz );
		if( errno == EINTR )    {
			/* Result of DEL */
			errno = 0;
			continue;
		}
		if( *ar == 'e' )
			return( FALSE );
		if( *ar == NUL )    {
			continue;
		}
		if( isdate( ar ) == TRUE )    {
			break;
		}
		else    {
			continue;
		}
	}
	return( TRUE );
}

float gtfloat( msg )
char *msg;
{
	extern int issfloat();

	char *Gets();
	char ar[ PRICELEN ];
	float tf;

	while( 1 )    {
		printf( "\n\n%s> ", msg );
		errno = 0;
		Gets( ar, PRICELEN );
		if( errno == EINTR )    {
			errno = 0;
			continue;
		}
		if( *ar == 'e' )
			return( (float) (-1) );
		if( *ar == NUL )    {
			continue;
		}
		if( sscanf( ar, "%f", &tf ) != 1 )    {
			putchar( BEL );
			printf( "\nERROR: not proper dollar amount.\n" );
			continue;
		}
		if( tf < (float)0 )    {
			putchar( BEL );
			printf( "\nERROR: Illegal negative value.\n" );
			continue;
		}
		/* A lexical check on the string for format
		 * of allowed float or int entry.
		 */
		if( !issfloat( ar ) )    {
			putchar( BEL );
			printf( "\nERROR: Illegal float syntax.\n" );
			continue;
		}
		else
			break;
	}
	return( tf );
}

float gtbigfloat( msg )
char *msg;
{
	extern int issfloat();

	char *Gets();
	char ar[BIGPRICELEN];
	float tf;

	while( 1 )    {
		printf( "\n\n%s> ", msg );
		errno = 0;
		Gets( ar, BIGPRICELEN );
		if( errno == EINTR )    {
			errno = 0;
			continue;
		}
		if( *ar == 'e' )
			return( (float) (-1) );
		if( *ar == NUL )    {
			continue;
		}
		if( sscanf( ar, "%f", &tf ) != 1 )    {
			printf( "\nNOT PROPER DOLLAR AMOUNT\n" );
			continue;
		}
		/* A lexical check on the string for format
		 * of allowed float or int entry.
		 */
		if( !issfloat( ar ) )    {
			putchar( BEL );
			printf( "\nERROR: Illegal float syntax.\n" );
			continue;
		}
		else
			break;
	}
	return( tf );
}


/* A get string function protected from vacuous entry and with better
 * clarity of interrogation after a return from interrupt.
 * For user entered string type data.
 * NOTE that the array is returned padded with padch, not NUL, up to its
 * NUL terminator.
 */

int Gtstr( padch, msg, s, sz )
char padch;
char *msg, *s;
int sz;
{
	char *Gets();

	char *sptr;
	int k, len;

	while( 1 )    {
		printf( "\n\n%s> ", msg );
		errno = 0;
		Gets( s, sz );
		if( errno == EINTR )    {
			errno = 0;
			continue;
		}
		len = strlen( s );
		if( *s == 'e' && len == 1 )
			return( EXITSIG );
		if( *s == NUL )    {
			/* User has hit return */
			continue;
		}
		else
			break;
	}
	/* Finish padding with padch: */
	/* Point at first NUL */
	sptr = s + len;
	k = len;
	while( k < sz - 1 )    {
		*sptr = padch;
		++k;
		++sptr;
	}
	return( len );
}

/*----------------------------------------------------------------------*/


/* Write a line to a named file
 * Newline must be supplied by calling function
 */
int lprintf( l, f ) /* Write a line to a named file */
char *l, *f;
{
	FILE *aptr;

	if( access( f, 00 ) != 0 )    {
		/* File does not exist */
		if( (aptr = Fopen( "lprintf", f, "w", aptr )) == NULL )    {
			return( ERROR );
		}
	}
	else    {
		if( (aptr = Fopen( "lprintf", f, "a", aptr )) == NULL )    {
			return( ERROR );
		}
	}
	fprintf( aptr, "%s", l );
	fclose( aptr );
	return( TRUE );
}

void display( fn, n ) /* Display the last n lines of a named file fn */
char *fn;
int n;
{
	extern int flc();

	FILE *rptr;
	char line[ MAXLINE ];
	int k, lno;

	/* Get line count */
	lno = flc( fn );
	/* Line number at which to start printing */
	lno -= n;

	if( (rptr = Fopen( "display", fn, "r", rptr ))  == NULL )
		return;

	k = 0;
	while( fgets( line, MAXLINE, rptr ) != NULL )    {
		if( ++k > lno )
			printf( "%s", line );
	}
	fclose( rptr );
}

int linedisplay( fn, n ) /* Display the n-th line of a named file fn */
char *fn;
int n;
{
	extern void until_lf();

	FILE *rptr;
	char line[MAXLINE];
	int k, lno;

	if( (rptr = Fopen( "display", fn, "r", rptr ))  == NULL )
		return( FALSE );

	k = 0;
	while( fgets( line, MAXLINE, rptr ) != NULL )    {
		if( ++k == n )    {
			printf( "%s", line );
			break;
		}
	}
	fclose( rptr );
	if( k < n )    {
		putchar( BEL );
		printf( "FILE ERROR: %s does not have line %d\n", fn, n );
		until_lf();
		return( FALSE );
	}
	return( TRUE );
}


int menuselect( menu, low, high )
void (*menu)();
int low, high;
{
	int gtnum();

	char nstr[4];
	int rv;

	do    {
		(*menu)();
		rv = gtnum( nstr, 4, low, high );
		switch( rv )    {
			case EXITSIG:	/* 'e' signal to get out */
				return( EXITSIG );
			case ERROR:	/* Error in choice */
				continue;
			default:	/* A good value */
				return( rv );
		}

	} while( 1 );

	/* Not Reached */
	return( ERROR );
}



Return to Home Page Return to Metayoga Page Return to C Language Page


The URL for this document is:
http://graham.main.nc.us/~bhammel/graham/CPROGS/io.html
Created: 1997
Last Updated: May 28, 2000 Email me, Bill Hammel at
bhammel@graham.main.nc.us
READ WARNING BEFORE SENDING E-MAIL