Printf ile onaltılık veya sekizli sayı olarak yazdırabilirim. İkili veya rastgele temel olarak yazdırılacak bir biçim etiketi var mı?
Gcc çalıştırıyorum.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Printf ile onaltılık veya sekizli sayı olarak yazdırabilirim. İkili veya rastgele temel olarak yazdırılacak bir biçim etiketi var mı?
Gcc çalıştırıyorum.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Yanıtlar:
Hacky ama benim için çalışıyor:
#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));
Çok baytlı tipler için
printf("m: "BYTE_TO_BINARY_PATTERN" "BYTE_TO_BINARY_PATTERN"\n",
BYTE_TO_BINARY(m>>8), BYTE_TO_BINARY(m));
Ne yazık ki tüm ekstra tırnak gerekir. Bu yaklaşım, makroların verimlilik risklerine sahiptir (argüman olarak bir işlevi geçmeyin BYTE_TO_BINARY
), ancak buradaki diğer bazı tekliflerde bellek sorunlarından ve çoklu strcat çağrılarından kaçınır.
printf
olanların yapamayacağı birçok kez çağrılma avantajı da vardır static
.
%d
için %c
bile daha hızlı olması gerektiği, çünkü ( %d
ederken, digit-> karakter dönüşümü gerçekleştirmek zorundadır %c
basitçe argüman verir
int
Sistemde 32 bit olduğu varsayıldığında , tek bir 32 bit değerinin yazdırılması 32 * 4 bayt değerleri için alan gerektirir; toplam 128 bayt. Yığın boyutuna bağlı olarak sorun olabilir veya olmayabilir.
Herhangi Bir Veri Türü İçin İkili Yazdırma
//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("");
}
Ölçek
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;
}
size_t i; for (i=size; i-- > 0; )
önlemek için size_t
vs int
yanlış eşleme.
ptr
(dış döngü); ardından her bit için geçerli bayt (iç döngü), baytı geçerli bit ( 1 << j
) ile maskeler . Bu sağa kaydırarak 0 ( 0000 0000b
) veya 1 ( 0000 0001b
) içeren bir bayt elde edilir . Formatı ile sonuçlanan bayt printf yazdır %u
. HTH.
>
olan size_t
ve olmayan >=
döngü sonlandırmak için zaman yorumunuzun belirlemek için.
>
ve son durum kullanımının dikkate alınmasına dikkat edilmelidir >=
. 0
imzasız bir kenar durumu ve daha az yaygın olan imzalı matematik aksine, yaygın olarak ortaya çıkar INT_MAX/INT_MIN
.
İşte istediğinizi yapmak için teknikleri göstermek için hızlı bir kesmek.
#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;
}
strcat
döngünün her geçişinde dizeye tek bir karakter eklemek için verimsiz bir yöntemdir. Bunun yerine, a ekleyin char *p = b;
ve iç halkayı ile değiştirin *p++ = (x & z) ? '1' : '0'
. z
256 (2 ^ 8) yerine 128 (2 ^ 7) ile başlamalıdır. Kullanılacak ara belleğe (iş parçacığı güvenliği için) benzer bir işaretçi almak için güncellemeyi düşünün inet_ntoa()
.
strcat()
! strcat
Muhtemelen anlaşılması için ödevin kaydı kaldırılmış bir işaretçiyi arttırmadan daha kolay olduğunu kabul ediyorum , ancak yeni başlayanların bile standart kütüphaneyi nasıl kullanacaklarını bilmeleri gerekiyor. Belki de atama için dizine alınmış bir dizi kullanmak iyi bir gösterim olurdu (ve b
işlevi her çağırdığınızda tüm sıfırlara sıfırlanmadığından , aslında işe yarayacaktır ).
printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4))
.
Normal olarak glibc'de ikili bir dönüşüm belirteci yoktur.
Glibc'deki printf () ailesine özel dönüşüm türleri eklemek mümkündür. Ayrıntılar için register_printf_function bölümüne bakın . Uygulama kodunu kullanılabilir hale getirmek için basitleştirirse, kendi kullanımınız için özel bir% b dönüşümü ekleyebilirsiniz.
İşte glibc'de özel bir printf formatlarının nasıl uygulanacağına dair bir örnek .
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]
Aynı olsa yapmak için yeni bir işlevi yoktur: register_printf_specifier()
. Yeni kullanımın bir örneğini burada bulabilirsiniz: codereview.stackexchange.com/q/219994/200418
Hızı artırmak için küçük bir tablo kullanabilirsiniz 1 . Benzer teknikler gömülü dünyada, örneğin bir baytı ters çevirmek için yararlıdır:
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 Çoğunlukla optimize edicilerin çok agresif olmadığı ve hız farkının görüldüğü gömülü uygulamalardan bahsediyorum.
En küçük biti yazdırın ve sağdan dışarı kaydırın. Tamsayı sıfır oluncaya kadar bunu yapmak, ikili gösterimleri baştaki sıfırlar olmadan, ancak ters sırada yazdırır. Özyineleme kullanarak, sipariş oldukça kolayca düzeltilebilir.
#include <stdio.h>
void print_binary(int number)
{
if (number) {
print_binary(number >> 1);
putc((number & 1) ? '1' : '0', stdout);
}
}
Bana göre, bu sorunun en temiz çözümlerinden biri. 0b
Önek ve sondaki yeni satır karakterini beğendiyseniz , işlevi sarmanızı öneririz.
putc('0'+(number&1), stdout);
@William Whyte'ın cevap dayanarak, bu sağlayan bir makro olduğunu int8
, 16
, 32
ve 64
yeniden sürümlerini INT8
önlemek tekrarına makro.
/* --- 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;
}
Bu çıktılar:
My Flag 0001011011100001001010110111110101111000100100001111000000101000
Okunabilirlik için aşağıdakiler için bir ayırıcı eklemek isteyebilirsiniz:
My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
PRINTF_BYTE_TO_BINARY_INT#
İsteğe bağlı olarak kullanmak için tanımlanmış gruplanmış bir sürümü ekler .
İşlevin yeniden girme sorunlarından muzdarip olmayan veya bağımsız değişkenin boyutuna / türüne ilişkin sınırlamalar olmayan bir işlev sürümü:
#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;
}
Sadece 2'leri istediğiniz tabanla değiştirirseniz, bu kodun 2 ile 10 arasındaki herhangi bir taban için de işe yarayacağını unutmayın. Kullanımı:
char tmp[FMT_BUF_SIZE];
printf("%s\n", binary_fmt(x, tmp));
x
Herhangi bir integral ifade nerede .
char *a = binary_fmt(x), *b = binary_fmt(y);
beklendiği gibi çalışmayacağını bilmelidir . Arayıcının bir tamponu geçmeye zorlanması, depolama gereksinimini ortadan kaldırır; arayan, elbette, gerçekten isteniyorsa statik bir tampon kullanmakta serbesttir ve daha sonra aynı tamponun tekrar kullanılması açık hale gelir. Ayrıca, modern PIC ABI'lerde statik arabelleklerin genellikle yığındaki arabelleklerden daha fazla kod maliyeti olduğunu unutmayın.
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;
}
'1'
ve '0'
yerine 49
ve 48
sizin üçlü içinde. Ayrıca, b
9 karakter uzunluğunda olmalıdır , böylece son karakter boş bir sonlandırıcı olarak kalabilir.
static char b[9] = {0}
halkanın dışında 2. hamle beyanı: int z,y;
3. Final sıfır ekleyin: b[y] = 0
. Bu şekilde reinitalizasyona gerek yoktur.
8
ile değiştirilmelidir CHAR_BIT
.
Hızlı ve kolay çözüm:
void printbits(my_integer_type x)
{
for(int i=sizeof(x)<<3; i; i--)
putchar('0'+((x>>(i-1))&1));
}
Her boyutta ve imzalı ve imzasız girişlerde çalışır. Vardiya işaret uzantısı yapabileceğinden, imzalanan girişleri işlemek için '& 1' gereklidir.
Bunu yapmanın pek çok yolu var. Burada, imzalı veya imzasız 32 bit türden 32 bit veya n bit yazdırmak (imzalı ise negatif koymamak, sadece gerçek bitleri yazdırmak) ve satırbaşı yok için çok basit bir işlemdir. İ, bit kaydırmasından önce azaltılır:
#define printbits_n(x,n) for (int i=n;i;i--,putchar('0'|(x>>i)&1))
#define printbits_32(x) printbits_n(x,32)
Daha sonra depolamak veya yazdırmak için bitlerle bir dize döndürmeye ne dersiniz? Ya belleği ayırabilir ve geri gönderebilirsiniz ve kullanıcının serbest bırakması gerekir, aksi takdirde statik bir dize döndürürsünüz, ancak yeniden çağrılırsa veya başka bir iş parçacığı tarafından engellenir. Her iki yöntem de gösterilmiştir:
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;
}
İle ara:
// 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);
Daha önce gönderilen cevapların hiçbiri tam olarak aradığım şey değildi, bu yüzden bir tane yazdım. % B ile 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);
}
char* buffer = (char*) malloc(sizeof(char) * 50);
char *buffer = malloc(sizeof(*buffer) * 50);
Bazı çalışma zamanları standart olmasa da "% b" yi destekler.
Ayrıca ilginç bir tartışma için buraya bakın:
http://bytes.com/forum/thread591027.html
HTH
Bu kod 64 bite kadar ihtiyaçlarınızı karşılamalıdır. 2 fonksiyon pBin & pBinFill oluşturdum. Her ikisi de aynı şeyi yapar, ancak pBinFill, önde gelen boşlukları fillChar ile doldurur. Sınama işlevi bazı sınama verileri oluşturur, ardından bu işlevi kullanarak yazdırır.
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
width
bunun yerine böyle bir genel ad kullanmak için log4cxx komutunu söylemelisiniz !
İkili biçimde yazdırmak için bir printf dönüştürücü var mı?
printf()
Aile sadece doğrudan standart belirteçleri kullanarak tabanı 8, 10 ve 16 baskı yapabiliyor. Kodun özel ihtiyaçlarına göre bir dizeye sayı dönüştüren bir işlev oluşturmanızı öneririz.
Herhangi bir tabanda yazdırmak için [2-36]
Şimdiye kadar olan diğer tüm cevaplar bu sınırlamalardan en az birine sahiptir.
Dönüş arabelleği için statik bellek kullanın. Bu, işlevin bağımsız değişken olarak kaç kez kullanılabileceğini sınırlar printf()
.
Arama kodunu gerektiren belleği boş göstergelere ayırın.
Arama kodunun açıkça uygun bir arabellek sağlamasını isteyin.
printf()
Doğrudan arayın . Bu için yeni işlev mecbur fprintf()
, sprintf()
, vsprintf()
vb
Daha düşük bir tamsayı aralığı kullanın.
Aşağıdakiler yukarıdaki sınırlamalardan hiçbirine sahip değildir . C99 veya daha yenisini ve kullanımını gerektirir "%s"
. Tampon alanı sağlamak için bileşik bir değişmez değeri kullanır . İçinde birden fazla çağrı ile hiçbir sorun yoktur 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;
}
Çıktı
1020304 5060708
1000000100000001100000100 101000001100000011100001000
100401404
A2F44
Belki biraz OT, ancak yaptığınız bazı ikili işlemleri anlamak veya izlemek için hata ayıklamak için buna ihtiyacınız varsa, wcalc'e (basit bir konsol hesap makinesi) göz atabilirsiniz. -B seçenekleri ile ikili çıktı elde edersiniz.
Örneğin
$ wcalc -b "(256 | 3) ve 0xff" = 0b11
ruby -e 'printf("%b\n", 0xabc)'
ve dc
onu 2o
takip ediyor 0x123p
, vb.
C standart kütüphanesinde böyle ikili çıktı verecek formatlama fonksiyonu yoktur. Printf ailesinin desteklediği tüm format işlemleri insan tarafından okunabilir metne yöneliktir.
Aşağıdaki özyinelemeli işlev yararlı olabilir:
void bin(int n)
{
/* Step 1 */
if (n > 1)
bin(n/2);
/* Step 2 */
printf("%d", n % 2);
}
Boyut ve C ++ için en iyi çözümü optimize ettim ve bu çözüme ulaştım:
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;
}
std::string
) kullanmak istiyorsanız , static
diziden de kurtulabilirsiniz . En basit yol, static
niteleyiciyi b
bırakmak ve işleve yerel yapmaktır .
((x>>z) & 0x01) + '0'
yeterlidir.
Bu yaklaşımın nitelikleri vardır:
#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;
}
$ ./printb
11111111
11111111
00000000 11111111
00000000 00000000 00000000 11111111
01000100
00000000 00000000 00000000 01000100
01000100 00010001 11111111 00000001
00000000 01000011
Kullandım başka bir yaklaşım ( bitprint.h (bit dizeleri gibi) tüm bayt içeren bir tablo doldurmak ve giriş / index byte dayalı bunları yazdırmak için). Bir göz atmaya değer.
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');
}
}
Paniq tarafından kodu sevdim, statik tampon iyi bir fikir. Ancak, her zaman aynı işaretçiyi döndürdüğü ve dizinin üzerine yazdığı için tek bir printf () içinde birden çok ikili biçim istiyorsanız, başarısız olur.
Burada, bölünmüş bir arabellekteki işaretçiyi döndüren bir C stili açılır listesi var.
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;
}
count
ulaşıldığında MAXCNT - 1
, bir sonraki artışı sıfır yerine count
bunu yapar ve bu MAXCNT
da dizinin sınırlarının dışına erişilmesine neden olur. Yapmalıydın count = (count + 1) % MAXCNT
.
MAXCNT + 1
bu işleve çağrıları tek bir şekilde kullanan bir geliştiriciye daha sonra sürpriz olacaktı printf
. Genel olarak, 1'den fazla şey için seçenek vermek istiyorsanız, onu sonsuz yapın. 4 gibi sayılar sadece soruna neden olabilir.
Standart ve taşınabilir bir yol yok.
Bazı uygulamalar itoa () sağlar , ancak çoğunda olmayacak ve biraz crummy bir arayüze sahiptir. Ancak kod bağlantının arkasındadır ve kendi biçimlendiricinizi kolayca uygulamanıza izin vermelidir.
Herhangi bir integral türünün standart kütüphane kullanılarak ikili dize temsiline dönüştürülmesi için bir deyim genel dönüştürmesi :
#include <bitset>
MyIntegralType num = 10;
print("%s\n",
std::bitset<sizeof(num) * 8>(num).to_string().insert(0, "0b").c_str()
); // prints "0b1010\n"
Ya da sadece: std::cout << std::bitset<sizeof(num) * 8>(num);
Çözümüm:
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");
Onun cevabını @ ideasman42 önerisine dayanarak, bu sağlayan bir makro olduğunu int8
, 16
, 32
ve 64
yeniden sürümlerini INT8
önlemek tekrarına makro.
/* --- 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;
}
Bu çıktılar:
My Flag 0001011011100001001010110111110101111000100100001111000000101000
Okunabilirliği için, değiştirebilirsiniz: #define PRINTF_BINARY_SEPARATOR
için #define PRINTF_BINARY_SEPARATOR ","
veya#define PRINTF_BINARY_SEPARATOR " "
Bu çıktı:
My Flag 00010110,11100001,00101011,01111101,01111000,10010000,11110000,00101000
veya
My Flag 00010110 11100001 00101011 01111101 01111000 10010000 11110000 00101000
kullanın:
char buffer [33];
itoa(value, buffer, 2);
printf("\nbinary: %s\n", buffer);
Daha fazla referans için bkz. İkili sayıyı printf ile yazdırma .
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);
}
}
çalışmalı - denenmemiş.
/* 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" */
Sonra size bellek düzenini gösterecektir:
#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;
}
İşte 32 ve 64 bit tamsayıların yazdırılmasına izin vermek için şablonlar kullanan küçük bir paniq çözümü çeşidi :
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);
}
Ve şu şekilde kullanılabilir:
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() );
İşte sonuç:
0x1e127ad: 00000001111000010010011110101101
0x2e0b04ce0: 0000000000000000000000000000001011100000101100000100110011100000