📄 wsprintf.c
字号:
/*------------------------------------------------------------------------*/
int digits = 0;
int base;
unsigned long cvt;
/*------------------------------------------------------------------------*/
/* If no precision was given, set it to 1. */
/*------------------------------------------------------------------------*/
if (pfield->precision < 0) pfield->precision = 1;
/*------------------------------------------------------------------------*/
/* Set the base of the number by the type of conversion specified. */
/*------------------------------------------------------------------------*/
switch (pfield->conv)
{
case 'p' :
case 'x' :
case 'X' : base = 16;
break;
case 'o' : base = 8;
break;
case 'u' :
case 'd' :
case 'i' : base = 10;
}
/*------------------------------------------------------------------------*/
/* Get the next argument. */
/*------------------------------------------------------------------------*/
cvt = _getarg_diouxp(pfield, _ap);
/*------------------------------------------------------------------------*/
/* If the precision is 0, and the number is 0, do nothing and return 1. */
/*------------------------------------------------------------------------*/
if (pfield->precision == 0 && cvt == 0) return 1;
/*------------------------------------------------------------------------*/
/* If the number is signed and negative, set the minus sign flag, and */
/* multiply the number by -1. */
/*------------------------------------------------------------------------*/
if ((pfield->conv == 'd' || pfield->conv == 'i')
&& ((long)cvt < 0))
{
*minus_flag = 1;
cvt = (long)cvt * -1;
}
/*------------------------------------------------------------------------*/
/* Call the function to convert the number to a string, and add the */
/* total number of digits assigned into DIGITS. */
/*------------------------------------------------------------------------*/
digits += _ltostr(cvt, base, pfield->conv, a_it);
/*------------------------------------------------------------------------*/
/* Fill in the remainder of the precision with zeros. */
/*------------------------------------------------------------------------*/
while (digits++ < pfield->precision) *((*a_it)--) = '0';
/*------------------------------------------------------------------------*/
/* If the "#" flag was used in the X or x conversion, prefix a "0x" or */
/* "0X" to the hexadecimal number. */
/*------------------------------------------------------------------------*/
if ((pfield->conv == 'x' || pfield->conv == 'X') && _STCHK(pfield, _PFPOUND))
{
*((*a_it)--) = pfield->conv;
*((*a_it)--) = '0';
}
/*------------------------------------------------------------------------*/
/* If the "#' flag was used in the o conversion, prefix a "0" to the */
/* octal number. */
/*------------------------------------------------------------------------*/
if (pfield->conv == 'o' && _STCHK(pfield, _PFPOUND)) *((*a_it)--) = '0';
return(0);
}
/*****************************************************************************/
/* _GETARG_DIOUXP - Get the argument for a d, i, o, u, x, or p conversion */
/* */
/* This function takes the next argument off the argument list, after */
/* determining what kind of argument it is. It decides this by checking */
/* to see if the 'h' or the 'l' flag was used. It returns the next */
/* argument. */
/* */
/*****************************************************************************/
static unsigned long _getarg_diouxp(_PFIELD *pfield, va_list *_ap)
{
/*------------------------------------------------------------------------*/
/* Local variables */
/*------------------------------------------------------------------------*/
unsigned long cvt;
/*------------------------------------------------------------------------*/
/* Get the number from the next argument. Determine what kind of */
/* argument by checking for the h or l flag in the format specification. */
/*------------------------------------------------------------------------*/
switch (_STCHK(pfield, (_MFH | _MFL)))
{
case _MFH : switch (pfield->conv)
{
case 'd' :
case 'i' : cvt = va_arg(*_ap, int);
break;
case 'p' :
case 'o' :
case 'u' :
case 'x' :
case 'X' : cvt = va_arg(*_ap, unsigned int);
}
break;
case _MFL : switch (pfield->conv)
{
case 'd' :
case 'i' : cvt = va_arg(*_ap, long int);
break;
case 'p' :
case 'o' :
case 'u' :
case 'x' :
case 'X' : cvt = va_arg(*_ap, unsigned long int);
}
break;
default : switch (pfield->conv)
{
case 'd' :
case 'i' : cvt = va_arg(*_ap, int);;
break;
case 'p' :
case 'o' :
case 'u' :
case 'x' :
case 'X' : cvt = va_arg(*_ap, unsigned int);
}
break;
}
return(cvt);
}
/*****************************************************************************/
/* _LTOSTR - Convert an integer to a string of up to base 16 */
/* */
/* This function takes an unsigned long integer, converts it to a string */
/* which is pointed to by *A_IT. The result will also be converted to */
/* a base corresponding to the variable base. */
/* */
/*****************************************************************************/
static int _ltostr(unsigned long cvt, int base, char conv, char **a_it)
{
/*------------------------------------------------------------------------*/
/* Local Variables */
/*------------------------------------------------------------------------*/
unsigned long quot,
rem;
char *bnum = "0123456789abcdef0123456789ABCDEF";
/*------------------------------------------------------------------------*/
/* The number CVT will be converted to a string by taking the remainder */
/* of a division of it by its base, and converting it to a character. */
/* The number CVT is then set equat to itself divided by its base, and */
/* this continues until CVT is 0. */
/*------------------------------------------------------------------------*/
if (! cvt) *((*a_it)--) = '0';
while (cvt)
{
quot = _div(cvt, base);
rem = cvt - (quot * base);
if (conv == 'X') rem += 16;
*((*a_it)--) = bnum[rem];
cvt = quot;
}
return(strlen(*a_it) -1);
}
/*****************************************************************************/
/* _DIV - Divide two integers */
/* */
/* This function takes an unsigned long, and divides it by an integer. */
/* This function exists because when an integer is greater than the */
/* largest signed long integer, the conventional '/' operator overflows. */
/* This function is used by _LTOSTR when it is converting an unsigned int */
/* to a string. */
/* */
/*****************************************************************************/
static unsigned long _div(unsigned long cvt, int base)
{
/*------------------------------------------------------------------------*/
/* If the '/' operator will not overflow, use it. */
/*------------------------------------------------------------------------*/
if (cvt <= LONG_MAX) return(cvt / base);
/*------------------------------------------------------------------------*/
/* In the case that the base is 8 or 16, the division can be done using */
/* bit operations. For base 10, the numerator and the divisor are */
/* converted into double floating point numbers, where the '/' operator */
/* will work properly. */
/*------------------------------------------------------------------------*/
else
switch (base)
{
case 8 :
case 16 : while ((base >>=1) > 0) cvt >>=1; break;
case 10 : cvt >>= 1;
cvt /= 5;
break;
}
return(cvt);
}
#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)) 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);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -