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

📄 wsprintf.c

📁 是一个手机功能的模拟程序
💻 C
📖 第 1 页 / 共 4 页
字号:
   /*------------------------------------------------------------------------*/
   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 + -