Преобразовать целое число в биты

У меня есть функция байта в двоичную строку,

std::string byte_to_binary(unsigned char byte)
{
    int x = 128;
    std::ostringstream oss;
    oss << ((byte & 255) != 0);

    for (int i = 0; i < 7; i++, x/=2)
       oss << ((byte & x) != 0);

    return oss.str();
}

Как я могу записать int в биты таким же образом? Мне не нужны дополнительные 0 в начале двоичной строки, поэтому я не могу понять, как каждый раз создавать переменную длину. Кроме того, я не использую std::bitset.


person parc65    schedule 18.05.2011    source источник
comment
Ну тогда вопрос, а почему вы не используете std::bitset?   -  person Xeo    schedule 18.05.2011
comment
Потому что я использую побитовые операторы.   -  person parc65    schedule 18.05.2011
comment
@parc: И bitset их перегружает. Следующая причина?   -  person Xeo    schedule 18.05.2011
comment
@parc: вы используете ostringstream и string, так что вы явно пишете код на C++. Используйте классы C++ для того, для чего они созданы. Следующая причина? :P Это может показаться немного резким, но позже вы будете благодарны.   -  person Xeo    schedule 18.05.2011
comment
Позже я преобразую их для использования массивов символов.   -  person parc65    schedule 18.05.2011
comment
@parc65 : Если вы хотите получить ответ C, вы должны явно указать это в своем вопросе и пометить вопрос c, а не c++.   -  person ildjarn    schedule 18.05.2011
comment
@parc: Почему вы так не хотите использовать std::bitset? Его можно построить даже из вашего byte!! (Возможно, вам придется следить за порядком байтов.)   -  person Xeo    schedule 18.05.2011
comment
Да, это может быть причиной того, что я не использую набор битов, потому что это мешает порядку байтов.   -  person parc65    schedule 18.05.2011
comment
@parc: Не ищи внезапно оправданий. Проверь это. Кроме того, я думаю, что мой предыдущий комментарий о порядке байтов мог быть ошибкой. Опять же, проверьте.   -  person Xeo    schedule 18.05.2011


Ответы (4)


Я просто опубликую это как ответ. Это короче, безопаснее и, что самое главное, выполнено.

#include <string>
#include <bitset>
#include <type_traits>

// SFINAE for safety. Sue me for putting it in a macro for brevity on the function
#define IS_INTEGRAL(T) typename std::enable_if< std::is_integral<T>::value >::type* = 0

template<class T>
std::string integral_to_binary_string(T byte, IS_INTEGRAL(T))
{
    std::bitset<sizeof(T) * CHAR_BIT> bs(byte);
    return bs.to_string();
}

int main(){
    unsigned char byte = 0x03; // 0000 0011
    std::cout << integral_to_binary_string(byte);
    std::cin.get();
}

Выход:

00000011

Изменено имя функции, хотя я не доволен этим... у кого-нибудь есть хорошая идея?

person Xeo    schedule 18.05.2011
comment
Спасибо, кстати, вы получили этот вывод из ОС с прямым порядком байтов или с прямым порядком байтов? - person parc65; 18.05.2011
comment
+1, если вы обобщаете это в шаблон функции, используя sizeof(T) в качестве аргумента шаблона для std::bitset<>, чтобы он работал с другими целочисленными типами. - person ildjarn; 18.05.2011
comment
@ildjarn: Готово, и благодаря вам я заметил ошибку ... один байт - это бит CHAR_BIT, а не 4 бита. :) - person Xeo; 18.05.2011
comment
@parc: Little-endian, как и большинство ОС на x86-64. Просмотрите список в Википедии. - person Xeo; 18.05.2011
comment
О, и я также добавил немного SFINAE для безопасности, в макросе для краткости. Подайте на меня в суд. :) - person Xeo; 18.05.2011
comment
Итак, порядок байтов вообще не влияет на порядок, может быть, я соглашусь с этим. - person parc65; 18.05.2011
comment
@parc: Да, кажется, bitset позаботится об этом. - person Xeo; 18.05.2011
comment
В этом SFINAE отсутствует ::type перед звездочкой. - person Cubbi; 18.05.2011
comment
Может быть, DecToBits или что-то в этом роде? - person parc65; 18.05.2011

Что-то вроде этого должно работать (хотя я быстро его взломал и не проверял):

#include <string>
#include <climits>

template<typename T>
std::string to_binary(T val)
{
  std::size_t sz = sizeof(val)*CHAR_BIT;
  std::string ret(sz, ' ');
  while( sz-- )
  {
    ret[sz] = '0'+(val&1);
    val >>= 1;
  }
  return ret;
}
person Pablo    schedule 18.05.2011
comment
Переносимый код должен использовать CHAR_BIT вместо жестко заданного 8 и хранить результат в std::size_t вместо int. - person ildjarn; 18.05.2011

Вы можете сделать это с помощью std:bitset и преобразовать любое число в битовую строку любого размера, например 64

#include <string>
#include <iostream>
#include <bitset>
using namespace std;

int main() {

 std::bitset<64> b(836); //convent number into bit array
 std::cout << "836 in binary is " <<  b << std::endl;

 //make it string
 string mystring = b.to_string<char,char_traits<char>,allocator<char> >();
 std::cout << "binary as string " << mystring << endl;
}
person shirvind    schedule 18.07.2013

Поскольку вы упомянули о своем желании использовать стиль C в комментариях, вы можете рассмотреть возможность использования itoa ( или _itoa) если вас не беспокоит стандарт ANSI-C. Многие компиляторы поддерживают его в stdlib.h. Он также удаляет ведущие 0:

unsigned char yourGoldenNumber = 42;
char binCode[64];
itoa(yourGoldenNumber,binCode,2); // third parameter is the radix
puts(binCode); // 101010
person Jan Turoň    schedule 08.12.2014