了解sprintf如何将整数转换为字符串

问题描述 投票:1回答:1

我正在学习C以及将整数转换为字符串的基本示例(您在其他语言中认为这是理所当然的)。我找到的答案是这样的:

sprintf(str, "%d", num);

但我想看看这是如何实现的。所以我查看sprintf,它带我到这里:

#define vsprintf(s, f, a) _IO_vsprintf (s, f, a)

int
__sprintf (char *s, const char *format, ...)
{
  va_list arg;
  int done;

  va_start (arg, format);
  done = vsprintf (s, format, arg);
  va_end (arg);

  return done;
}

那么我查找_IO_vsprintf,它显示:

int
__IO_vsprintf (char *string, const char *format, va_list args)
{
  _IO_strfile sf;
  int ret;

#ifdef _IO_MTSAFE_IO
  sf._sbf._f._lock = NULL;
#endif
  _IO_no_init (&sf._sbf._f, _IO_USER_LOCK, -1, NULL, NULL);
  _IO_JUMPS (&sf._sbf) = &_IO_str_jumps;
  _IO_str_init_static_internal (&sf, string, -1, string);
  ret = _IO_vfprintf (&sf._sbf._f, format, args);
  _IO_putc_unlocked ('\0', &sf._sbf._f);
  return ret;
}

这似乎围绕着_IO_vfprintf。但我无法找到code中的位置。谷歌和GitHub没有带来任何结果。想知道是否有人可以完全实现sprintf,如果没有,可以解释它是如何工作的。

我想知道如何实现itoa,因为sprintf做到了,这听起来像是一个很好的实现。

如果没有实现,我很困惑这个代码如何实际运行。

c printf
1个回答
2
投票

Looks这样的_IO_vfprintf_IO_vfprintf_internal隐藏的别名。

在为正常(非宽)字符编译文件vfprintf.c文件时,fprintf变为一个定义为_IO_vfprintf_internal的宏,来自here并且在别名here之前未定义。

所以_IO_vfprintf_internal声明开始here,其中vfprintf被声明(好吧,“在未经过处理的源文件中”,标识符vfprintf得到的永远不会被声明)。

vfprintf函数停止处理所有宽度,空格,缩小和其他格式说明符之后,它最终将跳过jump tables(这基本上是通过跳转表跳转到不同的goto标签的智能方式,其中地址通过GCC扩展labels as values获得)它将落在form_integer:标签上。从那里我们jumpnumber:。从那里我们称之为_itoa_word

现在_itoa_word显然简单易行,甚至足以在这里发布预处理函数:

char *
_itoa_word (_ITOA_WORD_TYPE value, char *buflim,
        unsigned int base, int upper_case) {
        const char *digits = (upper_case
               ? _itoa_upper_digits
               : _itoa_lower_digits);

      ...
      switch (base)
      {
      ...
      // SPECIAL (10); expands to:
      case 10:
          do
              *--buflim = digits[value % Base];
          while ((value /= Base) != 0);
          break;
      ...
      }
      ...
}

digits,如_itoa_upper_digits_itoa_lower_digits中的_itoa_word是一个简单的查找表,从字符串文字初始化的char数组,用于将小数转换为其关联的ascii表示。

outputted之后有一些代码用于处理左对齐字符串,打印前导符号字符并用空格或零填充字符串,但最后我们的字符串得到outputted(或左对齐printf("%+- 3lld %+- 4.3Lf %-+04hhd %+- 5zd", 1llu, 2.L, 3, (ssize_t)4); )。

将整数转换为字符串的示例

所以99%的工作都是为了处理所有奇怪的事情

#include <stdio.h>

char *my_itoa(char *dest, size_t destlen, int number)
{
    // we will work our way from the ending
    char *p = &dest[destlen];
    // null terminate the string
    *--p = '\0';

    while (number) {
        if (p == dest) {
            // destination buffer too small!!
            return NULL;
        }
        *--p = "0123456789"[number % 10];
        number /= 10;
    }

    return p;
}

int main()
{
    char buf[20];
    printf("%s\n", my_itoa(buf, sizeof(buf), 123));
}

它需要符合的格式说明符。转换只是一个简单的转换,使用查找字符串(处理非ASCII系统),它的工作方式是向后通过数字:

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.