How to print an array of char backward.

H

hank

I have this code here, it converts decimal numbers to binary. There is
one problem. The output is printed 'in reverse' and I have no clue at all
how to solve this problem.

Output of program:

Decimal number: 10
Binary representation: 0101
(It should be 1010, and not 0101...)

I would be glad if someone could help me. Maybe there is some function,
which does the trick... (I have no idea.)

Thanks.

/**********************************************************************/
#include <stdio.h>
#include <string.h>

int main()
{
char bin[25] = "";
int dec;

printf("Decimal number: ");
scanf("%d", &dec);

do {
if (dec % 2 == 0)
strcat(bin, "0");
else {
strcat(bin, "1");
dec--;
}
dec = dec / 2;
} while (dec > 0);
printf("Binary representation: %s\n", bin);

return 0;
}
/**********************************************************************/
 
S

santosh

hank said:
I have this code here, it converts decimal numbers to binary. There is
one problem. The output is printed 'in reverse' and I have no clue at
all how to solve this problem.

Output of program:

Decimal number: 10
Binary representation: 0101
(It should be 1010, and not 0101...)

I would be glad if someone could help me. Maybe there is some
function, which does the trick... (I have no idea.)

You could reverse the string in place before printing it. There is no
standard string reverse function, but it's easy enough to write one. As
an alternative you could just iterate backwards through the string
while printing it, character by character.

<snip>
 
A

Andrew Kerr

santosh said:
You could reverse the string in place before printing it.

Or you could write it correctly.

/**********************************************************************/
#include <stdio.h>
#include <string.h>

void fprint_binary_representation(FILE *out, unsigned char byte) {
char str_rep[9] = {0};
int i;
for (i = 7; i >= 0; i--) {
str_rep[7 - i] = ((byte & (1 << i)) ? '1' : '0');
}
fprintf(out, "%s", str_rep);
}

int main() {
fprint_binary_representation(stdout, 10); // prints 00001010

return 0;
}

/**********************************************************************/
 
S

sohijb.edrisy

You could reverse the string in place before printing it. There is no
standard string reverse function, but it's easy enough to write one. As
an alternative you could just iterate backwards through the string
while printing it, character by character.

<snip>

Here's what I should do.

(Put this after the do-while{} loop)

////////////////////////////////////////////////////////////////////////
length = strlen(bin);
int i;

for (i = length - 1; i >= 0; i--)
{
printf("%c", bin);
}
///////////////////////////////////////////////////////////////////////
 
A

Andrew Kerr

Andrew said:
Or you could write it correctly.

Correctly... which is reversing the string in place before printing it.

Sorry about that comment, I'm an ass.
 
L

Lew Pitcher

In said:
You could reverse the string in place before printing it. There is no
standard string reverse function, but it's easy enough to write one. As
an alternative you could just iterate backwards through the string
while printing it, character by character.

<snip>

Here's what I should do.

(Put this after the do-while{} loop)

////////////////////////////////////////////////////////////////////////
length = strlen(bin);
int i;

for (i = length - 1; i >= 0; i--)
{
printf("%c", bin);
}
///////////////////////////////////////////////////////////////////////


How about...

void RevPrint(char *string)
{
if (*string)
{
RevPrint(string+1);
printf("%c",*string);
}
}

used as...
printf("Binary representation: "); RevPrint(bin);



--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
T

Tomás Ó hÉilidhe

  do {
    if (dec % 2 == 0)
      strcat(bin, "0");
    else {
      strcat(bin, "1");
      dec--;
    }
    dec = dec / 2;
  } while (dec > 0);


This algorithm can be written differently depending on whether you do
or do not want leading zeroes.

My major criticism of your original code is that it takes a human
approach rather than a computer approach. A computer approach would be
to use (x & 1) instead of (x % 2), and also to use shifting instead of
division by 2.

If I didn't want leading zeroes, I'd go with something like the
following:

(Disclaimer: Untested code thrown together in the last two minutes)

#define QUANTITY_VALUE_BITS(int_type) /* fancy macro */

void GetBinary(unsigned const val, char *p)
{
unsigned mask = 1u << (QUANTITY_VALUE_BITS(unsigned) - 1);

do if (val & mask) goto We_Have_Ones;
while (mask >> = 1);

/* If here is reached, there's no 1's */
p[0] = '0';
p[1] = 0;
return; /* <--- And we're gone! */

We_Have_Ones:

*p++ = '1';

while (mask >>= 1) *p++ = (val & mask ? '1' : '0');

*p = 0;
}
 
R

Richard

pete said:
I disagree.
The code as written, is easy to understand.
If he were doing decimal representation,
he would be dividing by 10 instead.

It's entirely possible and likely that a compiler
will know as much as you do about these simple micro-optimizations
and generate the same machine code for (x & 1) as it does for (x % 2).

If the code is shown to be not fast enough,
then I would investigate the changes that you suggest,
otherwise legibility is a higher priority.

If the code was being maintained by Bill possibly. But if a C programmer
does not understand something x&1 or shift right/left then they have no
business writing in C in a commercial setting.
 
B

Ben Bacarisse

Richard said:
If the code was being maintained by Bill possibly. But if a C programmer
does not understand something x&1 or shift right/left then they have no
business writing in C in a commercial setting.

But what of pete's first point? I much prefer % and / in the context
because it expresses a general algorithm. Even if asked to do just
base 2, might be tempted to write:

#define BASE 2
#define DIGITS "01"

....

while (num) {
*--p = DIGITS[num % BASE];
num /= BASE;
}

just because it is so self-documenting and obviously extensible. The
shift/mask method is entirely understandable, but it obscures (ever so
slightly) the algorithm.
 
R

Richard

Ben Bacarisse said:
Richard said:
If the code was being maintained by Bill possibly. But if a C programmer
does not understand something x&1 or shift right/left then they have no
business writing in C in a commercial setting.

But what of pete's first point? I much prefer % and / in the context
because it expresses a general algorithm. Even if asked to do just
base 2, might be tempted to write:

#define BASE 2
#define DIGITS "01"

...

while (num) {
*--p = DIGITS[num % BASE];
num /= BASE;
}

just because it is so self-documenting and obviously extensible. The
shift/mask method is entirely understandable, but it obscures (ever so
slightly) the algorithm.

I have no problem with his code, but I would suggest that (especially
the shift) the bit test and the shift are obvious to any half decent C
programmer.
 
B

Ben Bacarisse

I have no problem with his code, but I would suggest that (especially
the shift) the bit test and the shift are obvious to any half decent C
programmer.

Right and I agreed. I wondered if you had anything to add about his
first point which is not about whether anyone should or should not be
able to read the alternative.
 
R

Richard

Ben Bacarisse said:
Right and I agreed. I wondered if you had anything to add about his
first point which is not about whether anyone should or should not be
able to read the alternative.

If you are talking about the compiler part and the optimisation then
yes, of course I agree with him.

There is often a misty area with certain code constructs. I would
generally go for maintainability over obscure nano second saving
techniques. In this case however, >>1 is as clear as /2 for me.

However, I remember seeing someone (I think it was Chuck) complaining
about

while(*d++=*s++);

as being a "misuse" of the language. To me this *IS* C and if you have
any issue with it then you should not be programming in C. C is not
Pascal or Ada.

I have been involved in a lot of large projects with shifting maintainer
base. And never once have we advocated programming for the weakest
link. We program for competent C programmers not for someone with no
programming experience. A good programmer will pick up things very, very
quickly. The only real thing I always insisted on was never, ever have
conditional result blocks on the same line as the conditional as
Falconer seems to favour.

e.g

if(f){
i=f2(i);
}

is infinitely better than

if(f) i=f2(i);

I always structure code to faciliate *other people* to set inquisitive
break points. But we've all been down that alley here before and I
really don't want to hear from the usual suspects about how they once
debugged 5000000 lines by simply reading the code as if that somehow
meant a debugger was useless for all.
 
T

Tomás Ó hÉilidhe

#define BASE 2
#define DIGITS "01"


#define DIGITS "01"

#define BASE (sizeof digits - 1)

:-D

To make the trully perfect algorithm for this, you'd need to know:
1) Whether there should be trailing zeroes
2) Whether it's OK to return a pointer which is a few bytes ahead of
the supplied pointer.

For example:

(Disclaimer: Untested code thrown together in a few minutes)

#define DIGITS "0123456789abcdef"

#define BASE (sizeof digits - 1)

void Convert(unsigned const val, char *p)
{
char *q = p; /* Keep track of the first address */

/* --- First write the string backwards --- */

do *p++ = DIGITS[val % BASE];
while (val /= BASE);

*p-- = 0; /* Write the null and point p to the last char */

/* --- Now reverse the string --- */

for ( ; q > p; ++q, --p)
{
char const temp = *q;
*q = *p;
*p = temp;
}
}
 
B

Ben Bacarisse

Richard said:
If you are talking about the compiler part and the optimisation then
yes, of course I agree with him.

There is often a misty area with certain code constructs. I would
generally go for maintainability over obscure nano second saving
techniques. In this case however, >>1 is as clear as /2 for me.

That confuses meaning with intent. Understanding code happens at
multiple levels. The meaning of both may be equally clear, but one
expresses the intent more directly.

Having said that, I'd even go as far as to say that they are *not* as
quite clear as each other. You have to know more about the code to be
sure that >>1 is doing what you want than do with /2. The particular
case in question is interesting. Follow the thread up and you will
see that >>1 requires both of us to check the implementation's
documentation to know what the code would do when the input is
negative. I don't need to do that to understand the OP's code because
it used /2.

The only real thing I always insisted on was never, ever have
conditional result blocks on the same line as the conditional

I can't get worked up about layout, just as I can't get worked up
about the return type of main. Both are trivial to fix. I once
worked with an inveterate single space indenter and in the end we just
added a make target for our preferred indent settings. As his boss, I
could have insisted but then I would have risked annoying an otherwise
brilliant programmer for no good technical reason.

I
really don't want to hear from the usual suspects about how they once
debugged 5000000 lines by simply reading the code as if that somehow
meant a debugger was useless for all.

Yes, that would be an extraordinary conclusion to draw from such a
story but, as far as I can tell, the only people every to have
suggested it are people in the pro-debugger camp who want to
over-state the opposing case. Everyone who expressed the view that
they find a debugger less that essential (for things other than a
back-trace) seemed to accept that this was a personal preference.
 
R

Richard

Ben Bacarisse said:
That confuses meaning with intent. Understanding code happens at

To some. My point here is that it would not for me in the context of the
code.
multiple levels. The meaning of both may be equally clear, but one
expresses the intent more directly.

Not really. Not in the context. >>1 reads to me the same as /2. For me
that is. However I do not give bonus points to someone using >>1 for
them being "elite".
Having said that, I'd even go as far as to say that they are *not* as
quite clear as each other. You have to know more about the code to be
sure that >>1 is doing what you want than do with /2. The particular

Obviously - I assumed we had that covered.
case in question is interesting. Follow the thread up and you will
see that >>1 requires both of us to check the implementation's
documentation to know what the code would do when the input is
negative. I don't need to do that to understand the OP's code because
it used /2.

Agreed. See "context" mentioned above.
I can't get worked up about layout, just as I can't get worked up
about the return type of main. Both are trivial to fix. I once

No they are not. They are far from trivial to fix and layout and
refactoring ofetn introduce many bugs because of human error. In *my*
experience of *large* projects with *many* programmers then a consistent
layout and debugger friendly layout is a must. Fixing layout means
checking out, fixing, submitting for testing etc. Much better to get it
tight the first time.
worked with an inveterate single space indenter and in the end we just
added a make target for our preferred indent settings. As his boss, I
could have insisted but then I would have risked annoying an otherwise
brilliant programmer for no good technical reason.

I see it another way : if he is really that good then he will appreciate
the needs for a uniform code style on large projects.
Yes, that would be an extraordinary conclusion to draw from such a
story but, as far as I can tell, the only people every to have
suggested it are people in the pro-debugger camp who want to

pro-debugger? You mean anti-debugger?
over-state the opposing case. Everyone who expressed the view that
they find a debugger less that essential (for things other than a
back-trace) seemed to accept that this was a personal preference.

That is most certainly not the case. The case supported by most regs was
based on the fact that they personally rarely used a debugger. And my
opinion of this was that most were simply posing or really had no clue
how to properly use one. It is impossible for a debugger to make your
life harder. It can only help. The rest is really a natural conclusion
and follow on.
 
S

Sohijb Edrisy

I have this code here, it converts decimal numbers to binary. There is
one problem. The output is printed 'in reverse' and I have no clue at
all how to solve this problem.

Output of program:

Decimal number: 10
Binary representation: 0101
(It should be 1010, and not 0101...)

I would be glad if someone could help me. Maybe there is some function,
which does the trick... (I have no idea.)

Thanks.

/**********************************************************************/
#include <stdio.h>
#include <string.h>

int main()
{
char bin[25] = "";
int dec;

printf("Decimal number: ");
scanf("%d", &dec);

do {
if (dec % 2 == 0)
strcat(bin, "0");
else {
strcat(bin, "1");
dec--;
}
dec = dec / 2;
} while (dec > 0);
printf("Binary representation: %s\n", bin);

return 0;
}
/**********************************************************************/

After spending some hours hacking and searching the Web, I came up with
this solution. The other solutions posted here by different people are
great, but they are too difficult...

Instead of saving the numbers in an array and iterating through them
backwards, you could use recursion. Without using recursion, the algorithm
calculates the final digit first. You would have to store all the digits
somewhere before displaying them.

The following code is from 'C Primer Plus'. (Yeah, i'm a n00b...)

/*****************************************************************/
/* binary.c -- prints integer in binary form */

#include <stdio.h>

void to_binary(unsigned long n);

int main()
{
unsigned long number;
printf("Enter an integer (q to quit): \n"); while (scanf("%ul", &number)
== 1) {
printf("Binary equivalent: ");
to_binary(number);
putchar('\n');
printf("Enter an integer: ");
}

return 0;
}

/* to_binary: recursive function */
void to_binary(unsigned long n)
{
int r;

r = n % 2;
if (n >= 2)
to_binary(n / 2);
putchar('0' + r);

return;
}
/*****************************************************************/
 
T

Tomás Ó hÉilidhe

/* to_binary: recursive function */
void to_binary(unsigned long n)
{
  int r;

  r = n % 2;
  if (n >= 2)
    to_binary(n / 2);
  putchar('0' + r);

  return;
}


This is neat and all but it's HORRIBLY inefficient, both in terms of
the execution time and also the amount of stack space it eats up.
 
I

Ian Collins

CBFalconer said:
No it isn't. It is far and away the best method, assuming
sufficient stack for about 32 recursion levels.

Agreed, a good example of how recursion can lead to elegant and
expressive code.
It can be simplified to:

void to_bin(unsigned long n) {

if (n > 1) to_bin(n / 2);
putchar('0' + (n % 2);
^
)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top