📄 _printfi.c
字号:
}
}
else
memset(f_start, ' ', (where - f_start));
}
#ifndef NOFLOAT
/*****************************************************************************/
/* _PPPROC_FGE - Process the conversion for f, g, G, e, and E */
/* */
/* This function takes the structure PFIELD, which contains all of the */
/* flags and parameters to process the conversion, and it does this */
/* conversion, and stores the result in the string pointed to by */
/* *A_IT. */
/*****************************************************************************/
static void _pproc_fge(_PFIELD *pfield, int *minus_flag, char **a_it,
va_list *_ap)
{
/*------------------------------------------------------------------------*/
/* Local variables */
/*------------------------------------------------------------------------*/
long double cvt = 0;
/*------------------------------------------------------------------------*/
/* Determine what kind of argument is coming next, and read it into CVT. */
/*------------------------------------------------------------------------*/
switch(_STCHK(pfield, _MFLD))
{
case 0 : cvt = (double)va_arg((*_ap), double);
break;
default : cvt = va_arg((*_ap), long double);
}
/*------------------------------------------------------------------------*/
/* If CVT is negative, set the MINUS_FLAG and reverse the sign of CVT. */
/*------------------------------------------------------------------------*/
if((*minus_flag = (cvt < 0)) != 0) cvt = -cvt;
/*------------------------------------------------------------------------*/
/* Call the proper conversion function */
/*------------------------------------------------------------------------*/
switch(pfield->conv)
{
case 'f' : _pconv_f(cvt, pfield, a_it);
break;
case 'e' :
case 'E' : _pconv_e(cvt, pfield, a_it);
break;
case 'g' :
case 'G' : _pconv_g(cvt, pfield, a_it);
}
}
/*****************************************************************************/
/* _PCONV_F - Perform the %f conversion */
/*****************************************************************************/
static void _pconv_f(long double cvt, _PFIELD *pfield, char **a_it)
{
/*------------------------------------------------------------------------*/
/* Local variables */
/*------------------------------------------------------------------------*/
char tmpbuf[400];
int dpt,
sign,
putdec;
/*------------------------------------------------------------------------*/
/* If no precision was specified, set it to 6. */
/*------------------------------------------------------------------------*/
if(pfield->precision < 0) pfield->precision = 6;
/*------------------------------------------------------------------------*/
/* Call the FCVT float to string function, then copy the fractional part, */
/* determine whether or not a decimal point should be placed, and copy */
/* whole number part. */
/*------------------------------------------------------------------------*/
strcpy(tmpbuf, fcvt(cvt, pfield->precision, &dpt, &sign));
_fcpy(tmpbuf, dpt, 1, pfield->precision, a_it);
putdec = (dpt != (int)strlen(tmpbuf) || _STCHK(pfield, _PFPOUND)) ? 1 : 0;
_mcpy(tmpbuf, dpt, putdec, a_it);
}
/*****************************************************************************/
/* _PCONV_E - Perform the %e conversion */
/*****************************************************************************/
static void _pconv_e(long double cvt, _PFIELD *pfield, char **a_it)
{
/*------------------------------------------------------------------------*/
/* Local variables */
/*------------------------------------------------------------------------*/
char tmpbuf[100];
int dpt,
sign,
putdec,
exp = 0;
/*------------------------------------------------------------------------*/
/* If no precision was specified, set it to 6. */
/*------------------------------------------------------------------------*/
if(pfield->precision < 0) pfield->precision = 6;
/*------------------------------------------------------------------------*/
/* Check if CVT is within legal range -HUGE_VALL <= CVT <= HUGE_VALL */
/*------------------------------------------------------------------------*/
if (cvt >= HUGE_VALL) cvt = HUGE_VALL;
else if (cvt <= -HUGE_VALL) cvt = -HUGE_VALL;
/*------------------------------------------------------------------------*/
/* Convert CVT to x.xxxe+xx form, keeping the exponent in EXP. */
/*------------------------------------------------------------------------*/
if(cvt)
{
for(;cvt < 1; cvt *= 10, exp--);
for(;cvt >= 10; cvt /= 10, exp++);
}
/*------------------------------------------------------------------------*/
/* Call the FCVT float to string function, copy the exponent part, the */
/* fractional part, then determine whether or not a decimal point should */
/* be placed, and copy the whole number part. */
/*------------------------------------------------------------------------*/
strcpy(tmpbuf, fcvt(cvt, pfield->precision, &dpt, &sign));
if(dpt==2) /* fcvt() might have rounded the number */
{
dpt--; exp++; tmpbuf[strlen(tmpbuf)-1] = 0;
}
_ecpy(exp, pfield->conv, a_it);
_fcpy(tmpbuf, dpt, 1, pfield->precision, a_it);
putdec = (dpt != (int)strlen(tmpbuf) || _STCHK(pfield, _PFPOUND)) ? 1 : 0;
_mcpy(tmpbuf, dpt, putdec, a_it);
}
/*****************************************************************************/
/* _PCONV_G - Perform the %g conversion */
/*****************************************************************************/
static void _pconv_g(long double cvt, _PFIELD *pfield, char **a_it)
{
/*------------------------------------------------------------------------*/
/* Local variables */
/*------------------------------------------------------------------------*/
char tmpbuf[100];
char *check;
int dpt,
sign,
putdec,
exp = 0,
change_test = 0;
/*------------------------------------------------------------------------*/
/* If the precision was given as 0, set it to one. */
/*------------------------------------------------------------------------*/
if(pfield->precision == 0) pfield->precision = 1;
/*------------------------------------------------------------------------*/
/* If no precision was specified, set it to 6. */
/*------------------------------------------------------------------------*/
if(pfield->precision < 0) pfield->precision = 6;
strcpy(tmpbuf, ecvt(cvt, pfield->precision, &dpt, &sign));
/*------------------------------------------------------------------------*/
/* If the exponent is less than -4, or greater than or equal to the */
/* precision, convert the number as a %e conversion. Otherwise convert */
/* it as a %f conversion. */
/*------------------------------------------------------------------------*/
if(dpt < -3 || dpt > pfield->precision)
{
for(;dpt > 1; dpt--, exp++);
for(;dpt < 1; dpt++, exp--);
_ecpy(exp, pfield->conv-2, a_it);
}
/*------------------------------------------------------------------------*/
/* Copy the fractional part of the number. CHANGE_TEST will be set if */
/* there was a fractional part, otherwise it will remain a zero. */
/*------------------------------------------------------------------------*/
check = *a_it;
_fcpy(tmpbuf, dpt, (_STCHK(pfield, _PFPOUND)) ? 1 : 0, pfield->precision,
a_it);
change_test = (check != *a_it);
/*------------------------------------------------------------------------*/
/* If the '#' flag was used, or there was a fractional part to the number */
/* a decimal point will be placed. */
/*------------------------------------------------------------------------*/
putdec = (_STCHK(pfield, _PFPOUND) || change_test) ? 1 : 0;
_mcpy(tmpbuf, dpt, putdec, a_it);
}
/*****************************************************************************/
/* _FCPY - Copy the fraction part of a float to a string */
/*****************************************************************************/
static char *_fcpy(const char *tmpbuf, int dpt, int trail, int precision,
char **a_it)
{
/*------------------------------------------------------------------------*/
/* Local variables */
/*------------------------------------------------------------------------*/
int i;
char *tmpptr = (char *)tmpbuf + strlen(tmpbuf) -1;
/*------------------------------------------------------------------------*/
/* Fill all unused precision spaces with zeros. */
/*------------------------------------------------------------------------*/
for(i = 0; i < precision && dpt > (int)strlen(tmpbuf) && trail; i++)
*((*a_it)--) = '0';
/*------------------------------------------------------------------------*/
/* Copy the fractional part of the float into the string. */
/*------------------------------------------------------------------------*/
if(dpt < (int)strlen(tmpbuf) && dpt >= 0)
{
i = (int)strlen(tmpbuf) - dpt;
/*---------------------------------------------------------------------*/
/* Skip trailing zeros if TRAIL is not set. */
/*---------------------------------------------------------------------*/
if(! trail) for(; i > 0 && *tmpptr == '0'; tmpptr--, i--);
for(; i > 0; tmpptr--, i--) *((*a_it)--) = *tmpptr;
}
/*------------------------------------------------------------------------*/
/* Place any leading fractional zeros if necessary. */
/*------------------------------------------------------------------------*/
if(dpt < 0)
{
if (-dpt < precision)
for(i = strlen(tmpbuf); i > 0; tmpptr--, i--) *((*a_it)--) = *tmpptr;
if (-dpt > precision) dpt = -precision;
for(i = -dpt; i > 0; i--) *((*a_it)--) = '0';
}
return (*a_it);
}
/*****************************************************************************/
/* _ECPY - Copy the "e+xx" part of a float to a string */
/*****************************************************************************/
static char *_ecpy(int exp, char letter, char **a_it)
{
_ltostr((exp > 0) ? exp : -exp, 10, 'd', a_it);
if(exp < 10 && exp > -10) *((*a_it)--) = '0';
*((*a_it)--) = (exp < 0) ? '-' : '+';
*((*a_it)--) = letter;
return (*a_it);
}
/*****************************************************************************/
/* _MCPY - Copy the whole number part of a float to a string */
/*****************************************************************************/
static char *_mcpy(const char *tmpbuf, int dpt, int putdec, char **a_it)
{
/*------------------------------------------------------------------------*/
/* Local variables */
/*------------------------------------------------------------------------*/
int i;
char *tmpptr = NULL;
/*------------------------------------------------------------------------*/
/* If the number has both a whole number part and a fractional part, */
/* position TMPPTR to the last character of the whole number. */
/*------------------------------------------------------------------------*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -