Ada sejumlah cara untuk mendekati pencetakan representasi biner untuk bilangan apa pun. Pertama, Anda cukup menampilkan hasil operasi shift dan indeks secara langsung (ke stdout
, file, dll...) Tampaknya ini adalah pendekatan yang Anda mulai, tetapi kemudian Anda mendeklarasikan buffer 32 bit. Meskipun Anda pasti bisa melakukan itu, tidak perlu melakukan buffering pada hasilnya jika Anda tidak ingin mengembalikan pointer ke buffer yang telah selesai. (yang membawa saya ke poin ketiga saya, di bawah)
Mengeluarkan bit secara sederhana tanpa menyimpan/mengembalikan pointer ke bit dalam string nul-terminated, ada tempatnya tetapi umumnya penggunaannya terbatas. Namun demikian, ini adalah masalah umum yang mencakup dasar-dasar semua pendekatan. Membuat representasi biner tanpa bantalan dapat dilakukan sebagai berikut:
/** unpadded binary representation of 'v'. */
void binprn (const unsigned long v)
{
if (!v) { putchar ('0'); return; }; /* if v = 0 output '0' */
size_t sz = sizeof v * CHAR_BIT; /* get the number of bits in v */
unsigned long rem = 0; /* variable to hold shifted result */
while (sz--) /* for each bit (in decreasing order) */
if ((rem = v >> sz)) /* if bits exist in the shifted value */
putchar ((rem & 1) ? '1' : '0'); /* output '1' or '0' */
}
Komentarnya cukup menjelaskan. Skemanya adalah dengan menggeser setiap bit yang dimulai dengan bit paling signifikan (misalnya bit 31 (31-0) untuk nomor 32-bit. Anda memeriksa apakah ada 1-bit setelah pergeseran tersebut (jika tidak, pergeserannya melebihi yang paling banyak). posisi bit yang signifikan dalam angka dan tidak ada yang perlu dicetak). Begitu ada bit yang ditemukan di rem
, akan selalu ada bit-bit yang harus dicetak sepanjang sisa iterasi perulangan karena Anda menggeser dengan jumlah yang semakin berkurang. Dengan memulai dari bit paling signifikan (yang dicetak pertama kali), bit Anda akan dicetak dalam urutan yang benar dan hanya mencetak jumlah bit yang membentuk nomor tersebut.
Umumnya ketika Anda hanya mengeluarkan representasi biner langsung ke layar, Anda hanya ingin mengeluarkan bit hingga bit paling signifikan. (yang mencegah keluaran 1
dengan 63 0
di depannya sehingga membuat segalanya berantakan.)
Selanjutnya, mengeluarkan representasi biner berlapis ke sejumlah bit. Ini berguna jika Anda hanya ingin melihat 8, 16, 32, ...
bit terbawah dalam angka berapa pun, namun menginginkan representasi dengan jumlah bit tetap setiap saat. Di sini Anda cukup memasukkan jumlah bit yang ingin Anda lihat. Fungsi Anda kemudian akan mengulang jumlah posisi bit dalam nomor Anda dan menampilkan hasilnya:
/** binary representation of 'v' padded to 'sz' bits.
* the padding amount is limited to the number of
* bits in 'v'. valid range: 0 - sizeof v * CHAR_BIT.
*/
void binprnpad (const unsigned long v, size_t sz)
{
if (!sz) putchar ((v & 1) ? '1' : '0'); /* if no sz, '0' is fine */
if (sz > sizeof v * CHAR_BIT) /* if sz exceed # of bits, limit */
sz = sizeof v * CHAR_BIT;
while (sz--) /* for sz positions in decreasing order, '1' or '0' */
putchar ((v >> sz & 1) ? '1' : '0');
}
Anda akan melihat perbedaan utama di sini adalah Anda tidak perlu repot memeriksa apakah masih ada bit untuk mencegah pencetakan angka nol di depan yang tidak diinginkan, karena Anda mengontrol jumlah bit dengan parameter sz
. (terserah Anda apa yang Anda lakukan jika ukuran 0
dilewati, saya hanya memilih untuk menampilkan '0'
)
Sekarang untuk poin ketiga yang disebutkan di atas. Mengeluarkan bit saja sudah rumit dari sudut pandang pemformatan di bagian utama kode Anda. Saya merasa jauh lebih berguna untuk menyimpan bit dalam array karakter (nul-terminated sehingga dapat diperlakukan sebagai string) dan mengembalikan pointer ke array sehingga dapat diteruskan ke printf
, dll Sekarang Anda harus memasukkan array berukuran cukup sebagai parameter, mendeklarasikan array static
sehingga array tidak dimusnahkan saat fungsi dikembalikan, atau secara dinamis mengalokasikan penyimpanan untuk array di dalam fungsi. Semuanya memiliki kelebihan dan kekurangan yang harus Anda pertimbangkan tergantung pada kebutuhan kode Anda. misalnya.:
/** returns pointer to binary representation of 'v' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad (const unsigned long v, const size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;
for (i = 0; i < sz; i++)
*--p = (v>>i & 1) ? '1' : '0';
return p;
}
Kode berfungsi sama dengan kode empuk non-buffer di atas. Perhatikan bagaimana p
mengembalikan posisi awal dalam buffer di mana sz
jumlah bit dimulai. Perhatikan juga bahwa Anda memerlukan konstanta untuk BITS_PER_LONG
yang menunjukkan jumlah bit dalam long
pada perangkat keras Anda. (yang biasanya ditangani dengan cara yang mirip dengan BUILD_64
)
catatan: perlu diketahui bahwa salah satu batasan pada deklarasi static
adalah fungsi konversi hanya dapat digunakan sekali dalam satu panggilan printf
(atau dalam satu baris kode) karena hanya ada satu larik penyimpanan untuk konversi biner. (Anda selalu dapat melakukan sejumlah panggilan dan menyimpan hasilnya di lokasi berbeda sebelum melakukan panggilan printf
)
Salah satu variasi terakhir pada cetakan biner adalah cetakan representasi dengan pemisah yang disertakan untuk membuatnya lebih mudah untuk mengidentifikasi dan membandingkan antara string biner (terutama ketika berhadapan dengan urutan 0
dan 1
yang lebih panjang. Misalnya:
hexval : 0xdeadbeef => 11011110-10101101-10111110-11101111
Fungsinya pada dasarnya bekerja sama seperti binpad
di atas, tetapi dengan tambahan bahwa buffer statis lebih besar untuk mengakomodasi pemisah dan pemeriksaan tambahan pada posisi bit untuk menentukan kapan pemisah harus ditambahkan ke buffer:
/** returns pointer to formatted binary representation of 'v' zero padded to 'sz'.
* returns pointer to string contianing formatted binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits with char
* 'sep' placed every 'szs' digits. (e.g. 10001010 -> 1000-1010).
*/
char *binfmt (const unsigned long v, const unsigned char sz,
const unsigned char szs, const char sep)
{
static char s[BITS_PER_LONG * 2 + 1] = {0};
char *p = s + 2 * BITS_PER_LONG;
register size_t i;
*p = 0;
for (i = 0; i < sz; i++) {
p--;
if (i > 0 && szs > 0 && i % szs == 0)
*p-- = sep;
*p = (v >> i & 1) ? '1' : '0';
}
return p;
}
Masalah Anda yang tersisa hanyalah memproses argumen baris perintah, dan melakukan konversi dari string input ke nilai yang tidak ditandatangani bersama dengan pemeriksaan validasi bahwa jumlahnya tidak melebihi 32-bit, dll. Anda dapat memproses argumen dengan getops
atau untuk sejumlah kecil opsi sederhana Anda cukup menggunakan loop. Di Linux, satu-satunya argumen wajib yang harus ditanggapi oleh kode Anda adalah -h
untuk bantuan dan -v
untuk versi. Meskipun tidak ada yang melakukan ini untuk contoh singkat, dll., setidaknya menyenangkan untuk memiliki informasi tersebut. Lihat contoh berikut yang menggabungkan semua bagian dan beri tahu saya jika Anda memiliki pertanyaan:
#include <stdio.h>
#include <stdlib.h> /* for strtoul */
#include <errno.h> /* for errno */
#include <limits.h> /* for UINT_MAX, ULONG_MAX, CHAR_BIT */
#define PACKAGE "hex2bin"
#define VERSION "0.01"
/* BUILD_64 - Check x86/x86_64 */
#if defined(__LP64__) || defined(_LP64)
# define BUILD_64 1
#endif
/* BITS_PER_LONG */
#ifdef BUILD_64
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif
unsigned long processopts (int argc, char **argv);
unsigned long xstrtoul (char *s);
void binprn (const unsigned long v);
void binprnpad (const unsigned long v, size_t sz);
char *binpad (const unsigned long v, const size_t sz);
char *binfmt (const unsigned long v, const unsigned char sz,
const unsigned char szs, const char sep);
void help (int xcode);
int main (int argc, char **argv) {
unsigned long hexval = processopts (argc, argv);
/* print unpadded binary */
printf ("\n hexval : 0x%lx (%lu) => ", hexval, hexval);
binprn (hexval);
printf ("\n");
/* print padded to 32-bits */
printf ("\n hexval : 0x%lx (%lu) => ", hexval, hexval);
binprnpad (hexval, sizeof (int) * CHAR_BIT);
printf ("\n");
/* padded binary returned as formatted string
* with '-' separators every 8 bits
*/
printf ("\n hexval : 0x%lx (%lu) => %s\n\n", hexval, hexval,
binfmt (hexval, sizeof (int) * CHAR_BIT, CHAR_BIT, '-'));
return 0;
}
/* quick custom argument handler */
unsigned long processopts (int argc, char **argv)
{
size_t i = 1;
unsigned long val = 0;
if (argc < 2) help (0); /* insufficient arguments */
for (; argv[i]; i++) { /* for each argument */
if (*argv[i] == '-') { /* for each beginning with '-' */
switch (argv[i][1]) {
case 'h': /* respond to '-h' help */
help (0);
case 'p': /* handle '-p' convert value */
if (!argv[i+1]) { /* if '-p' w/o next arg */
fprintf (stderr, "error: insufficient input.\n");
help (1);
}
if (*argv[i+1] != '0' || /* validate hex input */
(argv[i+1][1] != 'x' && argv[i+1][1] != 'X')) {
fprintf (stderr, "error: invalid 'hex_value' input.\n");
help (1);
}
val = xstrtoul (argv[i+1]); /* convert to ulong */
if (val > UINT_MAX) { /* validate 32-bits */
fprintf (stderr, "error: input value exceeds 32-bits.\n");
help (1);
}
break;
case 'v': /* respond to '-v' version */
printf ("%s, version %s\n", PACKAGE, VERSION);
exit (0);
default :
fprintf (stderr, "error: invalid/unrecognized option '%s'.\n",
argv[i]);
help (1);
}
}
}
return val; /* return val */
}
unsigned long xstrtoul (char *s)
{
unsigned long v = 0;
errno = 0;
/* test for hex or decimal conversion */
if (*s == '0' && (s[1] == 'x' || s[1] == 'X'))
v = strtoul (s, NULL, 16);
else
v = strtoul (s, NULL, 10);
/* check for various possible errors */
if ((errno == ERANGE && v == ULONG_MAX) || (errno != 0 && v == 0)) {
perror ("strtoul");
exit (EXIT_FAILURE);
}
return v;
}
/** unpadded binary representation of 'v'. */
void binprn (const unsigned long v)
{
if (!v) { putchar ('0'); return; };
size_t sz = sizeof v * CHAR_BIT;
unsigned long rem = 0;
while (sz--)
if ((rem = v >> sz))
putchar ((rem & 1) ? '1' : '0');
}
/** binary representation of 'v' padded to 'sz' bits.
* the padding amount is limited to the number of
* bits in 'v'. valid range: 0 - sizeof v * CHAR_BIT.
*/
void binprnpad (const unsigned long v, size_t sz)
{
if (!sz) putchar ((v & 1) ? '1' : '0');
if (sz > sizeof v * CHAR_BIT)
sz = sizeof v * CHAR_BIT;
while (sz--)
putchar ((v >> sz & 1) ? '1' : '0');
}
/** returns pointer to binary representation of 'v' zero padded to 'sz'.
* returns pointer to string contianing binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits.
*/
char *binpad (const unsigned long v, const size_t sz)
{
static char s[BITS_PER_LONG + 1] = {0};
char *p = s + BITS_PER_LONG;
register size_t i;
for (i = 0; i < sz; i++)
*--p = (v>>i & 1) ? '1' : '0';
return p;
}
/** returns pointer to formatted binary representation of 'v' zero padded to 'sz'.
* returns pointer to string contianing formatted binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits with char
* 'sep' placed every 'szs' digits. (e.g. 10001010 -> 1000-1010).
*/
char *binfmt (const unsigned long v, const unsigned char sz,
const unsigned char szs, const char sep)
{
static char s[BITS_PER_LONG * 2 + 1] = {0};
char *p = s + 2 * BITS_PER_LONG;
register size_t i;
*p = 0;
for (i = 0; i < sz; i++) {
p--;
if (i > 0 && szs > 0 && i % szs == 0)
*p-- = sep;
*p = (v >> i & 1) ? '1' : '0';
}
return p;
}
void help (int xcode)
{
xcode = xcode ? xcode : 0; /* set default exit code */
printf ("\n %s, version %s\n\n"
" usage: %s -p hex_value (32-bit)\n\n"
" converts 'hex_value' to its binary representation.\n\n"
" Options:\n\n"
" -h this help.\n"
" -p hex_value display binary representation of 'hex_value'.\n"
" -v display version information.\n\n",
PACKAGE, VERSION, PACKAGE);
exit (xcode);
}
Penggunaan/Keluaran
$ ./bin/hex2bin -p 0xe7
hexval : 0xe7 (231) => 11100111
hexval : 0xe7 (231) => 00000000000000000000000011100111
hexval : 0xe7 (231) => 00000000-00000000-00000000-11100111
$ ./bin/hex2bin -p 0xdeadbeef
hexval : 0xdeadbeef (3735928559) => 11011110101011011011111011101111
hexval : 0xdeadbeef (3735928559) => 11011110101011011011111011101111
hexval : 0xdeadbeef (3735928559) => 11011110-10101101-10111110-11101111
$ ./bin/hex2bin -h
hex2bin, version 0.01
usage: hex2bin -p hex_value (32-bit)
converts 'hex_value' to its binary representation.
Options:
-h this help.
-p hex_value display binary representation of 'hex_value'.
-v display version information.
$ ./bin/hex2bin -v
hex2bin, version 0.01
person
David C. Rankin
schedule
19.02.2016
Agak tidak jelas apa masalah Anda. Mungkin saja Anda memiliki beberapa paket yang tidak kompatibel. Untuk menghindari masalah seperti ini, saya merekomendasikan penggunaan Anaconda: https://anaconda.org
Itu akan datang dengan python dan sebagian besar perpustakaan dasar, termasuk matplotlib. Saya juga dapat merekomendasikan seaborn untuk plot yang terlihat profesional dan tidak memerlukan banyak kode.
- person DNH   schedule 19.02.20160-size
Anda mendapatkan bit dalam urutan host-byte sehingga bit pertama yang Anda geser adalah bit paling tidak signifikan pada perangkat keras little-endian. Anda dapat mengatasinya dengan beberapa cara, mengindeks posisi karakter dalam array Anda dari tinggi ke rendah untuk memperbaiki masalah, atau Anda dapat melakukan pergeseran yang lebih besar terlebih dahulu (misalnyan >> size - 1
) dan menulis bit dalam urutan normal. Setelah Anda memahami kekhasan itu, pengkodeannya menjadi mudah. - person David C. Rankin   schedule 19.02.2016