Saya dapat mencetak dengan printf sebagai angka hex atau oktal. Apakah ada tag format untuk dicetak sebagai biner, atau basis arbitrer?
Saya menjalankan gcc.
printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n"
print("%b\n", 10); // prints "%b\n"
Jawaban:
Meretas tetapi bekerja untuk saya:
Untuk tipe multi-byte
Sayangnya, Anda membutuhkan semua kutipan tambahan. Pendekatan ini memiliki risiko efisiensi makro (jangan melewati fungsi sebagai argumen untuk
BYTE_TO_BINARY
) tetapi menghindari masalah memori dan beberapa pemanggilan strcat dalam beberapa proposal lainnya di sini.sumber
printf
mana yang denganstatic
buffer tidak bisa.%d
ke%c
, karena harus lebih cepat (%d
harus melakukan konversi digit-> char, sementara%c
hanya mengeluarkan argumenint
32-bit pada sistem, mencetak nilai 32-bit tunggal akan membutuhkan ruang untuk nilai 32 * 4-byte; total 128 byte. Yang, tergantung pada ukuran tumpukan, mungkin atau mungkin tidak menjadi masalah.Cetak Biner untuk Semua Datatype
uji
sumber
size_t i; for (i=size; i-- > 0; )
untuk menghindarisize_t
vsint
salah pertandingan.ptr
(loop luar); lalu untuk setiap bit byte saat ini (loop dalam), tutup byte dengan bit saat ini (1 << j
). Geser ke kanan yang menghasilkan byte yang berisi 0 (0000 0000b
) atau 1 (0000 0001b
). Cetak byte printf yang dihasilkan dengan format%u
. HTH.>
dengansize_t
dan bukan>=
dari komentar Anda untuk menentukan kapan harus mengakhiri loop.>
dan>=
dengan tipe yang tidak ditandatangani.0
adalah kasus tepi yang tidak ditandatangani dan sering terjadi, tidak seperti matematika yang ditandatangani dengan yang kurang umumINT_MAX/INT_MIN
.Berikut ini adalah retasan cepat untuk menunjukkan teknik untuk melakukan apa yang Anda inginkan.
sumber
strcat
adalah metode yang tidak efisien untuk menambahkan karakter tunggal ke string pada setiap lintasan loop. Sebagai gantinya, tambahkanchar *p = b;
dan ganti loop dalam dengan*p++ = (x & z) ? '1' : '0'
.z
harus dimulai pada 128 (2 ^ 7), bukan 256 (2 ^ 8). Coba perbarui untuk mengambil pointer ke buffer yang akan digunakan (untuk keamanan thread), mirip denganinet_ntoa()
.strcat()
! Saya setuju bahwastrcat
mungkin lebih mudah dipahami daripada menambahkan pointer dereferenced setelah penugasan, tetapi bahkan pemula perlu tahu cara menggunakan perpustakaan standar dengan benar. Mungkin menggunakan array yang diindeks untuk tugas akan menjadi demonstrasi yang baik (dan benar-benar akan berfungsi, karenab
tidak disetel ulang ke all-nol setiap kali Anda memanggil fungsi).printf("%s + %s = %s", byte_to_binary(3), byte_to_binary(4), byte_to_binary(3+4))
.Biasanya tidak ada specifier konversi biner di glibc.
Dimungkinkan untuk menambahkan jenis konversi khusus ke keluarga fungsi printf () di glibc. Lihat register_printf_fungsi untuk detailnya. Anda dapat menambahkan konversi% b kustom untuk penggunaan Anda sendiri, jika itu menyederhanakan kode aplikasi agar tersedia.
Berikut adalah contoh cara menerapkan format printf kustom di glibc.
sumber
warning: 'register_printf_function' is deprecated [-Wdeprecated-declarations]
Ada fungsi baru untuk melakukan hal yang sama, meskipun:register_printf_specifier()
. Contoh penggunaan baru dapat ditemukan di sini: codereview.stackexchange.com/q/219994/200418Anda bisa menggunakan meja kecil untuk meningkatkan kecepatan 1 . Teknik serupa berguna di dunia tertanam, misalnya, untuk membalikkan byte:
1 Saya kebanyakan mengacu pada aplikasi yang dibenamkan di mana pengoptimal tidak begitu agresif dan perbedaan kecepatan terlihat.
sumber
Cetak bit yang paling tidak signifikan dan geser keluar di sebelah kanan. Melakukan ini sampai bilangan bulat menjadi nol mencetak representasi biner tanpa memimpin nol tetapi dalam urutan terbalik. Menggunakan rekursi, pesanan dapat dikoreksi dengan mudah.
Bagi saya, ini adalah salah satu solusi terbersih untuk masalah ini. Jika Anda menyukai
0b
awalan dan karakter baris baru yang tertinggal, saya sarankan membungkus fungsi.Demo online
sumber
putc('0'+(number&1), stdout);
Berdasarkan jawaban @William Whyte, ini adalah makro yang menyediakan
int8
,16
,32
&64
versi, menggunakan kembaliINT8
makro untuk menghindari pengulangan.Output ini:
Untuk keterbacaan, Anda mungkin ingin menambahkan pemisah misalnya:
sumber
PRINTF_BYTE_TO_BINARY_INT#
definisi yang dikelompokkan untuk digunakan secara opsional.Berikut adalah versi fungsi yang tidak mengalami masalah reentrancy atau batasan ukuran / jenis argumen:
Perhatikan bahwa kode ini akan berfungsi dengan baik untuk setiap pangkalan antara 2 dan 10 jika Anda hanya mengganti 2 dengan pangkalan yang diinginkan. Penggunaannya adalah:
Di mana
x
ada ekspresi integral.sumber
char *a = binary_fmt(x), *b = binary_fmt(y);
tidak akan berfungsi seperti yang diharapkan. Memaksa penelepon untuk melewati buffer membuat persyaratan penyimpanannya jelas; penelepon tentu saja bebas menggunakan buffer statis jika itu benar-benar diinginkan, dan kemudian menggunakan kembali buffer yang sama menjadi eksplisit. Juga perhatikan bahwa, pada PIC ABI modern, buffer statis biasanya membutuhkan lebih banyak kode untuk diakses daripada buffer pada stack.sumber
'1'
dan'0'
bukannya49
dan48
di ternary Anda. Juga,b
harus sepanjang 9 karakter sehingga karakter terakhir dapat tetap menjadi terminator nol.static char b[9] = {0}
2. Langkah deklarasi keluar dari loop:int z,y;
3. Tambahkan akhir nol:b[y] = 0
. Dengan cara ini tidak diperlukan reinitalization.8
itu harus diganti olehCHAR_BIT
.Solusi cepat dan mudah:
Bekerja untuk semua jenis ukuran dan untuk int yang ditandatangani dan tidak ditandatangani. Tanda '& 1' diperlukan untuk menangani int yang ditandatangani karena shift mungkin melakukan ekstensi sign.
Ada banyak cara untuk melakukan ini. Inilah yang super sederhana untuk mencetak 32 bit atau n bit dari jenis 32 bit yang ditandatangani atau tidak ditandatangani (tidak menempatkan negatif jika ditandatangani, hanya mencetak bit yang sebenarnya) dan tidak ada carriage return. Perhatikan bahwa saya dikurangi sebelum bit shift:
Bagaimana dengan mengembalikan string dengan bit untuk disimpan atau dicetak nanti? Anda dapat mengalokasikan memori dan mengembalikannya dan pengguna harus membebaskannya, atau Anda mengembalikan string statis tetapi itu akan musnah jika dipanggil lagi, atau dengan utas lainnya. Kedua metode yang ditampilkan:
Telepon dengan:
sumber
Tidak ada jawaban yang diposting sebelumnya persis apa yang saya cari, jadi saya menulis satu. Sangat mudah menggunakan% B dengan
printf
!sumber
char* buffer = (char*) malloc(sizeof(char) * 50);
char *buffer = malloc(sizeof(*buffer) * 50);
Beberapa runtime mendukung "% b" walaupun itu bukan standar.
Lihat juga di sini untuk diskusi yang menarik:
http://bytes.com/forum/thread591027.html
HTH
sumber
Kode ini harus menangani kebutuhan Anda hingga 64 bit. Saya membuat 2 fungsi pBin & pBinFill. Keduanya melakukan hal yang sama, tetapi pBinFill mengisi ruang terkemuka dengan fillChar. Fungsi uji menghasilkan beberapa data uji, lalu mencetaknya menggunakan fungsi tersebut.
sumber
width
!The
printf()
keluarga hanya mampu mencetak dalam basis 8, 10, dan 16 dengan menggunakan penentu standar langsung. Saya sarankan membuat fungsi yang mengubah angka menjadi string per kebutuhan khusus kode.Untuk mencetak basis apa pun [2-36]
Semua jawaban lain sejauh ini memiliki setidaknya satu dari keterbatasan ini.
Gunakan memori statis untuk buffer kembali. Ini membatasi berapa kali fungsi dapat digunakan sebagai argumen
printf()
.Alokasikan memori yang membutuhkan kode panggilan ke pointer gratis.
Memerlukan kode panggilan untuk secara eksplisit menyediakan buffer yang sesuai.
Hubungi
printf()
langsung. Ini mewajibkan fungsi baru untuk untukfprintf()
,sprintf()
,vsprintf()
, dllGunakan rentang integer yang dikurangi.
Berikut ini tidak memiliki batasan di atas . Itu membutuhkan C99 atau lebih baru dan penggunaan
"%s"
. Ini menggunakan senyawa literal untuk menyediakan ruang buffer. Tidak memiliki masalah dengan beberapa panggilan dalam aprintf()
.Keluaran
sumber
Mungkin sedikit OT, tetapi jika Anda hanya membutuhkan ini untuk debug untuk memahami atau menelusuri kembali beberapa operasi biner yang Anda lakukan, Anda mungkin melihat wcalc (kalkulator konsol sederhana). Dengan opsi -b Anda mendapatkan output biner.
misalnya
sumber
ruby -e 'printf("%b\n", 0xabc)'
,dc
diikuti oleh2o
diikuti oleh0x123p
, dan sebagainya.Tidak ada fungsi format di pustaka standar C untuk menghasilkan biner seperti itu. Semua operasi format yang didukung keluarga printf adalah terhadap teks yang dapat dibaca manusia.
sumber
Fungsi rekursif berikut mungkin berguna:
sumber
Saya mengoptimalkan solusi teratas untuk ukuran dan C ++ - ness, dan mendapatkan solusi ini:
sumber
std::string
), Anda mungkin juga menyingkirkanstatic
array. Cara paling sederhana adalah dengan hanya menjatuhkanstatic
kualifikasi dan menjadikanb
lokal ke fungsi.((x>>z) & 0x01) + '0'
Cukup.Cetak bit dari jenis apa pun menggunakan lebih sedikit kode dan sumber daya
Pendekatan ini memiliki atribut:
Keluaran
Saya telah menggunakan pendekatan lain ( bitprint.h ) untuk mengisi tabel dengan semua byte (sebagai string bit) dan mencetaknya berdasarkan input / index byte. Layak untuk dilihat.
sumber
sumber
Saya menyukai kode oleh paniq, buffer statis adalah ide yang bagus. Namun gagal jika Anda ingin beberapa format biner dalam printf tunggal () karena selalu mengembalikan pointer yang sama dan menimpa array.
Ini adalah drop-in gaya C yang memutar pointer pada buffer split.
sumber
count
mencapaiMAXCNT - 1
, penambahan berikutnyacount
akan membuatnyaMAXCNT
bukan nol, yang akan menyebabkan akses keluar dari batas-batas array. Anda seharusnya melakukannyacount = (count + 1) % MAXCNT
.MAXCNT + 1
panggilan ke fungsi ini dalam satuprintf
. Secara umum, jika Anda ingin memberikan opsi untuk lebih dari 1 hal, buatlah tak terbatas. Angka seperti 4 hanya dapat menyebabkan masalah.Tidak ada cara standar dan portabel.
Beberapa implementasi menyediakan itoa () , tetapi tidak akan di sebagian besar, dan memiliki antarmuka yang agak payah. Tetapi kodenya ada di belakang tautan dan seharusnya membiarkan Anda menerapkan formatter Anda sendiri dengan mudah.
sumber
Satu pernyataan konversi generik dari semua tipe integral ke representasi string biner menggunakan pustaka standar :
Atau hanya:
std::cout << std::bitset<sizeof(num) * 8>(num);
sumber
Solusi saya:
sumber
Berdasarkan saran @ ideasman42 di jawabannya, ini adalah makro yang menyediakan
int8
,16
,32
&64
versi, menggunakan kembaliINT8
makro untuk menghindari pengulangan.Output ini:
Untuk keterbacaan, Anda dapat mengubah:
#define PRINTF_BINARY_SEPARATOR
menjadi#define PRINTF_BINARY_SEPARATOR ","
atau#define PRINTF_BINARY_SEPARATOR " "
Ini akan menampilkan:
atau
sumber
Menggunakan:
Untuk referensi lebih lanjut, lihat Cara mencetak nomor biner melalui printf .
sumber
harus bekerja - belum diuji.
sumber
sumber
Berikutnya akan menunjukkan kepada Anda tata letak memori:
sumber
Berikut ini adalah variasi kecil dari solusi paniq yang menggunakan templat untuk memungkinkan pencetakan integer 32 dan 64 bit:
Dan bisa digunakan seperti:
Inilah hasilnya:
sumber