views:

1967

answers:

9

Still learning C and I was wondering:

Given a number, is it possible to do something like the following?

char a = 5;
printf("binary representation of a = %b",a);
> 101

Or would i have to write my own method to do the transformation to binary?

+2  A: 

You have to write your own transformation. Only decimal, hex and octal numbers are supported with format specifiers.

sharptooth
+12  A: 

There is no direct way (i.e. using printf or another standard library function) to print it. You will have to write your own function.

/* This code has an obvious bug and another non-obvious one :) */
void printbits(unsigned char v) {
   for (; v; v >>= 1) putchar('0' + (v & 1));
}
dirkgently
Nice bit hacks. Unreadable code FTW!
Chris Lutz
@Chris Lutz: Actually, this is as simple as they come :-)
dirkgently
@Chris Lutz: I agree with dirkgently. The function is well named, and clearly written in a linear fashion. Each statement is simple and obvious.
abelenky
Yeah, not sure I'd be inflicting this monstrosity :-) on someone "Still learning C". Still, it works.
paxdiablo
I upvoted, and actually do like the solution. I just am also a bit sarcastic sometimes. Sorry it seemed like I thought it was bad. I think it's quite readable, if you know bitwise operations. Which a lot of people unfortunately don't. (Also, the >>= and <<= operators just look a bit silly to me.)
Chris Lutz
@Pax: Do you equate terseness with monstrosity? Alas, any student of C has to live with such monstrosity, for that is the C way of life. The earlier they learn, the better it is.
dirkgently
Obvious bug - it prints bits in reverse order. Non-obvious bug - it prints nothing for v = 0.
Chris Lutz
@Chris Lutz: +2; It was the other way round for me though :)
dirkgently
unwind
The other bug is that it only prints out for a byte at a time, not for 32-bit or 64-bit values. Though, since the question was about printing a 'char', maybe that doesn't matter.
Jonathan Leffler
@Jonathan Leffler: This is by design. You may have already noted the input parameter.
dirkgently
@unwind: Which buffer size parameter are you talking about?
dirkgently
@dirk, I gather that buffer size comment was meant for my answer.
paxdiablo
@Pax: Oh, well, so I gathered :-) Just wanted a confirmation from unwind.
dirkgently
A: 

There is no direct format specifier for this in the C language. Although I wrote this quick python snippet to help you understand the process step by step to roll your own.

#!/usr/bin/python

dec = input("Enter a decimal number to convert: ")
base = 2
solution = ""

while dec >= base:
    solution = str(dec%base) + solution
    dec = dec/base
if dec > 0:
    solution = str(dec) + solution

print solution

Explained:

dec = input("Enter a decimal number to convert: ") - prompt the user for numerical input (there are multiple ways to do this in C via scanf for example)

base = 2 - specify our base is 2 (binary)

solution = "" - create an empty string in which we will concatenate our solution

while dec >= base: - while our number is bigger than the base entered

solution = str(dec%base) + solution - get the modulus of the number to the base, and add it to the beginning of our string (we must add numbers right to left using division and remainder method). the str() function converts the result of the operation to a string. You cannot concatenate integers with strings in python without a type conversion.

dec = dec/base - divide the decimal number by the base in preperation to take the next modulo

if dec > 0: solution = str(dec) + solution - if anything is left over, add it to the beginning (this will be 1, if anything)

print solution - print the final number

John T
You missed the case where the input is 0, which will print nothing in this case.
lacqui
I don't think anyone would bother putting 0 into a converter as the answer is obvious, but choose your fix of choice. An if statement at the top of the script along with a sys.exit or check the value of the solution variable at the bottom.
John T
A: 

Yes (write your own), something like the following complete function.

#include <stdio.h> /* only needed for the printf() in main(). */
#include <string.h>

/* Create a string of binary digits based on the input value.
   Input:
       val:  value to convert.
       buff: buffer to write to must be >= sz+1 chars.
       sz:   size of buffer.
   Returns address of string or NULL if not enough space provided.
*/
static char *binrep (unsigned int val, char *buff, int sz) {
    char *pbuff = buff;

    /* Must be able to store one character at least. */
    if (sz < 1) return NULL;

    /* Special case for zero to ensure some output. */
    if (val == 0) {
        *pbuff++ = '0';
        *pbuff = '\0';
        return buff;
    }

    /* Work from the end of the buffer back. */
    pbuff += sz;
    *pbuff-- = '\0';

    /* For each bit (going backwards) store character. */
    while (val != 0) {
        if (sz-- == 0) return NULL;
        *pbuff-- = ((val & 1) == 1) ? '1' : '0';

        /* Get next bit. */
        val >>= 1;
    }
    return pbuff+1;
}

Add this main to the end of it to see it in operation:

#define SZ 32
int main(int argc, char *argv[]) {
    int i;
    int n;
    char buff[SZ+1];

    /* Process all arguments, outputting their binary. */
    for (i = 1; i < argc; i++) {
        n = atoi (argv[i]);
        printf("[%3d] %9d -> %s (from '%s')\n", i, n,
            binrep(n,buff,SZ), argv[i]);
    }

    return 0;
}

Run it with "progname 0 7 12 52 123" to get:

[  1]         0 -> 0 (from '0')
[  2]         7 -> 111 (from '7')
[  3]        12 -> 1100 (from '12')
[  4]        52 -> 110100 (from '52')
[  5]       123 -> 1111011 (from '123')
paxdiablo
I see a buffer underflow if the binrep() function is not given enough space for the value it is printing. And, speaking from bitter (but long ago) experience, stuff writing off the front of an array can be really nasty to debug!
Jonathan Leffler
Yes, that will be troublesome - if your ints are more than 32 bits, you have to make sure you increase SZ to suit.
paxdiablo
Fixed to prevent the buffer overflow.
paxdiablo
Quote: "buff: buffer to write to must be >= sz+1 chars." - sz is the size of the buffer, excluding the terminating null.
paxdiablo
@Pax: Oh, okay ... I'll delete my comment. I get queasy when exposed to a function taking a string size argument that is incompatible with a simple sizeof; requiring me to remember to add or subtract 1 is not cool, in my opinion.
unwind
Well, it has precedent, in fgets(), so I guess it's not a total anti-pattern.
paxdiablo
+3  A: 

Use a lookup table, like:

char *table[16] = {"0000", "0001", .... "1111"};

then print each nibble like this

printf("%s%s", table[a / 0xF], table[a % 0xF]);

Surely you can use just one table, but it will be marginally faster and too big.

qrdl
+5  A: 

Based on dirkgently's answer, but fixing his two bugs, and always printing a fixed number of digits:

void printbits(unsigned char v) {
  int i; // for C89 compatability
  for(i = 7; i >= 0; i--) putchar('0' + ((v >> i) & 1));
}
Chris Lutz
As icing on the cake you could also replace i = 7 with (sizeof(v)*8)-1
Leon Sodhi
I'd do that if I could find a way to make the function take an argument of any type, rather than just an unsigned char. I tried using a void pointer, but I'm getting errors. I'll need to look into that more sometime though.
Chris Lutz
A: 

Have a look here

Printing an unsigned integer in bits

Indeera
+1  A: 
mrwes
+3  A: 
#include<iostream>
#include<conio.h>
#include<stdlib.h>
using namespace std;
void displayBinary(int n)
{
       char bistr[1000];
       itoa(n,bistr,2);       //2 means binary u can convert n upto base 36
       printf("%s",bistr);

}

int main()
{
    int n;
    cin>>n;
    displayBinary(n);
    getch();
    return 0;
}
Nirupam