【问题标题】:Print integer as character digits (no arrays/printf/etc...)将整数打印为字符数字(无数组/printf/等...)
【发布时间】:2014-01-30 03:39:20
【问题描述】:

我正在尝试将整数打印到 C 中的控制台,但有一些限制,其中最重要的是我只能将单个字符写入控制台,如下所示:

void my_char(char ch)
}
    write(1, &ch, 1);
}

其他约束包括没有预定义的方法(printf、log 等)。没有递归。最后,我可能不会创建数组。

到目前为止,我已经想出了一种方法,可以很好地打印出数字……向后。

int main()
{
    int i = -345320;
    my_int(i);
    return 0;
}

void my_int(int x)
{
    char *a;
    int n;

    if(x < 0)
    {
            x = x * -1;
            my_char('-');
    }

    while(x)
    {
            n = x % 10;
            a = (char*)&n;
            my_char(*a + 48);
            x /= 10;
    }
}

还有其他好的方法可以解决这个问题,还是我至少朝着正确的方向前进?理想情况下,我想扩展它以在我提供的任何基数中打印一个整数,但我需要从这里开始。

我正在玩在整数的每个字节上迭代一个指针,但我无法理解如何使用这些字符值来重新创建整数。

感谢任何建议。我宁愿获得一些见解,而不仅仅是代码解决方案。我也希望能提供更精简的意见。

【问题讨论】:

  • 尝试递归,并在递归步骤之后打印数字。
  • 我的错;我也在避免递归。更新以提及这一点。
  • 为了让它更精简,你可以去掉 n 和 a,只在 while 循环中使用这一行 my_char(x % 10 + '0');
  • 您的代码不仅向后打印数字,而且不适用于 0 或 INT_MIN。 (在二进制补码机器上没有 INT_MIN 的正数版本。)
  • 这是一个想法。尝试使用以十亿开头的变量(假设为 32 位整数)。用它来挑选从最重要的数字开始。

标签: c integer character


【解决方案1】:

这是一个遵循您的约束的通用(丑陋!)解决方案。它使用了我在上面的评论中给出的想法。它假定为 32 位整数。

void my_int(int x) {
    int n = 1000000000;
    if (x == 0) {
        my_char('0');
        return;
    }
    if (x == INT_MIN) { // INT_MIN is in limits.h
        my_char('-'); my_char('2'); my_char('1');
        my_char('4'); my_char('7'); my_char('4');
        my_char('8'); my_char('3'); my_char('6');
        my_char('4'); my_char('8');
        return;
    }
    if (x < 0) {
        x *= -1;
        my_char('-');
    }
    while (n > x) n /= 10;
    while (n != 0) {
        my_char(x / n % 10 + '0');
        n /= 10;
    }
}

【讨论】:

  • 这实际上似乎是一个相对稳健的解决方案。需要对其进行修改以打印尾随/内部 0(易于修改),但它看起来是一种合理的方法。
  • INT_MIN 检查很好。
  • 固定尾随零。
【解决方案2】:

这应该可以解决问题。它向前打印整数。:

void my_int(int x)
{
    int temp = 0;
    int divFactor = 10;

    if(x==0)
    {
        my_char('0');
        return;
    }

    if(x < 0)
    {
            x = x * -1;
            my_char('-');
    }
    temp = x;
    while((temp /= 10) > 10) {divFactor *= 10;}

    for(;divFactor > 0;divFactor /= 10)
    {
        temp = x;
        temp /= divFactor;
        my_char(temp + '0');
        x -= divFactor * temp;
    }
    printf("\n done!");
}


int main()
{
    int i = -1234001;
    my_int(i);
    return 0;
}

【讨论】:

  • 我建议休息而不是标志。
  • 你在这两个方面都是对的。我修复了12345 并将我的标志更改为中断。
  • 我敢打赌,你可以在另一个循环之外移动那个内部。计算一次该数字,然后在主循环的每次迭代中将其除以 10。你也可以去掉 a 和 n 并使用 '0' 而不是 48。
  • +1,但是你应该去掉 a 和 n,因为你没有使用它们。使用 '0' 而不是 48 被认为是更好的样式。更易于阅读且更便携。
  • 再次正确。编辑#4。我还修复了尾随零并使其更清晰。
【解决方案3】:
void my_int(int x)
{
    int n;
    int copy;
    char digit;

    // handle 0
    if (!x)
    {
        my_char('0');
        return;
    }       

    // emit sign
    if(x < 0)
    {
        x = x * -1;
        my_char('-');
    }

    // count base-10 digits in x, store 10^n in n
    n = 1;
    copy = x/10;  // shorten loop by 1 iteration
    while (copy)
    {
        n *= 10;
        copy /= 10;
    }

    // 'n' is now a digit selector
    while (n)
    {
        digit = x/n;
        my_char(digit + '0'); // print the most significant digit
        x -= digit*n;  // remove the most significant digit from x
        n /= 10;
    }
}

【讨论】:

  • 看起来@ooga 在我发布答案前不久将这个想法表达为评论。请注意,我将“n”的类型更改为“char”(尽管正如 ooga 指出的那样,您可以完全不使用它。)
  • 仍然向后打印数字。 :(
  • 当然有助于清洁,所以谢谢!我仍然坚持一个实际的解决方案。恐怕不会有分段字节的方法,但我还在琢磨。
  • 好的,我修改了我的答案以考虑向后打印。我手边没有编译器,所以没有测试。
  • 刚刚将 'n' 改为 int 而不是 char。
猜你喜欢
  • 2018-02-17
  • 2016-02-11
  • 1970-01-01
  • 2012-06-12
  • 1970-01-01
  • 2013-06-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多