แปลงเลขฐานสิบหกเป็นไบนารี่จากอาร์กิวเมนต์บรรทัดคำสั่ง C

นี่เป็นการบ้านที่ฉันต้องแปลงเลขฐานสิบหกเป็นไบนารี่เมื่อมีการเรียกใช้คำสั่งในเทอร์มินัล "ครู" ของฉันไม่ได้ "สอน" จริงๆ C ฉันก็เลยหลงทางไปแล้ว ฉันต้องรวมขั้นตอน ถือเป็นโมฆะ printBits (i ยาวที่ไม่ได้ลงนาม) ซึ่งจะพิมพ์บิตใน i มันจะถูกเรียกใช้จากบรรทัดคำสั่งโดยใช้สวิตช์ '-p' ตามด้วยจำนวนเต็มยาว 32 บิตที่ไม่ได้ลงนามในรูปแบบฐานสิบหก ตัวอย่าง: $ lab3 -p 0x5

เอาท์พุท: 0000 0000 0000 0000 0000 0000 0000 0101

กรุณาอย่าเพิ่งให้รหัสฉัน ฉันต้องเข้าใจสิ่งนี้

void printBits(unsigned long number) {
    // Declare Array to hold our binary number
    char binaryNumber[32];
    // For Loop Index
    int i;
    for (i = 31; i >= 0; --i)
    {
    binaryNumber[i] = (number & 1);
    number >>= 1;
    }

person DNH    schedule 19.02.2016    source แหล่งที่มา
comment
กรุณาอย่าเพิ่งให้รหัสฉัน ฉันต้องเข้าใจสิ่งนี้ ตกลง.   -  person 4pie0    schedule 19.02.2016
comment
คุณมีอะไรจนถึงตอนนี้?   -  person    schedule 19.02.2016
comment
แก้ไขเพื่อแสดงสิ่งที่ฉันมี ไม่รู้จะไปจากที่นั่นที่ไหน   -  person DNH    schedule 19.02.2016
comment
วิธีที่ดีที่สุดคือให้โปรแกรมทั้งหมด (ควรเป็นโปรแกรมที่คอมไพล์) เพื่อให้เราช่วยเหลือคุณได้ดีที่สุด แสดงให้เราเห็นทุกอย่าง ไม่ใช่แค่ฟังก์ชัน printBits() เนื่องจากคุณมีปัญหาหลายอย่างที่ต้องแก้ไข ไม่ใช่แค่การจัดการไบนารี่เท่านั้น คุณต้องรับอาร์กิวเมนต์บรรทัดคำสั่ง แยกวิเคราะห์เพื่อความถูกต้องแล้วแปลงเป็นจำนวนเต็ม ครูของคุณถามคุณเยอะมากว่าเขา/เธอไม่เต็มใจที่จะช่วยเหลือคุณหรือไม่   -  person    schedule 19.02.2016
comment
คำแนะนำ โปรดดูฟังก์ชันต่อไปนี้ในไลบรารี C: putchar(), strcmp(), sscanf() สิ่งเหล่านี้จะช่วยให้คุณแก้ปัญหาทั้งหมดที่ครูตั้งไว้ให้คุณ สุดท้ายนี้ เพื่อจัดการกับอาร์กิวเมนต์บรรทัดคำสั่ง คุณจะต้องใช้พารามิเตอร์ argc และ argv ในฟังก์ชัน main() ของคุณ ซึ่งพารามิเตอร์เหล่านี้มีการใช้กันอย่างแพร่หลายและสามารถค้นหาใน Google ได้อย่างง่ายดาย   -  person    schedule 19.02.2016
comment
ฉันขอโทษที่ฉันไม่ได้เริ่มต้นกับสิ่งอื่นใดเลย ฉันแค่พยายามทำความเข้าใจวิธีการทำงานของฟังก์ชัน printBits และ Google ก็ไม่ได้ช่วยอะไรมากนัก ฉันอาจจะค้นหาผิดที่ก็ได้   -  person DNH    schedule 19.02.2016
comment

ยังไม่ชัดเจนว่าปัญหาของคุณคืออะไร อาจเป็นเพราะคุณมีแพ็คเกจบางอย่างที่ไม่เข้ากัน เพื่อหลีกเลี่ยงปัญหาประเภทนี้ ฉันขอแนะนำให้ใช้ Anaconda: https://anaconda.org

มันจะมาพร้อมกับ python และไลบรารีพื้นฐานส่วนใหญ่ รวมถึง matplotlib ฉันยังสามารถแนะนำ seaborn สำหรับแปลงที่ดูเป็นมืออาชีพที่ไม่ต้องใช้โค้ดมากนัก

  -  person DNH    schedule 19.02.2016
comment
ปัญหานี้ไม่ยากเกินไป สิ่งที่คุณต้องเข้าใจคือเมื่อคุณเปลี่ยนตัวเลข โดยวนซ้ำ 0-size คุณจะได้รับบิตตามลำดับไบต์ของโฮสต์ ดังนั้นบิตแรกที่คุณเลื่อนจึงเป็นบิตที่มีนัยสำคัญน้อยที่สุดบนฮาร์ดแวร์ little-endian คุณสามารถจัดการได้หลายวิธี จัดทำดัชนีตำแหน่งอักขระในอาร์เรย์ของคุณจากสูงไปต่ำเพื่อแก้ไขปัญหา หรือคุณสามารถทำการเปลี่ยนแปลงที่ใหญ่ขึ้นก่อน (เช่น n >> size - 1) แล้วเขียนบิตตามลำดับปกติ เมื่อคุณเข้าใจถึงนิสัยแปลกๆ แล้ว การเขียนโค้ดก็เป็นเรื่องง่าย   -  person David C. Rankin    schedule 19.02.2016
comment
@DNH คุณมีสิทธิ์ทุกประการที่จะบ่นหากครูของคุณไม่ทำงาน ฉันอยากมีอินเตอร์เน็ตเมื่อสมัยเรียน Stack Overflow เป็นสถานที่ที่ดีในการเรียนรู้อย่างรวดเร็ว และเป็นเรื่องดีที่คุณต้องการเรียนรู้การเขียนโปรแกรมจริงๆ ฉันสอนภาษา C ด้วยตนเองและเป็นโปรแกรมเมอร์มืออาชีพมาเป็นเวลานานแล้ว ดังนั้นจึงสามารถทำได้โดยสิ้นเชิง   -  person    schedule 19.02.2016
comment
@ DavidC.Rankin ลำดับไบต์ของโฮสต์ไม่เกี่ยวข้องหากคุณใช้ประเภทข้อมูล int ที่ไม่ได้ลงชื่อเพื่อเก็บค่า เพียงแค่เปลี่ยนทิศทางที่ถูกต้องและทดสอบบิตที่ถูกต้องก็เป็นสิ่งสำคัญ   -  person    schedule 19.02.2016
comment
ถูกต้องแล้ว ฉันกำลังคิดเร็วขึ้นว่าฉันควรจะเป็น จุดประสงค์คือการอธิบายว่าทำไมการดึงบิตที่มีการเลื่อนที่ต่ำกว่าส่งผลให้มีตำแหน่งบิตที่สูงขึ้นในการแทนค่าไบนารี่   -  person David C. Rankin    schedule 19.02.2016


คำตอบ (4)


มีหลายวิธีในการพิมพ์การแทนค่าไบนารีสำหรับตัวเลขใดๆ ขั้นแรก คุณสามารถส่งออกผลลัพธ์ของการดำเนินการกะและดัชนีได้โดยตรง (ไปยัง stdout ไฟล์ ฯลฯ...) นี่ดูเหมือนจะเป็นแนวทางที่คุณเริ่มใช้ แต่จากนั้นคุณก็ประกาศบัฟเฟอร์ 32 บิต แม้ว่าคุณจะสามารถทำได้อย่างแน่นอน แต่ก็ไม่จำเป็นต้องบัฟเฟอร์ผลลัพธ์หากคุณไม่ต้องการส่งคืนพอยน์เตอร์ไปยังบัฟเฟอร์ที่เสร็จสมบูรณ์ (นั่นนำฉันไปสู่จุดที่ 3 ของฉันด้านล่าง)

เพียงแค่ส่งออกบิตโดยไม่ต้องจัดเก็บ/ส่งคืนตัวชี้ไปยังบิตในสตริง สิ้นสุดด้วยค่า nul จะมีตำแหน่งอยู่ แต่โดยทั่วไปแล้วมีการใช้งานที่จำกัด อย่างไรก็ตาม มันเป็นปัญหาทั่วไปที่ครอบคลุมพื้นฐานของทุกแนวทาง การสร้างการเป็นตัวแทนไบนารี่แบบไม่มีเบาะสามารถทำได้ดังนี้:

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

ความคิดเห็นค่อนข้างอธิบายได้ รูปแบบคือการเปลี่ยนแต่ละบิตที่ขึ้นต้นด้วยบิตที่สำคัญที่สุด (เช่น บิต 31 (31-0) สำหรับตัวเลข 32 บิต คุณตรวจสอบว่ามี 1 บิตใดๆ ที่ตามหลังการเปลี่ยนแปลงหรือไม่ (ถ้าไม่ใช่ การเปลี่ยนแปลงจะเกินค่าสูงสุด) ตำแหน่งบิตที่มีนัยสำคัญในตัวเลขและไม่จำเป็นต้องพิมพ์) เมื่อพบบิตใน rem แล้ว ก็จะมีบิตบิตที่จะพิมพ์ตลอดส่วนที่เหลือของการวนซ้ำเนื่องจากคุณกำลังขยับตามจำนวนที่ลดลง โดยเริ่มจาก บิตที่สำคัญที่สุด (ซึ่งจะพิมพ์ก่อน) คุณจะจบลงด้วยบิตของคุณที่พิมพ์ออกมาตามลำดับที่ถูกต้องและพิมพ์เฉพาะจำนวนบิตที่ประกอบเป็นตัวเลขเท่านั้น

โดยทั่วไปเมื่อคุณเพียงแค่ส่งออกการเป็นตัวแทนไบนารี่ไปยังหน้าจอโดยตรง คุณจะต้องการส่งออกบิตจนถึงบิตที่สำคัญที่สุดเท่านั้น (ซึ่งป้องกันการส่งออก 1 โดยมี 63 0 อยู่ข้างหน้าทำให้เกิดความยุ่งเหยิง)

ถัดไป กำลังส่งออกการแทนค่าไบนารี่แบบบุนวมไปยังบิตจำนวนหนึ่ง สิ่งนี้มีประโยชน์ถ้าคุณต้องการดูที่ 8, 16, 32, ... บิตล่างของตัวเลขใดๆ แต่ต้องการแสดงด้วยจำนวนบิตคงที่ในแต่ละครั้ง ที่นี่คุณเพียงแค่ส่งผ่านจำนวนบิตที่คุณต้องการดู ฟังก์ชันของคุณจะวนซ้ำตำแหน่งบิตจำนวนนั้นในตัวเลขของคุณและแสดงผลลัพธ์:

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

คุณจะสังเกตเห็นความแตกต่างหลักที่นี่คือ คุณไม่ต้องกังวลกับการตรวจสอบว่ายังมีบิตเหลืออยู่หรือไม่เพื่อป้องกันการพิมพ์ศูนย์นำหน้าที่ไม่ต้องการ เนื่องจากคุณควบคุมจำนวนบิตด้วยพารามิเตอร์ sz (ขึ้นอยู่กับคุณว่าคุณจะทำอย่างไรหากผ่านขนาด 0 ฉันแค่เลือกที่จะส่งออก '0')

ตอนนี้สำหรับประเด็นที่สามที่กล่าวถึงข้างต้น การส่งออกบิตเพียงอย่างเดียวนั้นยุ่งยากจากมุมมองการจัดรูปแบบในเนื้อหาหลักของโค้ดของคุณ ฉันพบว่ามีประโยชน์มากกว่ามากในการจัดเก็บบิตในอาร์เรย์อักขระ (สิ้นสุดด้วย nul เพื่อให้สามารถถือเป็นสตริงได้) และส่งคืนตัวชี้ไปยังอาร์เรย์เพื่อให้สามารถส่งผ่านไปยัง printf ฯลฯ ตอนนี้คุณต้องส่งอาร์เรย์ที่มีขนาดเพียงพอเป็นพารามิเตอร์ ประกาศอาร์เรย์ static เพื่อให้อาร์เรย์ไม่ถูกทำลายเมื่อส่งคืนฟังก์ชัน หรือจัดสรรพื้นที่เก็บข้อมูลแบบไดนามิกสำหรับอาร์เรย์ภายในฟังก์ชัน ทั้งหมดมีข้อดีและข้อเสียที่คุณต้องชั่งน้ำหนักโดยขึ้นอยู่กับความต้องการของโค้ดของคุณ เช่น.:

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

โค้ดทำงานเหมือนกับโค้ดที่ไม่มีบัฟเฟอร์ด้านบน สังเกตว่า p ส่งคืนตำแหน่งเริ่มต้น ภายใน บัฟเฟอร์โดยที่ sz จำนวนบิตเริ่มต้นอย่างไร โปรดทราบว่าคุณจะต้องมีค่าคงที่สำหรับ BITS_PER_LONG ซึ่งแสดงถึงจำนวนบิตใน long บนฮาร์ดแวร์ของคุณ (ซึ่งปกติจะได้รับการจัดการในลักษณะคล้ายกับ BUILD_64)

หมายเหตุ: โปรดทราบว่าข้อจำกัดประการหนึ่งของการประกาศ static คือฟังก์ชันการแปลงสามารถใช้ได้เพียงครั้งเดียวในการเรียก printf หนึ่งครั้ง (หรือภายในโค้ดบรรทัดเดียว) เนื่องจากมีอาร์เรย์หน่วยเก็บข้อมูลเพียงชุดเดียวสำหรับ การแปลงไบนารี (คุณสามารถโทรออกกี่ครั้งก็ได้และจัดเก็บผลลัพธ์ไว้ในตำแหน่งต่างๆ ก่อนที่จะโทร printf)

รูปแบบสุดท้ายประการหนึ่งของการพิมพ์ไบนารี่คือการพิมพ์การแสดงด้วยตัวคั่นเพื่อให้ระบุและเปรียบเทียบระหว่างสตริงไบนารี่ได้ง่ายขึ้น (โดยเฉพาะเมื่อต้องจัดการกับลำดับที่ยาวกว่าของ 0's และ 1's เช่น:

hexval : 0xdeadbeef  =>  11011110-10101101-10111110-11101111

โดยพื้นฐานแล้วฟังก์ชันทำงานเหมือนกับ binpad ข้างต้น แต่ด้วยการเพิ่มบัฟเฟอร์แบบคงที่ที่มีขนาดใหญ่กว่าเพื่อรองรับตัวแยกและการตรวจสอบเพิ่มเติมเกี่ยวกับตำแหน่งบิตเพื่อพิจารณาว่าเมื่อใดควรเพิ่มตัวแยกลงในบัฟเฟอร์:

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

ปัญหาที่เหลือของคุณคือเพียงประมวลผลอาร์กิวเมนต์บรรทัดคำสั่ง และทำการแปลงจากสตริงอินพุตเป็นค่าที่ไม่ได้ลงนาม พร้อมกับตรวจสอบความถูกต้องว่าจำนวนไม่เกิน 32 บิต ฯลฯ คุณสามารถประมวลผลอาร์กิวเมนต์ด้วย getops หรือสำหรับตัวเลือกง่ายๆ จำนวนเล็กน้อย คุณสามารถใช้การวนซ้ำได้ บน Linux อาร์กิวเมนต์ที่จำเป็นเพียงอย่างเดียวที่โค้ดของคุณควรตอบสนองคือ -h สำหรับความช่วยเหลือและ -v สำหรับเวอร์ชัน แม้ว่าจะไม่มีใครทำสิ่งนี้เพื่อเป็นตัวอย่างสั้นๆ ฯลฯ แต่อย่างน้อยการมีข้อมูลนั้นก็ถือเป็นเรื่องดี ดูตัวอย่างต่อไปนี้ที่รวบรวมชิ้นส่วนทั้งหมดเข้าด้วยกัน และแจ้งให้เราทราบหากคุณมีคำถามใดๆ:

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

ใช้/ส่งออก

$ ./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

แต่ละ umber จะถูกจัดเก็บไว้ในเครื่องเป็นชุดของบิต หากต้องการพิมพ์ไปยังคอนโซล คุณจะต้องส่งสตริงที่อักขระแต่ละตัวเป็น 1 (0x31) หรือ 0 (0x30) ขึ้นอยู่กับว่าตั้งค่าตัวเลขบิตที่สอดคล้องกันหรือไม่ และอักขระตัวสุดท้ายต้องเป็น '\0' เพื่อแสดงถึงจุดสิ้นสุดของสตริง

หลังจากที่คุณเตรียมบัฟเฟอร์อักขระแล้ว การพิมพ์ลงบนคอนโซลสามารถทำได้โดยใช้เช่น fprintf:

fprintf(stdout, "%s\n", binaryNumber); // (maybe use stderr)

ด้วยการแก้ไขโค้ดของคุณเล็กน้อยเพื่อให้มั่นใจว่าสตริงถูกยกเลิก NULL (มี '\0' เป็นอักขระตัวสุดท้ายในบัฟเฟอร์) และคุณใส่อักขระลงในบัฟเฟอร์ (มิฉะนั้น 1 และ 0 ซึ่งไม่ใช่อักขระที่พิมพ์ได้จะถูกใส่ลงในบัฟเฟอร์ และคุณจะเห็น ไม่มีเอาต์พุตเลย):

void
hex_to_bin_print(unsigned long number)
{
    char binaryNumber[33];
    int i;
    for (i = 31; i >= 0; --i)
    {
        binaryNumber[i] = (number & 1) ? '1' : '0';
        number >>= 1;
    }
    binaryNumber[32] = '\0';
    fprintf(stdout, "Number %s\n", binaryNumber);
}

int main(void) {
    hex_to_bin_print(1);
    hex_to_bin_print(2);
    hex_to_bin_print(15);
    hex_to_bin_print(127);
    hex_to_bin_print(256);
    hex_to_bin_print(12345);
    return 0;
}

พิมพ์:

หมายเลข 00000000000000000000000000000001

หมายเลข 0000000000000000000000000000010

หมายเลข 00000000000000000000000000001111

หมายเลข 0000000000000000000000001111111

หมายเลข 00000000000000000000000100000000

หมายเลข 00000000000000000011000000111001

person 4pie0    schedule 19.02.2016
comment
จุดประสงค์ของ ? '1' : '0'; นั่นกำลังทำอะไรอยู่? - person DNH; 19.02.2016
comment
@DNH มิฉะนั้น 1 และ 0 ที่ไม่สามารถพิมพ์อักขระได้จะถูกใส่ลงในบัฟเฟอร์และคุณจะไม่เห็นผลลัพธ์เลย - คุณลองแล้วหรือยัง? - person 4pie0; 19.02.2016
comment
?: เป็นวิธีย่อในการทำคำสั่ง if สภาพ ? if_true : if_false. หากคุณต้องการ คุณสามารถใช้คำสั่ง if/else ปกติได้ หลายๆ คนชอบ ?: แต่ก็ไม่ได้สำคัญอะไรนัก - person ; 19.02.2016

ขั้นแรกให้คุณแปลงสตริงที่คุณได้รับจากบรรทัดคำสั่งเป็นจำนวนเต็ม วิธีที่ง่ายที่สุดคือใช้ sscanf

e.g.

if ( sscanf( argv[1], "%X", &n ) == 1)
{
  ...

ตอนนี้คุณมีค่าทศนิยม n

ในการแปลงเป็นไบนารี่ คุณจะต้องผ่านแต่ละบิตในจำนวนเต็มที่ไม่ได้ลงนาม

ด้วยการทำระดับบิตและด้วยค่าทศนิยม คุณสามารถตรวจสอบแต่ละบิตว่ามีการตั้งค่าและพิมพ์ '1' หรือ '0' ขึ้นอยู่กับบิต

for (int i = 0; i < 32; ++i)
{
   unsigned int mask = 0x8000 >> i; // this bit we check
   char ch = (n & mask) ? '1' : '0'; // see if it is set or not
   ...
}
person AndersK    schedule 19.02.2016

นี่เป็นวิธีหนึ่งที่โปรแกรมของคุณสามารถดูได้ ฉันได้แสดงความคิดเห็นบิตที่สำคัญแล้ว แต่คุณต้องดูเอกสารประกอบสำหรับฟังก์ชันที่ใช้งานอยู่ หากคุณใช้ linux (ดูเหมือนว่าคุณกำลังตัดสินจากคำถามเดิม) คุณสามารถใช้ "หน้าคู่มือ" ของ linux เช่น man sscanf เพื่อให้ข้อมูลทั้งหมดเกี่ยวกับ sscanf หรือฟังก์ชันอื่น ๆ ในไลบรารี C

คอมไพล์ด้วย: gcc main.c -o lab3

/* main.c */
#include <stdio.h> //provides putchar()
#include <strings.h> //provides sscanf() and strcmp()
#include <stdlib.h> //provides EXIT_x values

void printBits(unsigned long i)
{
  int j; //define a loop counter

  for(j = 0 ; j < 32 ; j++)
  {
    //test the highest bit and write a 1 or a 0
    //(we always test the highest bit but we shift the number along each time)
    putchar(i & 0x80000000 ? '1' : '0');

    //shift the bits along by one ready for the next loop iteration
    i <<= 1;

    //print a space after every 4th bit to break it up into nybbles
    if((j % 4) == 3)
      putchar(' ');
  }

  //finish the output in a tidy manner by writin a newline
  putchar('\n');
}


//a helpful function to assist the user
void usage(const char* progname)
{
  //show the user the proper way to run the program
  printf("%s -p 0x1234abcd\n", progname);
}

//this version of the main() signature gives access to commandline arguments
int main(int argc, char** argv)
{
  //flag to show the commandline arguments are in the wrong format
  int badargs = 0;

  //variable to store the 32 bit number given by the user
  unsigned long value;

  if(argc == 3) //do we have the right number of commandline arguments?
    if(strcmp(argv[1], "-p") == 0) //is argv[1] equal to "-p" ?
      if(sscanf(argv[2], "0x%x", &value) == 1) //is the number formatted like hex?
        printBits(value); //success, user input was good, print the bits!
      else
        badargs = 1; //the integer was not properly formatted as hexadecimal like 0x1234
    else
      badargs = 1; //argv[1] was not "-p"
  else
    badargs = 1; //wrong number of args given by user

  if(badargs) //we detected bad argument syntax earlier so we'd better remind the user what to do
  {
    printf("Incorrect argument syntax\n\n\t");
    usage(argv[0]); //argv[0] is the name of your executable program file ("lab3" in your case)
    putchar('\n');
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}

ฉันเขียนสิ่งนี้ด้วยตัวเอง แต่มีตัวอย่างมากมายของ "แบบฝึกหัดการสอน" ประเภทนี้บนเว็บ ดังนั้นฉันไม่คิดว่ามันเป็นการสปอยล์มากนักที่จะรวมโค้ดคำต่อคำไว้ที่นี่

person Community    schedule 19.02.2016