By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
440,213 Members | 2,108 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 440,213 IT Pros & Developers. It's quick & easy.

prints out an unsigned long in decimal

P: n/a
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.
Nov 13 '05 #1
Share this Question
Share on Google+
18 Replies


P: n/a
Matt <jr********@hotmail.com> 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 (pa*****@cc.helsinki.fi) ---------------------------\
| 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
Nov 13 '05 #2

P: n/a
"Matt" <jr********@hotmail.com> wrote in message
news:ba**************************@posting.google.c om...
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
Nov 13 '05 #3

P: n/a
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
"Matt" <jr********@hotmail.com> wrote in message
news:ba**************************@posting.google.c om...
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 : bi****@eton.powernet.co.uk
"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
Nov 13 '05 #4

P: n/a
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:jo********@earthlink.net
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Nov 13 '05 #5

P: n/a

"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bl**********@hercules.btinternet.com...
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
"Matt" <jr********@hotmail.com> wrote in message
news:ba**************************@posting.google.c om...
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
Nov 13 '05 #6

P: n/a
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bl**********@hercules.btinternet.com...
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
> "Matt" <jr********@hotmail.com> wrote in message
> news:ba**************************@posting.google.c om...
>> 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 : bi****@eton.powernet.co.uk
"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
Nov 13 '05 #7

P: n/a
"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bl**********@sparta.btinternet.com...
| "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
| > "Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
| > news:bl**********@hercules.btinternet.com...
| >> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
| >> > "Matt" <jr********@hotmail.com> wrote in message
| >> > news:ba**************************@posting.google.c om...
| >> >> 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
Nov 13 '05 #8

P: n/a
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
Nov 13 '05 #9

P: n/a
Ivan Vecerina wrote:
A conflict with the exp() function if using <math.h> ?


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

--
pete
Nov 13 '05 #10

P: n/a
Richard Heathfield wrote:
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
"Richard Heathfield" wrote in message
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
> "Matt" <jr********@hotmail.com> 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.


How about (untested):

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 (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #11

P: n/a
In <bl**********@sparta.btinternet.com> Richard Heathfield <do******@address.co.uk.invalid> writes:
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bl**********@hercules.btinternet.com...
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

> "Matt" <jr********@hotmail.com> wrote in message
> news:ba**************************@posting.google.c om...
>> 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: Da*****@ifh.de
Nov 13 '05 #12

P: n/a
Ivan Vecerina wrote:
"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bl**********@sparta.btinternet.com...
| "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
| > "Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
| > news:bl**********@hercules.btinternet.com...
| >> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
| >> > "Matt" <jr********@hotmail.com> wrote in message
| >> > news:ba**************************@posting.google.c om...
| >> >> 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 : bi****@eton.powernet.co.uk
"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
Nov 13 '05 #13

P: n/a

"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bl**********@sparta.btinternet.com...
Ivan Vecerina wrote:
"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bl**********@sparta.btinternet.com...
| 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.
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
Nov 13 '05 #14

P: n/a
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bl**********@sparta.btinternet.com...

"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 : bi****@eton.powernet.co.uk
"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
Nov 13 '05 #15

P: n/a
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
C links at http://www.iedu.com/c

Nov 13 '05 #16

P: n/a

"Dan Pop" <Da*****@cern.ch> wrote in message
news:bl**********@sunnews.cern.ch...
In <bl**********@sparta.btinternet.com> Richard Heathfield <do******@address.co.uk.invalid> writes:
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bl**********@hercules.btinternet.com...
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

> "Matt" <jr********@hotmail.com> wrote in message
> news:ba**************************@posting.google.c om...
>> 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. Thesecond is a namespace issue.


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


Thanks Dan, Richard, and Ivan. I learned something today.
Nov 13 '05 #17

P: n/a
Da*****@cern.ch (Dan Pop) wrote in message news:<bl**********@sunnews.cern.ch>...
In <bl**********@sparta.btinternet.com> Richard Heathfield <do******@address.co.uk.invalid> writes:
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

"Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
news:bl**********@hercules.btinternet.com...
"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:

> "Matt" <jr********@hotmail.com> wrote in message
> news:ba**************************@posting.google.c om...
>> 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
Nov 13 '05 #18

P: n/a
In <63**************************@posting.google.com > ai***@acay.com.au (Peter Nilsson) writes:
Da*****@cern.ch (Dan Pop) wrote in message news:<bl**********@sunnews.cern.ch>...
In <bl**********@sparta.btinternet.com> Richard Heathfield <do******@address.co.uk.invalid> writes:
>"Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
>
>>
>> "Richard Heathfield" <do******@address.co.uk.invalid> wrote in message
>> news:bl**********@hercules.btinternet.com...
>>> "Ivan Vecerina" <ivecATmyrealboxDOTcom> wrote:
>>>
>>> > "Matt" <jr********@hotmail.com> wrote in message
>>> > news:ba**************************@posting.google.c om...
>>> >> 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: Da*****@ifh.de
Nov 13 '05 #19

This discussion thread is closed

Replies have been disabled for this discussion.