代码之家  ›  专栏  ›  技术社区  ›  Jamie Keeling

在位级别上读取字符

  •  4
  • Jamie Keeling  · 技术社区  · 14 年前

    我希望能够从键盘输入一个字符,并以00000001格式显示所述键的二进制代码。

    此外,我还希望以一种允许我输出的方式读取位,如果它们是真的或假的。

    例如

    01010101 = false,true,false,true,false,true,false,true
    

    我会发表一个我自己尝试过的想法,但是我完全不知道,我仍然在用C进行试验,这是我第一次尝试在如此低的水平上编程。

    谢谢你

    3 回复  |  直到 14 年前
        1
  •  3
  •   Steve Jessop    14 年前

    此代码是C89:

    /* we need this to use exit */
    #include <stdlib.h>
    /* we need this to use CHAR_BIT */
    #include <limits.h>
    /* we need this to use fgetc and printf */
    #include <stdio.h>
    
    int main() {
        /* Declare everything we need */
        int input, index;
        unsigned int mask;
        char inputchar;
    
        /* an array to store integers telling us the values of the individual bits.
           There are (almost) always 8 bits in a char, but it doesn't hurt to get into
           good habits early, and in C, the sizes of the basic types are different
           on different platforms. CHAR_BIT tells us the number of bits in a byte. 
         */
        int bits[CHAR_BIT];
    
        /* the simplest way to read a single character is fgetc, but note that
           the user will probably have to press "return", since input is generally 
           buffered */
        input = fgetc(stdin);
        printf("%d\n", input);
    
        /* Check for errors. In C, we must always check for errors */
        if (input == EOF) {
            printf("No character read\n");
            exit(1);
        }
    
        /* convert the value read from type int to type char. Not strictly needed,
           we can examine the bits of an int or a char, but here's how it's done. 
         */
        inputchar = input;
    
        /* the most common way to examine individual bits in a value is to use a 
           "mask" - in this case we have just 1 bit set, the most significant bit
           of a char. */
        mask = 1 << (CHAR_BIT - 1);
    
        /* this is a loop, index takes each value from 0 to CHAR_BIT-1 in turn,
           and we will read the bits from most significant to least significant. */
        for (index = 0; index < CHAR_BIT; ++index) {
            /* the bitwise-and operator & is how we use the mask.
               "inputchar & mask" will be 0 if the bit corresponding to the mask
               is 0, and non-zero if the bit is 1. ?: is the ternary conditional
               operator, and in C when you use an integer value in a boolean context,
               non-zero values are true. So we're converting any non-zero value to 1. 
             */
            bits[index] = (inputchar & mask) ? 1 : 0;
    
            /* output what we've done */
            printf("index %d, value %u\n", index, inputchar & mask);
    
            /* we need a new mask for the next bit */
            mask = mask >> 1;
        }
    
        /* output each bit as 0 or 1 */
        for (index = 0; index < CHAR_BIT; ++index) {
            printf("%d", bits[index]);
        }
        printf("\n");
    
        /* output each bit as "true" or "false" */
        for (index = 0; index < CHAR_BIT; ++index) {
            printf(bits[index] ? "true" : "false");
            /* fiddly part - we want a comma between each bit, but not at the end */
            if (index != CHAR_BIT - 1) printf(",");
        }
        printf("\n");
        return 0;
    }
    

    您不一定需要三个循环—如果需要,可以将它们组合在一起,如果只进行这两种输出中的一种,那么就不需要数组,只需在屏蔽时使用每个位值。但我认为这会使事情分开,希望更容易理解。

        2
  •  4
  •   Thomas Pornin    14 年前

    对于位调整,使用无符号类型通常更安全,因为有符号负值的移动具有依赖于实现的效果。平原 char 可以是签名的,也可以是未签名的(传统上,它在Macintosh平台上是未签名的,但在PC上是签名的)。因此,首先将你的角色投射到 unsigned char 类型。

    那么,你的朋友就是位布尔运算符( & , | , ^ ~ )轮班操作员( << >> )例如,如果您的角色在变量中 x ,然后要得到第5位,只需使用: ((x >> 5) & 1) . 移位运算符将值向右移动,将五个较低的位丢弃,并将您感兴趣的位移动到“最低位置”(也称为“最右边”)。按位与1简单地将所有其他位设置为0,因此结果值为0或1,即您的位。请注意,我从左有效(最右边)到最有效(最左边)对位进行编号,并且以零开始,而不是一。

    如果您假设您的字符是8位,则可以将代码编写为:

    unsigned char x = (unsigned char)your_character;
    int i;
    
    for (i = 7; i >= 0; i --) {
        if (i != 7)
            printf(",");
        printf("%s", ((x >> i) & 1) ? "true" : "false");
    }
    

    您可能会注意到,由于我从右到左对位进行编号,但您希望从左到右输出,所以循环索引必须减少。

    注意,根据C标准, 无符号字符 至少 8位,但可能有更多(现在,只有少数嵌入式DSP的字符不是8位)。为了更加安全,在代码的开头添加这个(作为顶级声明):

    #include <limits.h>
    #if CHAR_BIT != 8
    #error I need 8-bit bytes!
    #endif
    

    如果目标系统恰好是那些特殊的嵌入式DSP之一,这将阻止成功编译。作为注释上的注释,C标准中的“字节”一词表示“与 无符号字符 “,这样,在C语言中,一个字节可能有八个以上的位(一个字节并不总是八位字节)。这是一个传统的困惑源。

        3
  •  4
  •   Antony Woods    14 年前

    这可能不是最安全的方法-没有健全/大小/类型检查-但它应该仍然有效。

    unsigned char myBools[8];
    char myChar;  
    
    // get your character - this is not safe and you should
    // use a better method to obtain input...
    // cin >> myChar; <- C++
    scanf("%c", &myChar);
    
    // binary AND against each bit in the char and then
    // cast the result. anything > 0 should resolve to 'true'
    // and == 0 to 'false', but you could add a '> 1' check to be sure.
    for(int i = 0; i < 8; ++i)
    {
       myBools[i] = ( (myChar & (1 << i) > 0) ? 1 : 0 );
    }
    

    这将为字符提供一个无符号字符数组(0或1(true或false))。