c बाइनरी प्रारूप में प्रिंट करने के लिए कोई printf कनवर्टर है?




(24)

A small utility function in C to do this while solving a bit manipulation problem. This goes over the string checking each set bit using a mask (1<

void
printStringAsBinary(char * input)
{
    char * temp = input;
    int i = 7, j =0;;
    int inputLen = strlen(input);

    /* Go over the string, check first bit..bit by bit and print 1 or 0
     **/

    for (j = 0; j < inputLen; j++) {
        printf("\n");
        while (i>=0) {
            if (*temp & (1 << i)) {
               printf("1");
            } else {
                printf("0");
            }
            i--;
        }
        temp = temp+1;
        i = 7;
        printf("\n");
    }
}

मैं printf के साथ एक हेक्स या ऑक्टल संख्या के रूप में प्रिंट कर सकते हैं। बाइनरी, या मनमाने ढंग से आधार के रूप में मुद्रित करने के लिए एक प्रारूप टैग है?

मैं जीसीसी चला रहा हूँ।

printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"

कोई मानक और पोर्टेबल तरीका नहीं।

कुछ कार्यान्वयन itoa() प्रदान करते हैं, लेकिन यह अधिकतर नहीं होने वाला है, और इसमें कुछ हद तक क्रमी इंटरफ़ेस है। लेकिन कोड लिंक के पीछे है और आपको अपने स्वयं के फॉर्मेटर को आसानी से कार्यान्वित करने देना चाहिए।


निम्नलिखित रिकर्सिव फ़ंक्शन उपयोगी हो सकता है:

void bin(int n)
{
    /* Step 1 */
    if (n > 1)
        bin(n/2);
    /* Step 2 */
    printf("%d", n % 2);
}

अपने उत्तर में @ ideasman42 के सुझाव के आधार पर, यह एक मैक्रो है जो int8 , 16 , 32 और 64 संस्करण प्रदान करता है, पुनरावृत्ति से बचने के लिए INT8 मैक्रो का पुन: उपयोग करता है।

/* --- PRINTF_BYTE_TO_BINARY macro's --- */
#define PRINTF_BINARY_SEPARATOR
#define PRINTF_BINARY_PATTERN_INT8 "%c%c%c%c%c%c%c%c"
#define PRINTF_BYTE_TO_BINARY_INT8(i)    \
    (((i) & 0x80ll) ? '1' : '0'), \
    (((i) & 0x40ll) ? '1' : '0'), \
    (((i) & 0x20ll) ? '1' : '0'), \
    (((i) & 0x10ll) ? '1' : '0'), \
    (((i) & 0x08ll) ? '1' : '0'), \
    (((i) & 0x04ll) ? '1' : '0'), \
    (((i) & 0x02ll) ? '1' : '0'), \
    (((i) & 0x01ll) ? '1' : '0')

#define PRINTF_BINARY_PATTERN_INT16 \
    PRINTF_BINARY_PATTERN_INT8               PRINTF_BINARY_SEPARATOR              PRINTF_BINARY_PATTERN_INT8
#define PRINTF_BYTE_TO_BINARY_INT16(i) \
    PRINTF_BYTE_TO_BINARY_INT8((i) >> 8),   PRINTF_BYTE_TO_BINARY_INT8(i)
#define PRINTF_BINARY_PATTERN_INT32 \
    PRINTF_BINARY_PATTERN_INT16              PRINTF_BINARY_SEPARATOR              PRINTF_BINARY_PATTERN_INT16
#define PRINTF_BYTE_TO_BINARY_INT32(i) \
    PRINTF_BYTE_TO_BINARY_INT16((i) >> 16), PRINTF_BYTE_TO_BINARY_INT16(i)
#define PRINTF_BINARY_PATTERN_INT64    \
    PRINTF_BINARY_PATTERN_INT32              PRINTF_BINARY_SEPARATOR              PRINTF_BINARY_PATTERN_INT32
#define PRINTF_BYTE_TO_BINARY_INT64(i) \
    PRINTF_BYTE_TO_BINARY_INT32((i) >> 32), PRINTF_BYTE_TO_BINARY_INT32(i)
/* --- end macros --- */

#include <stdio.h>
int main() {
    long long int flag = 1648646756487983144ll;
    printf("My Flag "
           PRINTF_BINARY_PATTERN_INT64 "\n",
           PRINTF_BYTE_TO_BINARY_INT64(flag));
    return 0;
}

यह आउटपुट:

My Flag 0001011011100001001010110111110101111000100100001111000000101000

पठनीयता के लिए आप बदल सकते हैं: #define PRINTF_BINARY_SEPARATOR को #define PRINTF_BINARY_SEPARATOR "," करें #define PRINTF_BINARY_SEPARATOR "," या #define PRINTF_BINARY_SEPARATOR " "

यह आउटपुट होगा:

My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000

या

My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000

पहले से पोस्ट किए गए उत्तरों में से कोई भी वही नहीं है जो मैं खोज रहा था, इसलिए मैंने एक लिखा। printf साथ% बी का उपयोग करना बहुत आसान है!

    /*
     * File:   main.c
     * Author: Techplex.Engineer
     *
     * Created on February 14, 2012, 9:16 PM
     */

    #include <stdio.h>
    #include <stdlib.h>
    #include <printf.h>
    #include <math.h>
    #include <string.h>


    static int printf_arginfo_M(const struct printf_info *info, size_t n, int *argtypes) {
        /* "%M" always takes one argument, a pointer to uint8_t[6]. */
        if (n > 0) {
            argtypes[0] = PA_POINTER;
        }
        return 1;
    } /* printf_arginfo_M */

    static int printf_output_M(FILE *stream, const struct printf_info *info, const void *const *args) {
        int value = 0;
        int len;

        value = *(int **) (args[0]);

        //Beginning of my code ------------------------------------------------------------
        char buffer [50] = ""; //Is this bad?
        char buffer2 [50] = ""; //Is this bad?
        int bits = info->width;
        if (bits <= 0)
            bits = 8; // Default to 8 bits

        int mask = pow(2, bits - 1);
        while (mask > 0) {
            sprintf(buffer, "%s", (((value & mask) > 0) ? "1" : "0"));
            strcat(buffer2, buffer);
            mask >>= 1;
        }
        strcat(buffer2, "\n");
        // End of my code --------------------------------------------------------------
        len = fprintf(stream, "%s", buffer2);
        return len;
    } /* printf_output_M */

    int main(int argc, char** argv) {

        register_printf_specifier('B', printf_output_M, printf_arginfo_M);

        printf("%4B\n", 65);

        return (EXIT_SUCCESS);
    }

कुछ रनटाइम "% b" का समर्थन करते हैं हालांकि यह मानक नहीं है।

एक दिलचस्प चर्चा के लिए यहां भी देखें:

http://bytes.com/forum/thread591027.html

HTH


हो सकता है कि थोड़ा सा ओटी, लेकिन अगर आपको केवल कुछ बाइनरी ऑपरेशंस को समझने या उन्हें रिट्रेस करने के लिए डीबगिंग के लिए इसकी आवश्यकता है, तो आप wcalc (एक साधारण कंसोल कैलकुलेटर) पर एक नज़र डालेंगे। -b विकल्पों के साथ आपको बाइनरी आउटपुट मिलता है।

जैसे

$ wcalc -b "(256 | 3) & 0xff"
 = 0b11

अगला आपको मेमोरी लेआउट दिखाएगा:

#include <limits>
#include <iostream>
#include <string>

using namespace std;

template<class T> string binary_text(T dec, string byte_separator = " ") {
    char* pch = (char*)&dec;
    string res;
    for (int i = 0; i < sizeof(T); i++) {
        for (int j = 1; j < 8; j++) {
            res.append(pch[i] & 1 ? "1" : "0");
            pch[i] /= 2;
        }
        res.append(byte_separator);
    }
    return res;
}

int main() {
    cout << binary_text(5) << endl;
    cout << binary_text(.1) << endl;

    return 0;
}

const char* byte_to_binary( int x )
{
    static char b[sizeof(int)*8+1] = {0};
    int y;
    long long z;
    for (z=1LL<<sizeof(int)*8-1,y=0; z>0; z>>=1,y++)
    {
        b[y] = ( ((x & z) == z) ? '1' : '0');
    }

    b[y] = 0;

    return b;
}

इस तरह बाइनरी आउटपुट करने के लिए सी मानक लाइब्रेरी में कोई स्वरूपण कार्य नहीं है। प्रिंटफ परिवार का समर्थन करने वाले सभी प्रारूप संचालन मानव पठनीय पाठ की ओर हैं।


मुझे पनीक द्वारा कोड पसंद आया, स्थिर बफर एक अच्छा विचार है। हालांकि यह विफल रहता है यदि आप एक ही printf () में एकाधिक बाइनरी प्रारूप चाहते हैं क्योंकि यह हमेशा एक ही सूचक देता है और सरणी को ओवरराइट करता है।

यहां एक सी स्टाइल ड्रॉप-इन है जो एक स्प्लिट बफर पर पॉइंटर को घुमाता है।

char *
format_binary(unsigned int x)
{
    #define MAXLEN 8 // width of output format
    #define MAXCNT 4 // count per printf statement
    static char fmtbuf[(MAXLEN+1)*MAXCNT];
    static int count = 0;
    char *b;
    count = count % MAXCNT + 1;
    b = &fmtbuf[(MAXLEN+1)*count];
    b[MAXLEN] = '\0';
    for (int z = 0; z < MAXLEN; z++) { b[MAXLEN-1-z] = ((x>>z) & 0x1) ? '1' : '0'; }
    return b;
}

यहां पनीक के समाधान की एक छोटी भिन्नता है जो 32 और 64 बिट पूर्णांक की छपाई की अनुमति देने के लिए टेम्पलेट का उपयोग करती है:

template<class T>
inline std::string format_binary(T x)
{
    char b[sizeof(T)*8+1] = {0};

    for (size_t z = 0; z < sizeof(T)*8; z++)
        b[sizeof(T)*8-1-z] = ((x>>z) & 0x1) ? '1' : '0';

    return std::string(b);
}

और इस तरह इस्तेमाल किया जा सकता है:

unsigned int value32 = 0x1e127ad;
printf( "  0x%x: %s\n", value32, format_binary(value32).c_str() );

unsigned long long value64 = 0x2e0b04ce0;
printf( "0x%llx: %s\n", value64, format_binary(value64).c_str() );

परिणाम यहां दिया गया है:

  0x1e127ad: 00000001111000010010011110101101
0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000

किसी भी डेटाटाइप के लिए बाइनरी प्रिंट करें

//assumes little endian
void printBits(size_t const size, void const * const ptr)
{
    unsigned char *b = (unsigned char*) ptr;
    unsigned char byte;
    int i, j;

    for (i=size-1;i>=0;i--)
    {
        for (j=7;j>=0;j--)
        {
            byte = (b[i] >> j) & 1;
            printf("%u", byte);
        }
    }
    puts("");
}

परीक्षा

int main(int argv, char* argc[])
{
        int i = 23;
        uint ui = UINT_MAX;
        float f = 23.45f;
        printBits(sizeof(i), &i);
        printBits(sizeof(ui), &ui);
        printBits(sizeof(f), &f);
        return 0;
}

हैकी लेकिन मेरे लिए काम करता है:

#define BYTE_TO_BINARY_PATTERN "%c%c%c%c%c%c%c%c"
#define BYTE_TO_BINARY(byte)  \
  (byte & 0x80 ? '1' : '0'), \
  (byte & 0x40 ? '1' : '0'), \
  (byte & 0x20 ? '1' : '0'), \
  (byte & 0x10 ? '1' : '0'), \
  (byte & 0x08 ? '1' : '0'), \
  (byte & 0x04 ? '1' : '0'), \
  (byte & 0x02 ? '1' : '0'), \
  (byte & 0x01 ? '1' : '0') 
printf("Leading text "BYTE_TO_BINARY_PATTERN, BYTE_TO_BINARY(byte));

बहु-बाइट प्रकार के लिए

printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n",
  BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));

दुर्भाग्यवश आपको सभी अतिरिक्त उद्धरणों की आवश्यकता है। इस दृष्टिकोण में मैक्रोज़ के दक्षता जोखिम हैं ( BYTE_TO_BINARY लिए तर्क के रूप में फ़ंक्शन को पास न करें) लेकिन यहां कुछ अन्य प्रस्तावों में स्मृति समस्याओं और BYTE_TO_BINARY एकाधिक BYTE_TO_BINARY से बचाता है।


मैं बस अपना समाधान पोस्ट करना चाहता हूं। इसका उपयोग शून्य और एक बाइट के लिए किया जाता है, लेकिन इस फ़ंक्शन को कॉल करने के लिए कुछ बार बड़े डेटा ब्लॉक के लिए उपयोग किया जा सकता है। मैं इसे 128 बिट या बड़े structs के लिए उपयोग करता हूं। आप इसे आकार में डेटा पैरामीटर और पॉइंटर के रूप में size_t का उपयोग करने के लिए संशोधित कर सकते हैं, जिससे आप प्रिंट करना चाहते हैं, इसलिए यह आकार स्वतंत्र हो सकता है। लेकिन यह मेरे लिए काम करता है जैसा कि यह है।

void print_binary(unsigned char c)
{
 unsigned char i1 = (1 << (sizeof(c)*8-1));
 for(; i1; i1 >>= 1)
      printf("%d",(c&i1)!=0);
}

void get_binary(unsigned char c, unsigned char bin[])
{
 unsigned char i1 = (1 << (sizeof(c)*8-1)), i2=0;
 for(; i1; i1>>=1, i2++)
      bin[i2] = ((c&i1)!=0);
}

Yet another approach to print in binary: Convert the integer first .

To print 6 in binary, change 6 to 110 , then print "110" .

Bypasses char buf[] issues.
printf() format specifiers, flags, & fields like "%08lu" , "%*lX" still readily usable.
Not only binary (base 2), this method expandable to other bases up to 16.
Limited to smallish integer values.

#include <stdint.h>
#include <stdio.h>
#include <inttypes.h>

unsigned long char_to_bin10(char ch) {
  unsigned char uch = ch;
  unsigned long sum = 0;
  unsigned long power = 1;
  while (uch) {
    if (uch & 1) {
      sum += power;
      }
   power *= 10;
   uch /= 2;
  }
  return sum;
}

uint64_t uint16_to_bin16(uint16_t u) {
  uint64_t sum = 0;
  uint64_t power = 1;
  while (u) {
    if (u & 1) {
      sum += power;
      }
    power *= 16;
    u /= 2;
  }
  return sum;
}

void test(void) {
  printf("%lu\n", char_to_bin10(0xF1));
  // 11110001
  printf("%" PRIX64 "\n", uint16_to_bin16(0xF731));
  // 1111011100110001
}

इस कोड को 64 बिट्स तक आपकी आवश्यकताओं को संभालना चाहिए। मैंने 2 फ़ंक्शंस पीबीएन और पीबीनफिल बनाया। दोनों एक ही काम करते हैं, लेकिन पीबीनफिल fillChar के साथ प्रमुख रिक्त स्थान में भर जाता है। परीक्षण फ़ंक्शन कुछ परीक्षण डेटा उत्पन्न करता है, फिर फ़ंक्शन का उपयोग करके इसे प्रिंट करता है।



char* pBinFill(long int x,char *so, char fillChar); // version with fill
char* pBin(long int x, char *so);                   // version without fill
#define kDisplayWidth 64

char* pBin(long int x,char *so)
{
 char s[kDisplayWidth+1];
 int  i=kDisplayWidth;
 s[i--]=0x00;   // terminate string
 do
 { // fill in array from right to left
  s[i--]=(x & 1) ? '1':'0';  // determine bit
  x>>=1;  // shift right 1 bit
 } while( x &gt 0);
 i++;   // point to last valid character
 sprintf(so,"%s",s+i); // stick it in the temp string string
 return so;
}

char* pBinFill(long int x,char *so, char fillChar)
{ // fill in array from right to left
 char s[kDisplayWidth+1];
 int  i=kDisplayWidth;
 s[i--]=0x00;   // terminate string
 do
 { // fill in array from right to left
  s[i--]=(x & 1) ? '1':'0';
  x>>=1;  // shift right 1 bit
 } while( x > 0);
 while(i>=0) s[i--]=fillChar;    // fill with fillChar 
 sprintf(so,"%s",s);
 return so;
}

void test()
{
 char so[kDisplayWidth+1]; // working buffer for pBin
 long int val=1;
 do
 {
   printf("%ld =\t\t%#lx =\t\t0b%s\n",val,val,pBinFill(val,so,'0'));
   val*=11; // generate test data
 } while (val < 100000000);
}

Output:
00000001 =  0x000001 =  0b00000000000000000000000000000001
00000011 =  0x00000b =  0b00000000000000000000000000001011
00000121 =  0x000079 =  0b00000000000000000000000001111001
00001331 =  0x000533 =  0b00000000000000000000010100110011
00014641 =  0x003931 =  0b00000000000000000011100100110001
00161051 =  0x02751b =  0b00000000000000100111010100011011
01771561 =  0x1b0829 =  0b00000000000110110000100000101001
19487171 = 0x12959c3 =  0b00000001001010010101100111000011

कम से कम महत्वपूर्ण बिट प्रिंट करें और इसे दाईं ओर बाहर स्थानांतरित करें। इसे पूर्ण करने तक शून्य पूर्ण होने के बावजूद बाइनरी प्रस्तुति शून्य हो जाती है लेकिन उलट क्रम में। रिकर्सन का उपयोग करके, ऑर्डर को आसानी से ठीक किया जा सकता है।

#include <stdio.h>

void print_binary(int number)
{
    if (number) {
        print_binary(number >> 1);
        putc((number & 1) ? '1' : '0', stdout);
    }
}

मेरे लिए, यह समस्या के सबसे साफ समाधानों में से एक है। यदि आपको 0 0b उपसर्ग और पिछला नया लाइन वर्ण पसंद है, तो मैं फ़ंक्शन को लपेटने का सुझाव देता हूं।

ऑनलाइन डेमो


आप गति 1 को बेहतर बनाने के लिए एक छोटी सी तालिका का उपयोग कर सकते हैं। एम्बेडेड दुनिया में इसी तरह की तकनीकें उपयोगी होती हैं, उदाहरण के लिए, बाइट को घुमाने के लिए:

const char *bit_rep[16] = {
    [ 0] = "0000", [ 1] = "0001", [ 2] = "0010", [ 3] = "0011",
    [ 4] = "0100", [ 5] = "0101", [ 6] = "0110", [ 7] = "0111",
    [ 8] = "1000", [ 9] = "1001", [10] = "1010", [11] = "1011",
    [12] = "1100", [13] = "1101", [14] = "1110", [15] = "1111",
};

void print_byte(uint8_t byte)
{
    printf("%s%s", bit_rep[byte >> 4], bit_rep[byte & 0x0F]);
}

1 मैं ज्यादातर एम्बेडेड अनुप्रयोगों का जिक्र कर रहा हूं जहां अनुकूलक इतने आक्रामक नहीं हैं और गति अंतर दिखाई दे रहा है।


INT8 व्हाइट के उत्तर के आधार पर, यह एक मैक्रो है जो पुनरावृत्ति से बचने के लिए INT8 मैक्रो का उपयोग करके INT8 , 16 , 32 और 64 संस्करण प्रदान करता है।

/* --- PRINTF_BYTE_TO_BINARY macro's --- */
#define PRINTF_BINARY_PATTERN_INT8 "%c%c%c%c%c%c%c%c"
#define PRINTF_BYTE_TO_BINARY_INT8(i)    \
    (((i) & 0x80ll) ? '1' : '0'), \
    (((i) & 0x40ll) ? '1' : '0'), \
    (((i) & 0x20ll) ? '1' : '0'), \
    (((i) & 0x10ll) ? '1' : '0'), \
    (((i) & 0x08ll) ? '1' : '0'), \
    (((i) & 0x04ll) ? '1' : '0'), \
    (((i) & 0x02ll) ? '1' : '0'), \
    (((i) & 0x01ll) ? '1' : '0')

#define PRINTF_BINARY_PATTERN_INT16 \
    PRINTF_BINARY_PATTERN_INT8              PRINTF_BINARY_PATTERN_INT8
#define PRINTF_BYTE_TO_BINARY_INT16(i) \
    PRINTF_BYTE_TO_BINARY_INT8((i) >> 8),   PRINTF_BYTE_TO_BINARY_INT8(i)
#define PRINTF_BINARY_PATTERN_INT32 \
    PRINTF_BINARY_PATTERN_INT16             PRINTF_BINARY_PATTERN_INT16
#define PRINTF_BYTE_TO_BINARY_INT32(i) \
    PRINTF_BYTE_TO_BINARY_INT16((i) >> 16), PRINTF_BYTE_TO_BINARY_INT16(i)
#define PRINTF_BINARY_PATTERN_INT64    \
    PRINTF_BINARY_PATTERN_INT32             PRINTF_BINARY_PATTERN_INT32
#define PRINTF_BYTE_TO_BINARY_INT64(i) \
    PRINTF_BYTE_TO_BINARY_INT32((i) >> 32), PRINTF_BYTE_TO_BINARY_INT32(i)
/* --- end macros --- */

#include <stdio.h>
int main() {
    long long int flag = 1648646756487983144ll;
    printf("My Flag "
           PRINTF_BINARY_PATTERN_INT64 "\n",
           PRINTF_BYTE_TO_BINARY_INT64(flag));
    return 0;
}

यह आउटपुट:

My Flag 0001011011100001001010110111110101111000100100001111000000101000

पठनीयता के लिए आप उदाहरण के लिए एक विभाजक जोड़ना चाहते हैं:

My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000

मेरा समाधान:

long unsigned int i;
for(i = 0u; i < sizeof(integer) * CHAR_BIT; i++) {
    if(integer & LONG_MIN)
        printf("1");
    else
        printf("0");
    integer <<= 1;
}
printf("\n");

यहां बताया गया है कि मैंने इसे बिना हस्ताक्षरित int के लिए कैसे किया

void printb(unsigned int v) {
    unsigned int i, s = 1<<((sizeof(v)<<3)-1); // s = only most significant bit at 1
    for (i = s; i; i>>=1) printf("%d", v & i || 0 );
}

/* Convert an int to it's binary representation */

char *int2bin(int num, int pad)
{
 char *str = malloc(sizeof(char) * (pad+1));
  if (str) {
   str[pad]='\0';
   while (--pad>=0) {
    str[pad] = num & 1 ? '1' : '0';
    num >>= 1;
   }
  } else {
   return "";
  }
 return str;
}

/* example usage */

printf("The number 5 in binary is %s", int2bin(5, 4));
/* "The number 5 in binary is 0101" */

यहां फ़ंक्शन का एक संस्करण दिया गया है जो तर्क के आकार / प्रकार पर पुनर्वित्त के मुद्दों या सीमाओं से ग्रस्त नहीं है:

#define FMT_BUF_SIZE (CHAR_BIT*sizeof(uintmax_t)+1)
char *binary_fmt(uintmax_t x, char buf[static FMT_BUF_SIZE])
{
    char *s = buf + FMT_BUF_SIZE;
    *--s = 0;
    if (!x) *--s = '0';
    for(; x; x/=2) *--s = '0' + x%2;
    return s;
}

ध्यान दें कि यह कोड 2 और 10 के बीच किसी भी आधार के लिए भी काम करेगा यदि आप वांछित आधार से 2 को प्रतिस्थापित करते हैं। उपयोग है:

char tmp[FMT_BUF_SIZE];
printf("%s\n", binary_fmt(x, tmp));

जहां x कोई अभिन्न अभिव्यक्ति है।





printf