Я бы опубликовал идею того, как я пытался сделать это сам, но я понятия не имею, я все еще экспериментирую с C, и это мой первый опыт программирования на таком низком уровне.
Спасибо
Вы хотите это на C или на C#? Тег .net3-5, который вы поместили, будет означать C#, но вы также поместите тег C, который несовместим. Marcel Gosselin 02.02.2010
Это было веселое упражнение! Aiden Bell 02.02.2010
/* 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
Для настройки битов часто безопаснее использовать типы без знака, потому что сдвиги отрицательных значений со знаком имеют эффект, зависящий от реализации. Обычный 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, байт может иметь более восьми битов (байт не является всегда октет). Это традиционный источник путаницы.
Ответ 3 · рейтинг 4 · Antony Woods
Это, вероятно, не самый безопасный способ - никаких проверок работоспособности/размера/типа - но он все равно должен работать.
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 (истина или ложь) - для символа.