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

📄 printf_fp.c

📁 绝对正真的stdio.h的实现
💻 C
📖 第 1 页 / 共 3 页
字号:
      }    else      {	dig_max = info->prec < 0 ? 6 : (info->prec == 0 ? 1 : info->prec);	if ((expsign == 0 && exponent >= dig_max)	    || (expsign != 0 && exponent > 4))	  {	    if ('g' - 'G' == 'e' - 'E')	      type = 'E' + (info->spec - 'G');	    else	      type = isupper (info->spec) ? 'E' : 'e';	    fracdig_max = dig_max - 1;	    intdig_max = 1;	    chars_needed = 1 + 1 + fracdig_max + 1 + 1 + 4;	  }	else	  {	    type = 'f';	    intdig_max = expsign == 0 ? exponent + 1 : 0;	    fracdig_max = dig_max - intdig_max;	    /* We need space for the significant digits and perhaps	       for leading zeros when < 1.0.  The number of leading	       zeros can be as many as would be required for	       exponential notation with a negative two-digit	       exponent, which is 4.  */	    chars_needed = dig_max + 1 + 4;	  }	fracdig_min = info->alt ? fracdig_max : 0;	significant = 0;		/* We count significant digits.	 */      }    if (grouping)      {	/* Guess the number of groups we will make, and thus how	   many spaces we need for separator characters.  */	ngroups = __guess_grouping (intdig_max, grouping);	chars_needed += ngroups;      }    /* Allocate buffer for output.  We need two more because while rounding       it is possible that we need two more characters in front of all the       other output.  If the amount of memory we have to allocate is too       large use `malloc' instead of `alloca'.  */    buffer_malloced = ! __libc_use_alloca (chars_needed * 2 * sizeof (wchar_t));    if (buffer_malloced)      {	wbuffer = (wchar_t *) malloc ((2 + chars_needed) * sizeof (wchar_t));	if (wbuffer == NULL)	  /* Signal an error to the caller.  */	  return -1;      }    else      wbuffer = (wchar_t *) alloca ((2 + chars_needed) * sizeof (wchar_t));    wcp = wstartp = wbuffer + 2;	/* Let room for rounding.  */    /* Do the real work: put digits in allocated buffer.  */    if (expsign == 0 || type != 'f')      {	assert (expsign == 0 || intdig_max == 1);	while (intdig_no < intdig_max)	  {	    ++intdig_no;	    *wcp++ = hack_digit ();	  }	significant = 1;	if (info->alt	    || fracdig_min > 0	    || (fracdig_max > 0 && (fracsize > 1 || frac[0] != 0)))	  *wcp++ = decimalwc;      }    else      {	/* |fp| < 1.0 and the selected type is 'f', so put "0."	   in the buffer.  */	*wcp++ = L'0';	--exponent;	*wcp++ = decimalwc;      }    /* Generate the needed number of fractional digits.	 */    while (fracdig_no < fracdig_min	   || (fracdig_no < fracdig_max && (fracsize > 1 || frac[0] != 0)))      {	++fracdig_no;	*wcp = hack_digit ();	if (*wcp++ != L'0')	  significant = 1;	else if (significant == 0)	  {	    ++fracdig_max;	    if (fracdig_min > 0)	      ++fracdig_min;	  }      }    /* Do rounding.  */    digit = hack_digit ();    if (digit > L'4')      {	wchar_t *wtp = wcp;	if (digit == L'5'	    && ((*(wcp - 1) != decimalwc && (*(wcp - 1) & 1) == 0)		|| ((*(wcp - 1) == decimalwc && (*(wcp - 2) & 1) == 0))))	  {	    /* This is the critical case.	 */	    if (fracsize == 1 && frac[0] == 0)	      /* Rest of the number is zero -> round to even.		 (IEEE 754-1985 4.1 says this is the default rounding.)  */	      goto do_expo;	    else if (scalesize == 0)	      {		/* Here we have to see whether all limbs are zero since no		   normalization happened.  */		size_t lcnt = fracsize;		while (lcnt >= 1 && frac[lcnt - 1] == 0)		  --lcnt;		if (lcnt == 0)		  /* Rest of the number is zero -> round to even.		     (IEEE 754-1985 4.1 says this is the default rounding.)  */		  goto do_expo;	      }	  }	if (fracdig_no > 0)	  {	    /* Process fractional digits.  Terminate if not rounded or	       radix character is reached.  */	    while (*--wtp != decimalwc && *wtp == L'9')	      *wtp = '0';	    if (*wtp != decimalwc)	      /* Round up.  */	      (*wtp)++;	  }	if (fracdig_no == 0 || *wtp == decimalwc)	  {	    /* Round the integer digits.  */	    if (*(wtp - 1) == decimalwc)	      --wtp;	    while (--wtp >= wstartp && *wtp == L'9')	      *wtp = L'0';	    if (wtp >= wstartp)	      /* Round up.  */	      (*wtp)++;	    else	      /* It is more critical.  All digits were 9's.  */	      {		if (type != 'f')		  {		    *wstartp = '1';		    exponent += expsign == 0 ? 1 : -1;		  }		else if (intdig_no == dig_max)		  {		    /* This is the case where for type %g the number fits		       really in the range for %f output but after rounding		       the number of digits is too big.	 */		    *--wstartp = decimalwc;		    *--wstartp = L'1';		    if (info->alt || fracdig_no > 0)		      {			/* Overwrite the old radix character.  */			wstartp[intdig_no + 2] = L'0';			++fracdig_no;		      }		    fracdig_no += intdig_no;		    intdig_no = 1;		    fracdig_max = intdig_max - intdig_no;		    ++exponent;		    /* Now we must print the exponent.	*/		    type = isupper (info->spec) ? 'E' : 'e';		  }		else		  {		    /* We can simply add another another digit before the		       radix.  */		    *--wstartp = L'1';		    ++intdig_no;		  }		/* While rounding the number of digits can change.		   If the number now exceeds the limits remove some		   fractional digits.  */		if (intdig_no + fracdig_no > dig_max)		  {		    wcp -= intdig_no + fracdig_no - dig_max;		    fracdig_no -= intdig_no + fracdig_no - dig_max;		  }	      }	  }      }  do_expo:    /* Now remove unnecessary '0' at the end of the string.  */    while (fracdig_no > fracdig_min && *(wcp - 1) == L'0')      {	--wcp;	--fracdig_no;      }    /* If we eliminate all fractional digits we perhaps also can remove       the radix character.  */    if (fracdig_no == 0 && !info->alt && *(wcp - 1) == decimalwc)      --wcp;    if (grouping)      /* Add in separator characters, overwriting the same buffer.  */      wcp = group_number (wstartp, wcp, intdig_no, grouping, thousands_sepwc,			  ngroups);    /* Write the exponent if it is needed.  */    if (type != 'f')      {	*wcp++ = (wchar_t) type;	*wcp++ = expsign ? L'-' : L'+';	/* Find the magnitude of the exponent.	*/	expscale = 10;	while (expscale <= exponent)	  expscale *= 10;	if (exponent < 10)	  /* Exponent always has at least two digits.  */	  *wcp++ = L'0';	else	  do	    {	      expscale /= 10;	      *wcp++ = L'0' + (exponent / expscale);	      exponent %= expscale;	    }	  while (expscale > 10);	*wcp++ = L'0' + exponent;      }    /* Compute number of characters which must be filled with the padding       character.  */    if (is_neg || info->showsign || info->space)      --width;    width -= wcp - wstartp;    if (!info->left && info->pad != '0' && width > 0)      PADN (info->pad, width);    if (is_neg)      outchar ('-');    else if (info->showsign)      outchar ('+');    else if (info->space)      outchar (' ');    if (!info->left && info->pad == '0' && width > 0)      PADN ('0', width);    {      char *buffer = NULL;      char *cp = NULL;      char *tmpptr;      if (! wide)	{	  /* Create the single byte string.  */	  size_t decimal_len;	  size_t thousands_sep_len;	  wchar_t *copywc;	  decimal_len = strlen (decimal);	  if (thousands_sep == NULL)	    thousands_sep_len = 0;	  else	    thousands_sep_len = strlen (thousands_sep);	  if (buffer_malloced)	    {	      buffer = (char *) malloc (2 + chars_needed + decimal_len					+ ngroups * thousands_sep_len);	      if (buffer == NULL)		/* Signal an error to the caller.  */		return -1;	    }	  else	    buffer = (char *) alloca (2 + chars_needed + decimal_len				      + ngroups * thousands_sep_len);	  /* Now copy the wide character string.  Since the character	     (except for the decimal point and thousands separator) must	     be coming from the ASCII range we can esily convert the	     string without mapping tables.  */	  for (cp = buffer, copywc = wstartp; copywc < wcp; ++copywc)	    if (*copywc == decimalwc)	      cp = (char *) __mempcpy (cp, decimal, decimal_len);	    else if (*copywc == thousands_sepwc)	      cp = (char *) __mempcpy (cp, thousands_sep, thousands_sep_len);	    else	      *cp++ = (char) *copywc;	}      tmpptr = buffer;      if (__builtin_expect (info->i18n, 0))        {#ifdef COMPILE_WPRINTF	  wstartp = _i18n_number_rewrite (wstartp, wcp);#else	  tmpptr = _i18n_number_rewrite (tmpptr, cp);#endif        }      PRINT (tmpptr, wstartp, wide ? wcp - wstartp : cp - tmpptr);      /* Free the memory if necessary.  */      if (buffer_malloced)	{	  free (buffer);	  free (wbuffer);	}    }    if (info->left && width > 0)      PADN (info->pad, width);  }  return done;}libc_hidden_def (__printf_fp)/* Return the number of extra grouping characters that will be inserted   into a number with INTDIG_MAX integer digits.  */unsigned int__guess_grouping (unsigned int intdig_max, const char *grouping){  unsigned int groups;  /* We treat all negative values like CHAR_MAX.  */  if (*grouping == CHAR_MAX || *grouping <= 0)    /* No grouping should be done.  */    return 0;  groups = 0;  while (intdig_max > (unsigned int) *grouping)    {      ++groups;      intdig_max -= *grouping++;      if (*grouping == CHAR_MAX#if CHAR_MIN < 0	  || *grouping < 0#endif	  )	/* No more grouping should be done.  */	break;      else if (*grouping == 0)	{	  /* Same grouping repeats.  */	  groups += (intdig_max - 1) / grouping[-1];	  break;	}    }  return groups;}/* Group the INTDIG_NO integer digits of the number in [BUF,BUFEND).   There is guaranteed enough space past BUFEND to extend it.   Return the new end of buffer.  */static wchar_t *internal_functiongroup_number (wchar_t *buf, wchar_t *bufend, unsigned int intdig_no,	      const char *grouping, wchar_t thousands_sep, int ngroups){  wchar_t *p;  if (ngroups == 0)    return bufend;  /* Move the fractional part down.  */  __wmemmove (buf + intdig_no + ngroups, buf + intdig_no,	      bufend - (buf + intdig_no));  p = buf + intdig_no + ngroups - 1;  do    {      unsigned int len = *grouping++;      do	*p-- = buf[--intdig_no];      while (--len > 0);      *p-- = thousands_sep;      if (*grouping == CHAR_MAX#if CHAR_MIN < 0	  || *grouping < 0#endif	  )	/* No more grouping should be done.  */	break;      else if (*grouping == 0)	/* Same grouping repeats.  */	--grouping;    } while (intdig_no > (unsigned int) *grouping);  /* Copy the remaining ungrouped digits.  */  do    *p-- = buf[--intdig_no];  while (p > buf);  return bufend + ngroups;}

⌨️ 快捷键说明

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