Source for ASCII to FLOAT

~Jay Sturges jsturges at pldote.intel.com
Wed Jul 12 07:39:02 AEST 1989


/*
 * Here is a routine written some time ago
 * which will perform ASCII to float conversions
 *
 * Enjoy,
 *
 * Jay Sturges      sun!sacto!pldote!jsturges
 *
 */
#include <stdio.h>

#define MAXEXP	38		/* maximum exponent */
#define MINEXP	-38		/* minimum exponent */

#define EOL	'\0'		/* end of line */
#define DOT	'.'		/* decimal point */
#define TRUE	1
#define FALSE	0
#define CVALUE(c) (c - '0')	/* numerical value of char */

typedef	char	boolean;	/* flagging type */

/*
 * atof( )
 * string to double conversion in C language
 *
 */
atof(t, value)
char 	*t;
real	*value;
{
	boolean	eflg = FALSE;	/* exponetial flag */
	boolean	dflg = FALSE;	/* decimal point flag */
	boolean sflg = FALSE;	/* sign (+/-) flag */
	boolean	error  = FALSE;	/* error case	*/
	real	gtvalue = 0;	/* value of the string */
	real	dsign = 1.0;	/* sign of the mantissa */
	int	esign = 1; 	/* sign of exponetial */
	int	exp  = 0;	/* exponetial value */
	int	didx = 0;	/* places after decimal pt. */
	int	big = 0;	/* keeping track of the value */

	while (*t != EOL && !error)
	{
		switch (*t)
		{
		case 'e':		/* exponetial flag */
		case 'E':		/* reset sign flag */
			if (eflg) error = TRUE;
			else	  
			{
				eflg  = TRUE;
				sflg  = FALSE;
			}
			break;
		case DOT:		/* decimal point flag */
			if (dflg) error = TRUE;
			else	  
			{	/*
				 * starting counting digits
				 * after decimal point
				 */
				dflg  = TRUE;
				didx = 1;
			}
			break;
		case '-':		/* sign flag */
		case '+':
			if (sflg) error = TRUE;
			else	  
			{
				sflg  = TRUE;
				if (!eflg && *t == '-')
					dsign = -1.0;
				else if (eflg && *t == '-')
					esign = -1;
			}
			break;
		case '0':		/* unsigned part of the  */
		case '1':		/* exponetial and the    */
		case '2':		/* mantissa.		 */
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			if (eflg)
				exponetial(*t, &exp);
			else
			{
				if (big >= MAXEXP) 
					error = TRUE;
				else
				{
					mantissa(*t,&gtvalue,didx,dflg,&big);
					if (dflg) didx++;
				}
			}
			break;
                case ' ':
			break;
		default:
			error = TRUE;
		}
		t++;
	}

	/*
	 * having the exponetial, the mantissa, the signs of them
	 * the value can be computed, if possible
	 */
	if (!error)
	{
		/*
		 * signed exponetial and mantissa
		 */
		exp *= esign;
		gtvalue *= dsign;

		if (exp > MAXEXP || exp < MINEXP || 
			(exp + big) > MAXEXP ||
			(exp + big) < MINEXP)
			error = TRUE;
		else if (exp > 0)
			while (--exp >= 0)
				gtvalue *= 10.0;
		else if (exp < 0)
			while (++exp <= 0)
				gtvalue *= 0.1;
		*value = gtvalue;
		/*
		 * you can exponent zero with any number
		 * and it is still a legal case
		 */
		if (*value == 0.0)
			error = FALSE;
	}
	return (error);
}


/*
 * basically, atoi()
 */
static	exponetial(c, exp)
char	c;
int	*exp;
{
	*exp *= 10;
	*exp += CVALUE(c);
}


static	mantissa(c, value, didx, decimal, big)
char	c;
real	*value;
int	didx;
boolean	decimal;
int	*big;
{
	real	dtmp;

	if (!decimal)
	{
		/*
		 * before the decimal point
		 * keeping increasing the value
		 */
		*value *= 10.0;
		*value += (real) CVALUE(c);
		if (*value > 0.0)
			(*big)++;
	}
	else
	{
		/*
		 * after the decimal point
		 */
		dtmp = CVALUE(c);
		if (didx >= MAXEXP)
		{	/* too small, it's virtually zero */
			dtmp = 0.0;
			didx = 0;
		}
		while (--didx >= 0)	/* C is pass by value */
			dtmp *= 0.1;
		*value += dtmp;
	}
}



More information about the Comp.lang.c mailing list