# prints out an unsigned long in decimal

Discussion in 'C Programming' started by Matt, Sep 28, 2003.

1. ### MattGuest

Given only putchar (no sprintf, itoa, etc.) write a routine putlong
that prints out an unsigned long in decimal. No array allowed.

I have no idea if we can't use array to solve the problem.

Matt, Sep 28, 2003

2. ### Joona I PalasteGuest

Matt <> scribbled the following:
> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
> that prints out an unsigned long in decimal. No array allowed.

> I have no idea if we can't use array to solve the problem.

Hey come on. This problem is really quite easy. I'll leave you with a
skeleton of the solution.

void writeLong(unsigned long l) {
putchar( /* what goes here? */ );
if (l) {
writeLong( /* what goes here? */ );
}
}

I managed to solve the problem in a way similar to the above without
using arrays, or indeed other variables than l, at all. No need for
sprintf, itoa, etc either.

--
/-- Joona Palaste () ---------------------------\
| Kingpriest of "The Flying Lemon Tree" G++ FR FW+ M- #108 D+ ADA N+++|
| http://www.helsinki.fi/~palaste W++ B OP+ |
\----------------------------------------- Finland rules! ------------/
"Life without ostriches is like coffee with milk."
- Mika P. Nieminen

Joona I Palaste, Sep 28, 2003

3. ### Ivan VecerinaGuest

"Matt" <> wrote in message
news:...
> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
> that prints out an unsigned long in decimal. No array allowed.
>
> I have no idea if we can't use array to solve the problem.

One idea is to go with something like:
unsigned long exp = 10;
while(exp<val) exp*=10;
while( exp/=10 ) putchar( '0'+(val/exp)%10 );

Bug left in on purpose, and optimizations are possible.

Cheers,
Ivan
--
http://ivan.vecerina.com

Ivan Vecerina, Sep 28, 2003
4. ### Richard HeathfieldGuest

"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

> "Matt" <> wrote in message
> news:...
>> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
>> that prints out an unsigned long in decimal. No array allowed.
>>
>> I have no idea if we can't use array to solve the problem.

>
> One idea is to go with something like:
> unsigned long exp = 10;
> while(exp<val) exp*=10;
> while( exp/=10 ) putchar( '0'+(val/exp)%10 );
>
> Bug left in on purpose, and optimizations are possible.

Which bug? I count at least two.

--
Richard Heathfield :
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Richard Heathfield, Sep 28, 2003
5. ### Joe WrightGuest

Matt wrote:
>
> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
> that prints out an unsigned long in decimal. No array allowed.
>
> I have no idea if we can't use array to solve the problem.

Because it's an example program on page 64 or K&R2 which uses an array
as temporary storage. The alogrithm to convert binary to 'decimal'
generates digits, least significant first. Then the array is reversed
(another example of how to reverse a string). They don't want you to
copy the example from the book.

You can do it without an array. Think recursion. Good luck.
--
Joe Wright mailto:
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---

Joe Wright, Sep 29, 2003
6. ### Ivan VecerinaGuest

"Richard Heathfield" <> wrote in message
news:bl7m4k\$6i9\$...
> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
>
> > "Matt" <> wrote in message
> > news:...
> >> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
> >> that prints out an unsigned long in decimal. No array allowed.
> >>
> >> I have no idea if we can't use array to solve the problem.

> >
> > One idea is to go with something like:
> > unsigned long exp = 10;
> > while(exp<val) exp*=10;
> > while( exp/=10 ) putchar( '0'+(val/exp)%10 );
> >
> > Bug left in on purpose, and optimizations are possible.

>
> Which bug? I count at least two.

shush! Is a portability problem included in your count?

Regards,
Ivan
--
http://ivan.vecerina.com

Ivan Vecerina, Sep 29, 2003
7. ### Richard HeathfieldGuest

"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

>
> "Richard Heathfield" <> wrote in message
> news:bl7m4k\$6i9\$...
>> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
>>
>> > "Matt" <> wrote in message
>> > news:...
>> >> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
>> >> that prints out an unsigned long in decimal. No array allowed.
>> >>
>> >> I have no idea if we can't use array to solve the problem.
>> >
>> > One idea is to go with something like:
>> > unsigned long exp = 10;
>> > while(exp<val) exp*=10;
>> > while( exp/=10 ) putchar( '0'+(val/exp)%10 );
>> >
>> > Bug left in on purpose, and optimizations are possible.

>>
>> Which bug? I count at least two.

>
> shush! Is a portability problem included in your count?

Well, the first is that it basically gives the wrong answer sometimes. The
second is a namespace issue.

--
Richard Heathfield :
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Richard Heathfield, Sep 29, 2003
8. ### Ivan VecerinaGuest

"Richard Heathfield" <> wrote in message
news:bl8hst\$6rv\$...
| "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
| > "Richard Heathfield" <> wrote in message
| > news:bl7m4k\$6i9\$...
| >> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
| >> > "Matt" <> wrote in message
| >> > news:...
| >> >> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
| >> >> that prints out an unsigned long in decimal. No array allowed.
| >> >>
| >> >> I have no idea if we can't use array to solve the problem.
| >> >
| >> > One idea is to go with something like:
| >> > unsigned long exp = 10;
| >> > while(exp<val) exp*=10;
| >> > while( exp/=10 ) putchar( '0'+(val/exp)%10 );
| >> >
| >> > Bug left in on purpose, and optimizations are possible.
| >>
| >> Which bug? I count at least two.
| >
| > shush! Is a portability problem included in your count?

Hi Richard,

| Well, the first is that it basically gives the wrong answer sometimes.
Yes - a classic bounds problem I left for Matt to eventually find.

| The second is a namespace issue.
I am not sure what you mean by this. I assume you refer
to C name spaces, and not C++ namespace-s.
A conflict with the exp() function if using <math.h> ?

What I though of as a portability problem was the '0'+....
It could be replaced with "0123456789"[...],
or ...["0123456789"]

Also, note that the code I posted in this thread is not
a recommendation, just a hint at a possible approach.

Regards,
Ivan

--
http://ivan.vecerina.com

Ivan Vecerina, Sep 29, 2003
9. ### MartijnGuest

Ivan Vecerina wrote:
>> The second is a namespace issue.

> I am not sure what you mean by this. I assume you refer
> to C name spaces, and not C++ namespace-s.
> A conflict with the exp() function if using <math.h> ?

That, plus val not being declared...

--
Martijn
http://www.sereneconcepts.nl

Martijn, Sep 29, 2003
10. ### peteGuest

Ivan Vecerina wrote:

> A conflict with the exp() function if using <math.h> ?

How about regardless of whether or not using <math.h> ?

--
pete

pete, Sep 29, 2003
11. ### CBFalconerGuest

Richard Heathfield wrote:
> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
> > "Richard Heathfield" wrote in message
> >> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
> >> > "Matt" <> wrote in message
> >> >
> >> >> Given only putchar (no sprintf, itoa, etc.) write a routine
> >> >> putlong that prints out an unsigned long in decimal. No
> >> >> array allowed.
> >> >>
> >> >> I have no idea if we can't use array to solve the problem.
> >> >
> >> > One idea is to go with something like:
> >> > unsigned long exp = 10;
> >> > while(exp<val) exp*=10;
> >> > while( exp/=10 ) putchar( '0'+(val/exp)%10 );
> >> >
> >> > Bug left in on purpose, and optimizations are possible.
> >>
> >> Which bug? I count at least two.

> >
> > shush! Is a portability problem included in your count?

>
> Well, the first is that it basically gives the wrong answer
> sometimes. The second is a namespace issue.

unsigned long xp = 1;

while ((val / xp) >= 10) xp *= 10;
do {
putchar('0' + (val/xp) % 10);
} while (xp /= 10);

which may be easier on resources than the recursive method.

--
Chuck F () ()
Available for consulting/temporary embedded and systems.

CBFalconer, Sep 29, 2003
12. ### Dan PopGuest

In <bl8hst\$6rv\$> Richard Heathfield <> writes:

>"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
>
>>
>> "Richard Heathfield" <> wrote in message
>> news:bl7m4k\$6i9\$...
>>> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
>>>
>>> > "Matt" <> wrote in message
>>> > news:...
>>> >> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
>>> >> that prints out an unsigned long in decimal. No array allowed.
>>> >>
>>> >> I have no idea if we can't use array to solve the problem.
>>> >
>>> > One idea is to go with something like:
>>> > unsigned long exp = 10;
>>> > while(exp<val) exp*=10;
>>> > while( exp/=10 ) putchar( '0'+(val/exp)%10 );
>>> >
>>> > Bug left in on purpose, and optimizations are possible.
>>>
>>> Which bug? I count at least two.

>>
>> shush! Is a portability problem included in your count?

>
>Well, the first is that it basically gives the wrong answer sometimes. The
>second is a namespace issue.

No namespace issue, as long as exp has block scope.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email:

Dan Pop, Sep 29, 2003
13. ### Richard HeathfieldGuest

Ivan Vecerina wrote:

> "Richard Heathfield" <> wrote in message
> news:bl8hst\$6rv\$...
> | "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
> | > "Richard Heathfield" <> wrote in message
> | > news:bl7m4k\$6i9\$...
> | >> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
> | >> > "Matt" <> wrote in message
> | >> > news:...
> | >> >> Given only putchar (no sprintf, itoa, etc.) write a routine
> | >> >> putlong that prints out an unsigned long in decimal. No array
> | >> >> allowed.
> | >> >>
> | >> >> I have no idea if we can't use array to solve the problem.
> | >> >
> | >> > One idea is to go with something like:
> | >> > unsigned long exp = 10;
> | >> > while(exp<val) exp*=10;
> | >> > while( exp/=10 ) putchar( '0'+(val/exp)%10 );
> | >> >
> | >> > Bug left in on purpose, and optimizations are possible.
> | >>
> | >> Which bug? I count at least two.
> | >
> | > shush! Is a portability problem included in your count?
>
> Hi Richard,
>
> | Well, the first is that it basically gives the wrong answer sometimes.
> Yes - a classic bounds problem I left for Matt to eventually find.
>
> | The second is a namespace issue.
> I am not sure what you mean by this. I assume you refer
> to C name spaces, and not C++ namespace-s.
> A conflict with the exp() function if using <math.h> ?

Well, that's what I had in mind, yes, but see Dan Pop's rebuttal elsethread.

> What I though of as a portability problem was the '0'+....

No, that bit's fine, because '0' + (0 through 9) is guaranteed to give you
'0' through '9'. The Standard says:

"In both the source and execution basic character sets, the value of each
character after 0 in the above list of decimal digits shall be one greater
than the value of the previous."

--
Richard Heathfield :
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Richard Heathfield, Sep 29, 2003
14. ### Ivan VecerinaGuest

"Richard Heathfield" <> wrote in message
news:bla0q3\$1sk\$...
> Ivan Vecerina wrote:
> > "Richard Heathfield" <> wrote in message
> > news:bl8hst\$6rv\$...
> > | The second is a namespace issue.
> > I am not sure what you mean by this. I assume you refer
> > to C name spaces, and not C++ namespace-s.
> > A conflict with the exp() function if using <math.h> ?

>
> Well, that's what I had in mind, yes, but see Dan Pop's rebuttal

Yes, the name of a global function should not interfere with a local
variable. (yes, for those who doubted of it, the 3 code lines are
intended to be within the body of a function...).

But things get nastier with the C99 standard: the standard <tgmath.h>
header is intended to define a bunch of macros providing type-generic
math functions -- kind of like C++ function overloads -- including
an exp() macro.

This said, if exp is a function-like macro (and it shall be IIUC),
the code will still be ok even after the inclusion of <tgmath.h>:
function-like macros are only substituted when they are
followed by a '(' (std 6.10.3/10).

Anyway, this goes beyond the scope of my initial post...

> > What I though of as a portability problem was the '0'+....

>
> No, that bit's fine, because '0' + (0 through 9) is guaranteed to give you
> '0' through '9'. The Standard says:
>
> "In both the source and execution basic character sets, the value of each
> character after 0 in the above list of decimal digits shall be one greater
> than the value of the previous."

5.2.1/3 in C99.
Thank you, it is good to see this formally confirmed.
So this isn't like the latin alphabet characters, which can
be non-contiguous in non-ASCII encodings, e.g. EBDIC.

Kind regards,
Ivan
--
http://ivan.vecerina.com

Ivan Vecerina, Sep 30, 2003
15. ### Richard HeathfieldGuest

"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

>
> "Richard Heathfield" <> wrote in message
> news:bla0q3\$1sk\$...
>>
>> "In both the source and execution basic character sets, the value of each
>> character after 0 in the above list of decimal digits shall be one
>> greater than the value of the previous."

> 5.2.1/3 in C99.
> Thank you, it is good to see this formally confirmed.
> So this isn't like the latin alphabet characters, which can
> be non-contiguous in non-ASCII encodings, e.g. EBDIC.

Correct. The alphabet is a horse of a different kettle (or possibly a fish
of a different colour), and you need to go the extra mile if you need
portability. But you're fine with digits.

--
Richard Heathfield :
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton

Richard Heathfield, Sep 30, 2003
16. ### Morris DoveyGuest

Matt wrote:

> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
> that prints out an unsigned long in decimal. No array allowed.
>
> I have no idea if we can't use array to solve the problem.

Matt...

You might try something like:

#include <stdio.h>

void putlong(unsigned long x)
{ if (x > 10) putlong(x / 10);
putchar(x % 10 + '0');
}

HTH
--
Morris Dovey
West Des Moines, Iowa USA

Morris Dovey, Sep 30, 2003
17. ### BruceSGuest

"Dan Pop" <> wrote in message
news:bl9g53\$368\$...
> In <bl8hst\$6rv\$> Richard Heathfield

<> writes:
>
> >"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
> >
> >>
> >> "Richard Heathfield" <> wrote in message
> >> news:bl7m4k\$6i9\$...
> >>> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
> >>>
> >>> > "Matt" <> wrote in message
> >>> > news:...
> >>> >> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
> >>> >> that prints out an unsigned long in decimal. No array allowed.
> >>> >>
> >>> >> I have no idea if we can't use array to solve the problem.
> >>> >
> >>> > One idea is to go with something like:
> >>> > unsigned long exp = 10;
> >>> > while(exp<val) exp*=10;
> >>> > while( exp/=10 ) putchar( '0'+(val/exp)%10 );
> >>> >
> >>> > Bug left in on purpose, and optimizations are possible.
> >>>
> >>> Which bug? I count at least two.
> >>
> >> shush! Is a portability problem included in your count?

> >
> >Well, the first is that it basically gives the wrong answer sometimes.

The
> >second is a namespace issue.

>
> No namespace issue, as long as exp has block scope.

Thanks Dan, Richard, and Ivan. I learned something today.

BruceS, Oct 2, 2003
18. ### Peter NilssonGuest

(Dan Pop) wrote in message news:<bl9g53\$368\$>...
> In <bl8hst\$6rv\$> Richard Heathfield <> writes:
>
> >"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
> >
> >>
> >> "Richard Heathfield" <> wrote in message
> >> news:bl7m4k\$6i9\$...
> >>> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
> >>>
> >>> > "Matt" <> wrote in message
> >>> > news:...
> >>> >> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
> >>> >> that prints out an unsigned long in decimal. No array allowed.
> >>> >>
> >>> >> I have no idea if we can't use array to solve the problem.
> >>> >
> >>> > One idea is to go with something like:
> >>> > unsigned long exp = 10;
> >>> > while(exp<val) exp*=10;
> >>> > while( exp/=10 ) putchar( '0'+(val/exp)%10 );
> >>> >
> >>> > Bug left in on purpose, and optimizations are possible.
> >>>
> >>> Which bug? I count at least two.
> >>
> >> shush! Is a portability problem included in your count?

> >
> >Well, the first is that it basically gives the wrong answer sometimes. The
> >second is a namespace issue.

>
> No namespace issue, as long as exp has block scope.

But there is a conflict if <math.h> is included...

7.1.3p5:
... If the program declares or defines an identifier in a context in
which it is reserved (other than as allowed by 7.1.4), or defines a
reserved identifier as a macro name, the behavior is undefined.

--
Peter

Peter Nilsson, Oct 2, 2003
19. ### Dan PopGuest

In <> (Peter Nilsson) writes:

> (Dan Pop) wrote in message news:<bl9g53\$368\$>...
>> In <bl8hst\$6rv\$> Richard Heathfield <> writes:
>>
>> >"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
>> >
>> >>
>> >> "Richard Heathfield" <> wrote in message
>> >> news:bl7m4k\$6i9\$...
>> >>> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
>> >>>
>> >>> > "Matt" <> wrote in message
>> >>> > news:...
>> >>> >> Given only putchar (no sprintf, itoa, etc.) write a routine putlong
>> >>> >> that prints out an unsigned long in decimal. No array allowed.
>> >>> >>
>> >>> >> I have no idea if we can't use array to solve the problem.
>> >>> >
>> >>> > One idea is to go with something like:
>> >>> > unsigned long exp = 10;
>> >>> > while(exp<val) exp*=10;
>> >>> > while( exp/=10 ) putchar( '0'+(val/exp)%10 );
>> >>> >
>> >>> > Bug left in on purpose, and optimizations are possible.
>> >>>
>> >>> Which bug? I count at least two.
>> >>
>> >> shush! Is a portability problem included in your count?
>> >
>> >Well, the first is that it basically gives the wrong answer sometimes. The
>> >second is a namespace issue.

>>
>> No namespace issue, as long as exp has block scope.

>
>But there is a conflict if <math.h> is included...
>
> 7.1.3p5:
> ... If the program declares or defines an identifier in a context in
> which it is reserved (other than as allowed by 7.1.4), or defines a
> reserved identifier as a macro name, the behavior is undefined.

Could you, please, point out where the conflict is? After including
<math.h>, exp is NOT a reserved identifier if defined with block scope.

And if <math.h> defines an exp macro, it has to be a function-like macro,
therefore there is still no conflict with

unsigned long exp = 10;

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email:

Dan Pop, Oct 6, 2003