2010-02-02 3 views
4

Я хотел бы иметь возможность вводить символ с клавиатуры и отображать двоичный код для указанного ключа в формате 00000001, например.Чтение символов на уровне бит

Кроме того, я также хотел бы прочитать бит таким образом, чтобы я мог выводить, если они являются истинными или ложными.

например.

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

Я вывесил бы представление о том, как я пытался сделать это сам, но я не имею ни малейшего представления, я все еще экспериментировать с C, и это мой первый вкус программирования на таком масштабе низкого уровня.

Thankyou

+0

Вы хотите, чтобы это было на C или на C#? Тег .net3-5, который вы положили, будет означать C#, но вы также ставите тег C, который является непоследовательным. –

+0

oops sorry, я имею в виду C. –

+0

Это было весело! –

ответ

3

Этот код 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; 
} 

Вам не обязательно нужны три петли - вы могли бы объединить их вместе, если вы хотите, и если вы только делаете один из двух видов продукции, то вам не понадобится массив, вы можете просто использовать каждое значение бита, когда вы его замаскируете. Но я думаю, что это держит вещи раздельными и, надеюсь, легче понять.

+0

+1 для подробного примера, который заставил меня удалить мою собственную. Любой другой (если только не упрямый или глупый) не должен делать то же самое;) –

+0

Очень тщательный, к сожалению, при вставке в пустой исходный файл мне предъявлено 45 ошибок, в основном синтаксические ошибки и необъявленные идентификаторы. –

+0

Какой компилятор вы используете? –

4

Это, вероятно, не самый безопасный способ - не здравомыслие/размер/тип проверки - но он должен работать.

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) - для персонажа.

+0

Возможно, нужно скопировать круглые скобки (1 << i)? –

+0

Отредактировано - но вы можете проверить его, потому что мой C не такой сильный, как мой C++. – acron

+0

Если вы хотите, чтобы scanf читал число, попробуйте% d –

4

Для настройки битов часто бывает безопаснее использовать неподписанные типы, потому что сдвиги подписанных отрицательных значений имеют эффект, зависящий от реализации. Простой char может быть либо подписанным, либо беззнаковым (традиционно он не подписан на платформах MacIntosh, но подписан на ПК). Следовательно, сначала введите персонажа в тип 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, unsigned char имеет , по меньшей мере восемь бит, но могут иметь более (в настоящее время, только несколько встроенных DSP есть символы, которые не являются 8-бит). Для большей безопасности, добавьте это ближе к началу коды (как декларация верхнего уровня):

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

Это предотвратит успешную компиляцию, если целевая система, случается, один из тех специальных встроенных DSP. В примечании к примечанию термин «байт» в стандарте C означает «элементарный блок памяти, который соответствует unsigned char», так что в C-talk байт может иметь более восьми бит (байт не является всегда октет). Это традиционный источник путаницы.

+0

+1, некоторые хорошие подсказки там. –

Смежные вопросы