it-swarm-eu.dev

Existuje tiskový konvertor pro tisk v binárním formátu?

Můžu tisknout s printf jako hexadecimální nebo osmičkové číslo. Existuje formátovací značka pro tisk jako binární nebo libovolná báze? 

Používám gcc.

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

Hacky ale pracuje pro mě:

#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));

Pro vícebajtové typy 

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

Bohužel potřebujete všechny extra citace. Tento přístup má rizika účinnosti makra (nepředávají funkci jako argument BYTE_TO_BINARY), ale vyhýbají se problémům s pamětí a vícenásobným vyvoláváním strcat v některých dalších návrzích zde.

225
William Whyte

Vytisknout binární soubor pro libovolný datový typ

//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("");
}

test

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;
}
190
user295190

Zde je rychlý hack ukázat techniky dělat to, co chcete. 

#include <stdio.h>      /* printf */
#include <string.h>     /* strcat */
#include <stdlib.h>     /* strtol */

const char *byte_to_binary(int x)
{
    static char b[9];
    b[0] = '\0';

    int z;
    for (z = 128; z > 0; z >>= 1)
    {
        strcat(b, ((x & z) == z) ? "1" : "0");
    }

    return b;
}

int main(void)
{
    {
        /* binary string to int */

        char *tmp;
        char *b = "0101";

        printf("%d\n", strtol(b, &tmp, 2));
    }

    {
        /* byte to binary string */

        printf("%s\n", byte_to_binary(5));
    }

    return 0;
}
149
EvilTeach

Binární konverzní specifikátor není v glibc normálně.

Do rodiny funkcí printf () v glibc je možné přidat vlastní typy konverzí. Podrobnosti viz register_printf_function . Vlastní konverzi% b můžete přidat pro vlastní použití, pokud to zjednoduší kód aplikace, aby byl k dispozici.

Zde je příklad jak implementovat vlastní formáty printf v glibc.

77
DGentry

Ke zlepšení rychlosti můžete použít malý stolek1. Podobné techniky jsou užitečné ve vloženém světě, například k převrácení byte:

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 Většinou odkazuji na vestavěné aplikace, kde optimalizátory nejsou tak agresivní a rozdíl rychlosti je viditelný.

30
Shahbaz

Na základě odpovědi společnosti @William Whyte se jedná o makro, které poskytuje int8, 16, 32 & 64 verze, které znovu používají makro INT8, aby se zabránilo opakování.

/* --- 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;
}

Tyto výstupy:

My Flag 0001011011100001001010110111110101111000100100001111000000101000

Pro lepší čitelnost můžete přidat oddělovač např. Pro:

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

Zde je verze funkce, která netrpí problémy s reentrancy nebo omezením velikosti/typu argumentu:

#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;
}

Všimněte si, že tento kód by fungoval stejně dobře pro každou základnu mezi 2 a 10, pokud právě nahradíte 2 na požadovanou základnu. Použití je:

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

Kde x je libovolný integrální výraz.

16
R..

Vytiskněte nejméně významný bit a posuňte jej doprava. Tímto způsobem, dokud se celé číslo stane nulou, vytisknete binární reprezentaci bez úvodních nul, ale v obráceném pořadí. Pomocí rekurze lze příkaz snadno opravit.

#include <stdio.h>

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

Pro mě je to jedno z nejčistších řešení problému. Pokud se vám líbí 0b prefix a znak koncové nové řádky, navrhuji zabalení funkce.

Online demo

14
danijar
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;
}
11
works better

Některé runtime podporují "% b", i když to není standard.

Také zde naleznete zajímavou diskusi:

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

HTH

8
rlerallut

Žádná z dříve zaslaných odpovědí není přesně to, co jsem hledal, tak jsem napsal jeden. Je super snadné použít% B s 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);
    }
8
TechplexEngineer

Tento kód by měl vyhovovat vašim potřebám až 64 bitů. Vytvořil jsem 2 funkce pBin & pBinFill. Obě dělají totéž, ale pBinFill zaplní úvodní mezery pomocí fillChar. Testovací funkce vygeneruje některá testovací data a poté ji vytiskne pomocí funkce.



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 > 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
7
mrwes

Možná trochu OT, ale pokud to potřebujete pouze pro ladění, abyste porozuměli nebo obnovili některé binární operace, které děláte, můžete se podívat na wcalc (jednoduchá konzolová kalkulačka). S možnostmi -b získáte binární výstup.

např.

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

Existuje tiskový konvertor pro tisk v binárním formátu?

Rodina printf() je schopna tisknout pouze v základnách 8, 10 a 16 s použitím standardních specifikátorů přímo. Navrhuji vytvořit funkci, která převede číslo na konkrétní potřeby kódu.


Tisk v libovolné bázi [2-36]

Všechny ostatní odpovědi mají zatím alespoň jedno z těchto omezení.

  1. Použijte statickou paměť pro návratovou vyrovnávací paměť. To omezuje počet, kolikrát může být funkce použita jako argument printf().

  2. Přidělit paměť vyžadující volající kód k volným ukazatelům.

  3. Vyžadovat volací kód, aby explicitně poskytl vhodný buffer.

  4. Volání printf() přímo. To vyžaduje novou funkci pro fprintf(), sprintf(), vsprintf() atd.

  5. Použijte snížené celé číslo.

Následující má žádné z výše uvedených omezení. Vyžaduje C99 nebo novější a použití "%s". Používá sloučenina literál pro poskytnutí vyrovnávací paměti. Nemá žádné problémy s více hovory v printf().

#include <assert.h>
#include <limits.h>
#define TO_BASE_N (sizeof(unsigned)*CHAR_BIT + 1)

//                               v. compound literal .v
#define TO_BASE(x, b) my_to_base((char [TO_BASE_N]){""}, (x), (b))

// Tailor the details of the conversion function as needed
// This one does not display unneeded leading zeros
// Use return value, not `buf`
char *my_to_base(char *buf, unsigned i, int base) {
  assert(base >= 2 && base <= 36);
  char *s = &buf[TO_BASE_N - 1];
  *s = '\0';
  do {
    s--;
    *s = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[i % base];
    i /= base;
  } while (i);

  // Could employ memmove here to move the used buffer to the beginning

  return s;
}

#include <stdio.h>
int main(void) {
  int ip1 = 0x01020304;
  int ip2 = 0x05060708;
  printf("%s %s\n", TO_BASE(ip1, 16), TO_BASE(ip2, 16));
  printf("%s %s\n", TO_BASE(ip1, 2), TO_BASE(ip2, 2));
  puts(TO_BASE(ip1, 8));
  puts(TO_BASE(ip1, 36));
  return 0;
}

Výstup

1020304 5060708
1000000100000001100000100 101000001100000011100001000
100401404
A2F44
5
chux

Neexistuje žádná formátovací funkce ve standardní knihovně C pro výstup takového binárního. Všechny operace formátování, které podporuje rodina printf, směřují k čitelnému textu.

5
Florian Bösch

Následující rekurzivní funkce může být užitečná:

void bin(int n)
{
    /* Step 1 */
    if (n > 1)
        bin(n/2);
    /* Step 2 */
    printf("%d", n % 2);
}
5
kapil
void
print_binary(unsigned int n)
{
    unsigned int mask = 0;
    /* this grotesque hack creates a bit pattern 1000... */
    /* regardless of the size of an unsigned int */
    mask = ~mask ^ (~mask >> 1);

    for(; mask != 0; mask >>= 1) {
        putchar((n & mask) ? '1' : '0');
    }

}

Optimalizoval jsem špičkové řešení velikosti a C++ a dostal jsem se k tomuto řešení:

inline std::string format_binary(unsigned int x)
{
    static char b[33];
    b[32] = '\0';

    for (int z = 0; z < 32; z++) {
        b[31-z] = ((x>>z) & 0x1) ? '1' : '0';
    }

    return b;
}
4
paniq

Na základě návrhu @ ideaman42 v jeho odpovědi se jedná o makro, které poskytuje int8, 16, 32 & 64 verze, které znovu používají makro INT8, aby se zabránilo opakování.

/* --- 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;
}

Tyto výstupy:

My Flag 0001011011100001001010110111110101111000100100001111000000101000

Pro přehlednost můžete změnit: #define PRINTF_BINARY_SEPARATOR na #define PRINTF_BINARY_SEPARATOR "," nebo #define PRINTF_BINARY_SEPARATOR " "

Výsledkem bude:

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

nebo

My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000
3
Et7f3XIV

Tisk bitů z libovolného typu s použitím méně kódu a zdrojů

Tento přístup má jako atributy:

  • Pracuje s proměnnými a literály.
  • Není-li to nutné, neopakuje všechny bity.
  • Volání printf pouze při dokončení bajtu (ne zbytečně pro všechny bity).
  • Pracuje pro všechny typy.
  • Pracuje s malou a velkou endianness (používá GCC #defines pro kontrolu).
  • Používá typeof (), který není standardem C, ale je do značné míry definován.
#include <stdio.h>
#include <stdint.h>
#include <string.h>

#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define for_endian(size) for (int i = 0; i < size; ++i)
#Elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define for_endian(size) for (int i = size - 1; i >= 0; --i)
#else
#error "Endianness not detected"
#endif

#define printb(value)                                   \
({                                                      \
        typeof(value) _v = value;                       \
        __printb((typeof(_v) *) &_v, sizeof(_v));       \
})

void __printb(void *value, size_t size)
{
        uint8_t byte;
        size_t blen = sizeof(byte) * 8;
        uint8_t bits[blen + 1];

        bits[blen] = '\0';
        for_endian(size) {
                byte = ((uint8_t *) value)[i];
                memset(bits, '0', blen);
                for (int j = 0; byte && j < blen; ++j) {
                        if (byte & 0x80)
                                bits[j] = '1';
                        byte <<= 1;
                }
                printf("%s ", bits);
        }
        printf("\n");
}

int main(void)
{
        uint8_t c1 = 0xff, c2 = 0x44;
        uint8_t c3 = c1 + c2;

        printb(c1);
        printb((char) 0xff);
        printb((short) 0xff);
        printb(0xff);
        printb(c2);
        printb(0x44);
        printb(0x4411ff01);
        printb((uint16_t) c3);
        printf("\n");

        return 0;
}

Výstup

$ ./printb 
11111111 
11111111 
00000000 11111111 
00000000 00000000 00000000 11111111 
01000100 
00000000 00000000 00000000 01000100 
01000100 00010001 11111111 00000001 
00000000 01000011 

Použil jsem další přístup ( bitprint.h ) k vyplnění tabulky se všemi bajty (jako bitovými řetězci) a vytisknout je na základě vstupního/indexového bytu. Stojí to za to podívat se.

3
Geyslan G. Bem

Moje řešení:

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");
3
SarahGaidi

Žádný standardní a přenosný způsob.

Některé implementace poskytují itoa () , ale to nebude ve většině, a to má poněkud rozpadlé rozhraní. Ale kód je za odkazem a měl by vám umožnit implementaci vlastního formátovače docela snadno.

3
wnoise

Líbí se mi kód od paniq, statický buffer je dobrý nápad. Nepodaří se však, pokud chcete více binárních formátů v jediném printf (), protože vždy vrátí stejný ukazatel a přepíše pole. 

Zde je C-styl drop-in, který otáčí ukazatel na split buffer.

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;
}
3
eMPee584

Jeden příkaz obecný převod libovolného integrálního typu do binárního reprezentace řetězce pomocí knihovny standard:

#include <bitset>
MyIntegralType  num = 10;
print("%s\n",
    std::bitset<sizeof(num) * 8>(num).to_string().insert(0, "0b").c_str()
); // prints "0b1010\n"

Nebo jen:std::cout << std::bitset<sizeof(num) * 8>(num);

2
luart

Zde je návod, jak jsem to udělal pro nepodepsané 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 );
}
2
andre.barata

Malá funkce funkce v C, aby to při řešení bit manipulace problém. Toto přejde přes řetězec kontrolující každý nastavený bit pomocí masky (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");
    }
}
2
Gaurav Sinha

Další zobrazí rozložení paměti:

#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;
}
2
Yola
void print_ulong_bin(const unsigned long * const var, int bits) {
        int i;

        #if defined(__LP64__) || defined(_LP64)
                if( (bits > 64) || (bits <= 0) )
        #else
                if( (bits > 32) || (bits <= 0) )
        #endif
                return;

        for(i = 0; i < bits; i++) { 
                printf("%lu", (*var >> (bits - 1 - i)) & 0x01);
        }
}

by měla fungovat - netestovaná.

2
olli
#include <stdio.h>
#include <conio.h>

void main()
{
    clrscr();
    printf("Welcome\n\n\n");
    unsigned char x='A';
    char ch_array[8];
    for(int i=0; x!=0; i++)
    {
        ch_array[i] = x & 1;
        x = x >>1;
    }
    for(--i; i>=0; i--)
        printf("%d", ch_array[i]);

    getch();
}
2
rakesh jha

Ještě jeden způsob tisku v binárním formátu: Převést celé číslo jako první .

Chcete-li tisknout 6 v binárním souboru, změňte 6 na 110, poté vytiskněte "110".

Obchází char buf[] problémy.
printf() formát specifikátorů, příznaků a polí jako "%08lu", "%*lX" stále použitelné.
Nejen binární (základna 2), tato metoda se dá rozšířit na další báze až do 16.
Omezeno na menší hodnoty celých čísel. 

#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
}
2
chux

Zde je malá varianta řešení paniq , která používá šablony pro tisk 32 a 64 bitových celých čísel:

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);
}

Lze použít jako:

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() );

Zde je výsledek:

  0x1e127ad: 00000001111000010010011110101101
0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000
2
Leo

Chci jen poslat své řešení. Používá se k získání nuly a jednoho bajtu, ale několikanásobné volání této funkce lze použít pro větší datové bloky. Používám ho pro 128 bit nebo větší struktury. Můžete jej také upravit tak, aby používal velikost_t jako vstupní parametr a ukazatel na data, která chcete tisknout, takže může být nezávislá na velikosti. Ale funguje to pro mě tak dobře.

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);
}
2
Marko
/* 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" */
2
Ben Cordero

Existuje také myšlenka převést číslo na hexadecimální formát a pak dekódovat každou hexadecimální šifru na čtyři "bity" (ty a nuly). sprintf může pro nás provádět bitové operace:

const char* binary(int n) {
  static const char binnums[16][5] = { "0000","0001","0010","0011",
    "0100","0101","0110","0111","1000","1001","1010","1011","1100","1101","1110","1111" };
  static const char* hexnums = "0123456789abcdef";
  static char inbuffer[16], outbuffer[4*16];
  const char *i;
  sprintf(inbuffer,"%x",n); // hexadecimal n -> inbuffer
  for(i=inbuffer; *i!=0; ++i) { // for each hexadecimal cipher
    int d = strchr(hexnums,*i) - hexnums; // store its decimal value to d
    char* o = outbuffer+(i-inbuffer)*4; // shift four characters in outbuffer
    sprintf(o,"%s",binnums[d]); // place binary value of d there
  }
  return strchr(outbuffer,'1'); // omit leading zeros
}

puts(binary(42)); // outputs 101010
1
Jan Turoň

Použití:

char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);

Více viz., Viz {Jak tisknout binární číslo pomocí printf.

1
kapilddit

Možná, že někdo najde toto řešení užitečné:

void print_binary(int number, int num_digits) {
    int digit;
    for(digit = num_digits - 1; digit >= 0; digit--) {
        printf("%c", number & (1 << digit) ? '1' : '0');
    }
}
1
Kresimir
void DisplayBinary(unsigned int n)
{
    int l = sizeof(n) * 8;
    for (int i = l - 1 ; i >= 0; i--) {
        printf("%x", (n & (1 << i)) >> i);
    }
}
1
Rassoul
void DisplayBinary(int n)
{
    int arr[8];
    int top =-1;
    while (n)
    {
        if (n & 1)
            arr[++top] = 1;
        else
            arr[++top] = 0;

        n >>= 1;
    }
    for (int i = top ; i > -1;i--)
    {
        printf("%d",arr[i]);
    }
    printf("\n");
}
1
Akhil

Rychlé a snadné řešení:

void printbits(my_integer_type x)
{
    for(int i=sizeof(x)<<3; i; i--)
        putchar('0'+((x>>(i-1))&1));
}

Pracuje pro všechny velikosti a pro podepsané a nepodepsané ints. „& 1“ je potřeba ke zpracování podepsaných vstupů, protože směna může provádět prodloužení znaménka.

Existuje mnoho způsobů, jak toho dosáhnout. Tady je super jednoduchý pro tisk 32 bitů nebo n bitů z podepsaného nebo nepodepsaného 32 bitového typu (ne uvedení záporného, ​​pokud je podepsán, jen tisk skutečných bitů) a žádný návrat vozíku. Všimněte si, že i je před posunem bitů sníženo:

#define printbits_n(x,n) for (int i=n;i;i--,putchar('0'|(x>>i)&1))
#define printbits_32(x) printbits_n(x,32)

Co vrátit řetězec s bity pro uložení nebo tisk později? Buď můžete přidělit paměť a vrátit ji a uživatel ji musí uvolnit, jinak vrátíte statický řetězec, ale pokud se zavolá znovu, nebo jiným vláknem, dostane se k němu. Obě metody jsou uvedeny:

char *int_to_bitstring_alloc(int x, int count)
{
    count = count<1 ? sizeof(x)*8 : count;
    char *pstr = malloc(count+1);
    for(int i = 0; i<count; i++)
        pstr[i] = '0' | ((x>>(count-1-i))&1);
    pstr[count]=0;
    return pstr;
}

#define BITSIZEOF(x)    (sizeof(x)*8)

char *int_to_bitstring_static(int x, int count)
{
    static char bitbuf[BITSIZEOF(x)+1];
    count = (count<1 || count>BITSIZEOF(x)) ? BITSIZEOF(x) : count;
    for(int i = 0; i<count; i++)
        bitbuf[i] = '0' | ((x>>(count-1-i))&1);
    bitbuf[count]=0;
    return bitbuf;
}

Volání s:

// memory allocated string returned which needs to be freed
char *pstr = int_to_bitstring_alloc(0x97e50ae6, 17);
printf("bits = 0b%s\n", pstr);
free(pstr);

// no free needed but you need to copy the string to save it somewhere else
char *pstr2 = int_to_bitstring_static(0x97e50ae6, 17);
printf("bits = 0b%s\n", pstr2);
0
Robotbugs

I pro runtime knihovny, které podporují% b, se zdá, že je to pouze pro celočíselné hodnoty.

Pokud chcete v binárním režimu tisknout hodnoty s plovoucí desetinnou čárkou, napsal (a) jsem nějaký kód, který můžete najít na adrese http://www.exploringbinary.com/converting-floating-point-numbers-to-binary-strings-in-c/ .

0
Rick Regan

Zde je velmi jednoduchý:

int print_char_to_binary(char ch)
{
    int i;
    for (i=7; i>=0; i--)
        printf("%hd ", ((ch & (1<<i))>>i));
    printf("\n");
    return 0;
}
0
hiteshradia

Existuje tiskový konvertor pro tisk v binárním formátu?

Pro dosažení "binárního" výstupu neexistuje žádný standardní formát formátu printf. Tady je alternativa, kterou jsem vymyslel, když jsem ji potřeboval.

Důl pracuje pro všechny základny od 2 do 36. Fanoušci číslic ven do volající rámce rekurzivní vyvolání, dokud nedosáhne číslice menší než základny. Pak se „protáhne“ dozadu, naplní vyrovnávací paměť dopředu a vrátí se. Vrácená hodnota je použitá velikost nebo -1, pokud vyrovnávací paměť není dostatečně velká na to, aby držela řetězec.

int conv_rad (int num, int rad, char *s, int n) {
    char *vec = "0123456789" "ABCDEFGHIJKLM" "NOPQRSTUVWXYZ";
    int off;
    if (n == 0) return 0;
    if (num < rad) { *s = vec[num]; return 1; }
    off = conv_rad(num/rad, rad, s, n);
    if ((off == n) || (off == -1)) return -1;
    s[off] = vec[num%rad];
    return off+1;
}

Jedna velká námitka: Tato funkce byla navržena pro použití s ​​řetězci "Pascal", které nesou jejich délku. V důsledku toho conv_rad, jak je psáno, nul-ukončí buffer. Pro obecnější použití C to bude pravděpodobně potřebovat jednoduchý wrapper k nul-terminate. Nebo pro tisk stačí změnit přiřazení na putchar()s.

0
luser droog
void binario(int num) {
  for(int i=0;i<32;i++){
    (num&(1<i))? printf("1"):
        printf("0");
  }  
  printf("\n");
}
0
GutiMac

Následující funkce vrací binární reprezentaci daného celého čísla bez znaménka pomocí aritmetiky ukazatele bez úvodních nul: 

const char* toBinaryString(unsigned long num)
{
    static char buffer[CHAR_BIT*sizeof(num)+1];
    char* pBuffer = &buffer[sizeof(buffer)-1];

    do *--pBuffer = '0' + (num & 1);
    while (num >>= 1);
    return pBuffer;
}

Všimněte si, že není nutné explicity nastavit NUL terminátor, protože buffer repesuje objekt s statickým trváním úložiště , který je již naplněn nulami.

To může být snadno přizpůsobeno unsigned long long (nebo jinému nenaplněnému celému číslu) jednoduše změnou typu num formálního parametru.

CHAR_BIT vyžaduje zahrnutí <limits.h>.

Zde je příklad použití:

int main(void)
{
    printf(">>>%20s<<<\n", toBinaryString(1));
    printf(">>>%-20s<<<\n", toBinaryString(254));
    return 0;
}

s požadovaným výstupem jako:

>>>                   1<<<
>>>11111110            <<<
void PrintBinary( int Value, int Places, char* TargetString)
{
    int Mask;

    Mask = 1 << Places;

    while( Places--) {
        Mask >>= 1; /* Preshift, because we did one too many above */
        *TargetString++ = (Value & Mask)?'1':'0';
    }
    *TargetString = 0; /* Null terminator for C string */
}

Funkce volání "vlastní" řetězec ...:

char BinaryString[17];
...
PrintBinary( Value, 16, BinaryString);
printf( "yadda yadda %s yadda...\n", BinaryString);

V závislosti na vašem CPU, většina operací v PrintBinary vykreslit na jeden nebo velmi málo instrukcí stroje.

0
Adam

Možná to není moc efektivní, ale je to docela jednoduché. Zkuste to:

tmp1 = 1;
while(inint/tmp1 > 1) {
    tmp1 <<= 1;
}
do {
    printf("%d", tmp2=inint/tmp1);
    inint -= tmp1*tmp2;
} while((tmp1 >>= 1) > 0);
printf(" ");
0
Moses

Použijte níže uvedenou funkci:

void conbin(int num){  
        if(num != 0)
        {
            conbin(num >> 1);     
            if (num & 1){
            printf("1");
            }
            else{
            printf("0");
            }
        }
    }
0
kapilddit