【问题标题】:Dec to bin converter function printing result out backwardsDec to bin 转换器功能打印结果向后输出
【发布时间】:2016-06-10 04:26:50
【问题描述】:

作为练习的一部分,我必须重写一个递归函数,以便新函数不是递归的。这两个函数都需要将正十进制整数输入转换为等效的二进制。

这是使用递归的代码:

void convert(int n) { //recursive
  if (n > 0) {
    convert(n/2);
    printf("%d", n%2);
  }

  return;
}

这是我的代码:

void convert(int n) { //non-recursive
  while (n > 0) {
    printf("%d", n%2);
    n/=2;
  }

  return;
}

我的代码的问题是,可以理解的是,我的二进制转换被向后打印出来。比如我输入数字8,我的函数返回0001,如果我输入2,返回01,等等

对于仅使用 stdio.h 库的快速修复有何建议?

【问题讨论】:

  • 第一个代码段没有使用递归……foo3应该是convert吗?
  • 不错的收获。我修好了。
  • 输出到数组然后打印数组。
  • 了解对于整数值(无符号)n/2n >> 1 相同,但除法的计算成本更高,模计算也是如此。

标签: c recursion converter


【解决方案1】:

这是一个非递归版本,它产生与递归版本相同的结果,并且不需要数组:

void convert(int n) {
    int     s;

    for (s = 1; n/s/2 > 0; s *= 2)
        ;

    for (; s >= 1; s /= 2) {
        printf("%d", (n/s) % 2);
    }
}

这个版本处理零和大数(但不是负数)。

【讨论】:

    【解决方案2】:

    你可以在一个循环中做到这一点:

    if(num == 0) {
        printf("0\n");  // Check for num being 0.
        return;
    }
    
    num = num < 0 ? num*-1 : num; // Make sure the number has no sign bit. 
    char first1Found = 0; // Create a check for the first 1 printed.
    for (int i = sizeof(num)*8 - 1; i >= 0 ; --i) {
        if (num & (1 << i)) { // If its a 1, print it and set the first1Found bool.
            printf("1");
            first1Found = 1;
        } else if(first1Found) { // If its a 0 only print it if its not a leading 0.
            printf("0");
        }
    }
    printf("\n");
    

    Here is a live example.

    注意:我通过假设 sizeof 返回类型中的字节来使用 8。这可能不适用于所有系统和编译器(尽管应该如此)。一种更便携的方法可能是使用@chux 建议的&lt;limits.h&gt; 中的CHAR_BIT

    【讨论】:

    • 这无法删除前导零,因此实际上不起作用。
    • 您必须将 unsigned 1u 移入符号位。
    • 不要使用printf打印单个字符putchar (num &amp; (1 &lt;&lt; i) ? '1' : '0');然后putchar ('\n');
    • 8 是假设的(一个很好的假设,但是一个假设)。可以使用CHAR_BIT 而不是8,但这是在&lt;limits.h&gt; 中,这与“仅使用stdio.h”相悖。
    • @TomKarzes 谢谢,我没想到,已解决。
    【解决方案3】:

    这是一个变体,它明确使用位掩码并将掩码的位置从上端向下移动。它的行为类似于您的递归版本,因为它不做负数或零。

    void convert(int n) {
      for(int mask = 1 << (8 * sizeof(n) - 2); mask > 0; mask >>= 1) {
        if (mask <= n) {
          putchar((n & mask) ? '1' : '0');
        }
      }
      putchar('\n');
    }
    

    【讨论】:

    • 假设 8 - 见comment
    • @chux - 谢谢。鉴于“唯一的 stdio”请求,我将保持原样。
    【解决方案4】:

    @Tom Karzes 的 C99 变体处理所有 + 和 - 值,包括 INT_MIN

    void convertm(int n) {
      if (n < 0) {
        putchar('-');
      } else {
        n = -n;
      }
    
      // Build up a negative power-of-2 that meets/exceeds `n`
      int npow2;
      for (npow2 = -1; n/2 <= npow2 ; npow2 *= 2)
        ;
    
      // For each negative power-of-2 ...
      while (npow2) {
        putchar(n / npow2 + '0');
        n %= npow2;
        npow2 /= 2;
      }
      puts("");
    }
    

    【讨论】:

      【解决方案5】:

      打印无符号值的未填充二进制表示的一种可靠方法(任何大小能够适合long unsigned)是:

      /** unpadded binary representation of 'v'. */
      void binprn (const unsigned long v)
      {
          if (!v)  { putchar ('0'); return; };
      
          size_t sz = sizeof v * CHAR_BIT;
          unsigned long rem = 0;
      
          while (sz--)
              if ((rem = v >> sz))
                  putchar ((rem & 1) ? '1' : '0');
      }
      

      CHAR_BIT(通常是8)在limits.h中提供)。您“需要”使用limits.h——这正是CHAR_BIT 通常出现的地方。您所需要的只是一个常数,您可以随意称呼它。我一般只用:

      /* CHAR_BIT */
      #ifndef CHAR_BIT
      #define CHAR_BIT  8
      #endif
      

      【讨论】:

      • 使用来自&lt;limits.h&gt;CHAR_BIT 与“仅使用stdio.h 库”背道而驰。
      • 读起来太直白了。我只是指出了它的提供位置,但没有说您需要包含limits.h。你所需要的只是常数。 (任何命名常量设置每字节位数都可以)。
      猜你喜欢
      • 2021-02-09
      • 2023-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-24
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多