Can putchar() print an integer?

17.2k Views Asked by At

How can I print an integer with the help of putchar() only. i want to do it without using external storage.
This question was asked in an interview last year.

5

There are 5 best solutions below

2
On

When faced with vague requirements on an interview, it's a good idea to express your assumptions.

I would take the requirement about only being able to use putchar to mean that it is the only library function I am allowed to call. I would furthermore assume that "no external storage" meant that I could not explicitly create a buffer. If the interviewer agreed with my assumptions, I would proceed with:

void pr_int(int n) {
    if (n < 0) {
        putchar('-');
        n = -n;
    }
    if (n / 10 != 0)
        pr_int(n / 10);
    putchar((n % 10) + '0');
}

If the interviewer then commented that n = -n; would fail for INT_MIN, as noted below, then I would rewrite it as:

void pr_uint(unsigned int n) {
    if (n / 10 != 0)
        pr_uint(n / 10);
    putchar((n % 10) + '0');
}

void pr_int(int n) {
    if (n < 0) {
        putchar('-');
        n = -n;
    }
    pr_uint((unsigned int) n);
}
0
On

There was already a question similar to this, there I answered this.

It should be easy enough to convert this to a program using putchar only (for example, do something like this:

while(buf[i])
    putc(buf[i++]);

putc('\n');
0
On

I've just assembled something scary. It's mostly proof-of-concept, it is really scary, works for positive integers only but doesn't use almost no storage. Ah, and the integer can't be too big too, and it can be buggy.

#include <stdio.h>
#include <assert.h>

int main()
{
    const int max_precision = 100000;
    int b = 7414;
    int max = b * max_precision;

    assert(b > 0);

    while (b <= max && b >= 0)
    {
        putchar('0' + (b / max_precision) % 10);
        b *= 10;
    }

    putchar('\n');
}

max_precision sets how many digits will be printed. b stores the actual number, and max is used to terminate the loop (either that or integer overflow).

0
On

Answering this question correctly depends largely on what is meant by "external storage" and "putchar only".

void print_int_r (int x, int neg) {
    int y = x/10;
    int d = x%10;
    if (y) print_int_r(y, neg);
    putchar('0' + (neg ? -d : d));
}

void print_int (int x) {
    int neg = x < 0;
    if (neg) putchar('-');
    print_int_r(x, neg);
    putchar('\n');
}

The above implementation assumes C99 semantics, as described in C99 Section 6.5.5 p6:

When integers are divided, the result of the / operator is the algebraic quotient with any fractional part discarded. If the quotient a/b is representable, the expression (a/b)*b + a%b shall equal a.

However, the ANSI C (C 89) semantics for % is worse. ANSI C Section 3.3.5 p5 says:

If either operand is negative, whether the result of the / operator is the largest integer less than the algebraic quotient or the smallest integer greater than the algebraic quotient is implementation-defined, as is the sign of the result of the % operator.

Ferruccio's second answer is almost perfect. The problem is that the conversion is not right. The result of n = -n is undefined if the result of the operation is a value not representable by an int. So, the conversion should be done this way:

void pr_int(int n) {
    if (n < 0) {
        putchar('-');
        pr_uint(-(unsigned int)n);
    } else
        pr_uint(n);
    putchar('\n');
}

And the solution is now conforming to all ISO C standards. Details can be found here.

6
On

Consider using the itoa function (you need to import its library) and then looping through each character in the cstring it generates (use strlen to get the upper bound for this loop) then simply using putchar() on each character.