⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ftoprtf.h

📁 电力系统中的保护装置全部代码
💻 H
📖 第 1 页 / 共 2 页
字号:
/********************************************************
    Copyright 1989 Software Development Systems, Inc.
    All Rights Reserved.

    Routine to print floating types in printf-style
    formats.
********************************************************/
#include "abbr.h"
#include "prflt.h"

extern char *FTOA PROTOE((char *, int, FLT *, int, int *, int *));

/****************************************************************
    Emit a floating point quantity in printf format.

	put:	 function to emit a character (see below)
	where:	 pointer argument for "put" (see below)
	flt:	 pointer to the value to be converted and emitted
	fmt: 	 format: f, e, E, g, or G
	pp:	 pointer to a structure containing parameters

	returns: the number of characters emitted or -1 if a
		 "put" of any character fails.

    The arguments "put" and "where" are used as follows:

	    put( c, where )

    The function "put" should be declared as follows:

	    int put( int c, TYPE *where )

    TYPE may be any data type; normally it is "char" or "FILE",
    depending upon where "put" places its output.  The function
    "put" puts the character "c" into "where".  For example if
    "where" is a buffer, "c" would be appended to the end of the
    buffer. "put" must of course keep track of the current buffer
    position.

    "put" returns its argument "c" on success, or -1 on failure.
****************************************************************/
int
FTOPRTF PROTO5( (put, where, flt, fmt, pp),
int (*put)PROTOE((int,char *)),
register char *where,
FLT *flt,
int fmt,
const struct prflt *pp ) /* structure should not be modified, hence "const" */
{
    /********************************************************************
	A printed floating point number is a sequence of fields:
    ********************************************************************/

    /* PREFIX */

	int lpadb = 0;	/* number of blank chars to emit for padding of right-
			   justified numbers (if blank padding was chosen) */
	int sign = 0;	/* may be zero (indicating no sign), '+' or blank for
			   positive numbers, or '-' for negative numbers */
	int lpadz = 0;	/* number of zeroes to emit for zero padding of right-
			   justified numbers (if zero padding was chosen) */

    /* CENTER */

	int lsig = 0;	/* number of significant digits preceding the decimal
			   point (always one in basic format "e") */
	int lzero = 0;	/* number of zeroes to be used in zero-fill immediately
			   preceding the decimal point */
	int prtpt = 0;	/* print the decimal point?  0=>no, 1=>yes */
	int rzero = 0;	/* number of zeroes to be used in zero-fill immediately
			   following the decimal point */
	int rsig = 0;	/* number of significant digits following the decimal
			   point */
	int rprcz = 0;	/* number of zeroes to emit for zero-fill needed to
			   satisfy precision ("g" alternate and "f" only) */

    /* SUFFIX */

	int expwid = 0;	/* width (in chars) of the printed exponent */
	int rpadb = 0;	/* number of blank chars to emit for padding of left-
			   justified numbers (even if zero padding chosen) */

    /********************************************************************
	All fields are optional except that either "lsig" or "lzero"
	must be nonzero when we're ready to print. The term "significant"
	above means

	    a) any nonzero digit or
	    b) any zero appearing between nonzero digits (that are not
	       part of the exponent)

	Formats "e" and "f" are considered "basic formats", whereas "g"
	is not a basic format; all printings of "g" specifications are
	converted to either "e" or "f". However use of "g" modifies the
	interpretations of various option fields.

	Mutually exclusive field pairs (i.e. pairs of fields which cannot
	both be nonzero) are: [lpadb and lpadz], [lpadb and rpadb],
	[lpadz and rpadb], [lsig and rzero], and [lzero and rzero].
	If both lsig and rsig are nonzero, then neither lzero nor rzero
	will be nonzero.
    ********************************************************************/

    /********************************************************************
	Various other declarations.
    ********************************************************************/
    register int sigdigs;		/* # of signif. digits */
    register int expval;		/* value of exponent */
    register int basicF;		/* basic format: 0=>e, 1=>f */
    int slength;			/* output string length */
    int wasupper = 0;			/* was "fmt" in upper case? */

    /********************************************************************
	Buffers & associated variables.
    ********************************************************************/
    auto int decpt, isneg;	/* arguments for FTOA below */
    char  conv[MAXN+1];		/* buffer for FTOA converted values */

#   define EBSZ	8		/* exponent buffer size */
    char ebuf[EBSZ];		/* buffer for exponent E+nnnnn */
    register char *expp = 0;	/* exponent pointer */
    register char *convp;	/* significant digit pointer */

    struct prflt lp;		/* local copy of "pp" for efficiency */

    /************************************************************
	Initialize local copy of "pp" (cannot do it above be-
	cause some compilers cannot handle auto aggregate init-
	ialization).  We make a local copy because the structure
	is accessed so frequently; therefore we don't want to
	be doing an indirection with every access. Next, be sure
	that the specified precision has a reasonable value.
    ************************************************************/
    lp = *pp;
    if( lp.precision < 0 ) lp.precision = 6;	/* default */

    /************************************************************
	Convert "fmt" into a lower case version of itself
	(for use in switches below) and remember whether
	it was an upper case letter.
    ************************************************************/
    if( fmt == 'E' ) { fmt = 'e'; wasupper = 1; }
    else if( fmt == 'G' ) { fmt = 'g'; wasupper = 1; }

    /************************************************************
	    Perform the conversion to ASCII according to
	    the chosen format.
    ************************************************************/
    switch( fmt )
    {
	case 'f':
	/************************************************************
	    Precision here is interpreted as "digits after the
	    decimal point". FTOA will generate that many digits
	    plus however many digits are needed before the point.
	************************************************************/
	FTOA( conv, 1, flt, lp.precision, &decpt, &isneg );
	break;

	case 'e':
	/************************************************************
	    The passed-in notion of "precision" means "digits
	    after the decimal point", but in "e" notation we are
	    going to guarantee that precisely one digit appears
	    BEFORE the decimal point, so we must augment FTOA's
	    notion of how many digits to generate, and have it
	    count significant digits only (rather than digits
	    after the decimal point) since the point is "floating".
	************************************************************/
	FTOA( conv, 0, flt, lp.precision+1, &decpt, &isneg );
	break;

	case 'g':
	/************************************************************
	    A strange mix of "f" and "e". The precision implies
	    "significant digits", so like "f" there is no need
	    to augment the precision but like "e" we must ask
	    for significant digits only, rather than digits after
	    the point. NOTE: ANSI requires that zero precision
	    be interpreted as a precision of one instead.
	************************************************************/
	if( lp.precision == 0 ) lp.precision = 1;
	FTOA( conv, 0, flt, lp.precision, &decpt, &isneg );
	break;

	default: return -1;	/* error */
    }

    /****************************************************************
	Calculate the length of the string returned by FTOA above,
	NOT COUNTING TRAILING ZEROES. Note: strchr and strlen cannot
	be used in a "flt" routine, so calculate the length of the
	string directly.
    ****************************************************************/
    convp = conv;
    while ( *convp ) { ++convp; }
    while( (convp > conv) && (*(convp-1) == '0') ) --convp;
    sigdigs = convp - conv;

    /************************************************************
	Determine the value of the exponent. If there are no
	significant digits then the exponent and decimal
	point position are zero. Otherwise the exponent is
	determined by the location of the decimal point, and
	the decimal point field is valid.

	NOTE: "isneg" is not affected by sigdigs==0 because we
	want the sign to be printed according to whether the
	value being converted is negative (ANSI is somewhat vague
	on this but that is one way to read it).  Among other
	things this lets %+5.2f of -1e-20 print as -0 instead
	of +0.
    ************************************************************/
    if( sigdigs == 0 ) { expval = 0; decpt = 0; }
    else expval = decpt - 1;

    /***********************************************************
	Determine the basic format, which is either "e" or "f".
    ***********************************************************/
    if( fmt == 'g' )
    {
	/***********************************************************
	    We use "e" format if the printed exponent will be less
	    than -4 or greater than or equal to the precision,
	    otherwise we use "f".
	***********************************************************/
	if( expval < -4 || expval >= lp.precision ) basicF = 0;
	else basicF = 1;
    }
    else basicF = fmt == 'f';

    /************************************************************
	Determine the value of "sign". "isneg" is nonzero if
	the number is negative. If we're not forcing a sign
	and the number is not negative, we must choose between
	printing a blank or no sign at all.
    ************************************************************/
    sign = isneg? '-': '+';
    if( !lp.sign && !isneg ) sign = (lp.blank? ' ': 0);

    /************************************************************
	Determine lsig and lzero, and establish preliminary
	values for rzero and rsig.
    ************************************************************/
    if( basicF )
    {
	/***************************************************
	    "f" format may require placing zeroes around
	    the decimal point.
	***************************************************/
	if( decpt <= 0 )
	{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -