Итак, вопрос:
В переменной типа string записан кусок двоичного кода. Требуется: записать код в фаил в битовом виде, т.е. чтобы фаил, в который, например, записали код длиной 24 бита, весил соответственно 3 байта(24 бита).

Запись в фаил типа:
ofstream out("output.txt");
out << line;
естественно даст результат не 3 байта, а 24!
bitset<n> дает такой же результат.
В java это реализованно:
bos = new BitOutputStream(fis); // fis — fileInputStream...
bos.writeBit(((int)mas[a].charAt(i))-48);
а как в С++.
Очень важно, очень срочно.
Спасибо заранее.
18.10.06 18:06: Перенесено модератором из 'Алгоритмы' — Кодт
Здравствуйте, mxc, Вы писали:
mxc>Итак, вопрос:
mxc>В переменной типа string записан кусок двоичного кода. Требуется: записать код в фаил в битовом виде, т.е. чтобы фаил, в который, например, записали код длиной 24 бита, весил соответственно 3 байта(24 бита).
Запись в фаил типа:
mxc> ofstream out("output.txt");
mxc> out << line;
mxc>естественно даст результат не 3 байта, а 24!
1. Файл-поток нужно открывать в двоичном режиме
ofstream out("output.txt", ios::binary);
Нужно использовать метод write() потока...
Примерно так:
1. скопировать буфер строки в массив типа char — метод есть, не помню какой
2. out.wrate(buffer, sizeof(beffer));
можно и прямо из стринга писать, но нужно метод для доступа к буферу использовать — не помню какой...
Здравствуйте, mxc, Вы писали:
mxc>Итак, вопрос:
mxc>В переменной типа string записан кусок двоичного кода. Требуется: записать код в фаил в битовом виде, т.е. чтобы фаил, в который, например, записали код длиной 24 бита, весил соответственно 3 байта(24 бита).
Запись в фаил типа:
mxc> ofstream out("output.txt");
mxc> out << line;
mxc>естественно даст результат не 3 байта, а 24!
mxc>bitset<n> дает такой же результат.
mxc>В java это реализованно:
mxc> bos = new BitOutputStream(fis); // fis — fileInputStream...
mxc> bos.writeBit(((int)mas[a].charAt(i))-48);
mxc>а как в С++.
mxc>Очень важно, очень срочно.
mxc>Спасибо заранее.
А ручками реальзовать не быстрее будет, вместо того, чтобы искать готовое?
Режешь на кусочки по 8 потом битовой арифметикой формируешь байтики и пишешь уже их:
char *a = '0101010101001010010101001';
byte x = 0;
for (int i=0; i<strlen(a); i++) {
x = x || ((a[i]-48)<<(7-(i&7)));
if ((i&7)==7) {
// write x here to some place
cout << x;
x = 0;
}
}
if (strlen(a)%8) {
// there is a tail...
// write x here to some place
cout << x;
}
Кажется так.
Здравствуйте, mxc, Вы писали:
mxc>а как в С++.
посмотрите в сторону
strtol. Почти готовое решение, остается обработать напильником
Здравствуйте, mxc, Вы писали:
mxc>Очень важно, очень срочно.
Например, можно так:
#include <string>
#include <iostream>
#include <iterator>
/// declaration for binary packing type
template
<
typename CharType,
typename IterType
>
class BinaryPackingType
{
/// declaration for begin iterator data member
const IterType Begin_;
/// declaration for end iterator data member
const IterType End_;
public:
/// declaration for constructor
explicit BinaryPackingType (IterType Begin,
IterType End) : Begin_ (Begin), End_ (End) {}
/// declaration for packing function
template
<
typename CharTraits
>
void Packing (std::basic_ostream <CharType,
CharTraits> & Stream) const
{
/// declaration for char
char Char (0);
/// declaration for nought
const CharType Nought (Stream.widen ('0'));
for (IterType Iter (Begin_), End (Iter);
!Stream.fail () && (Iter != End_);)
{
/// initialize char
Char = 0;
/// initialize end
std::advance (End, CHAR_BIT);
/// calculate char
for (; Iter != End; ++ Iter)
{
/// move one bit to the left
Char <<= 1;
/// check one value
if (Nought != * Iter) /// operator * return CharType
{
Char |= unsigned (1);
}
}
/// put char
static_cast <void> (Stream.put
(static_cast <CharType> (Char)));
}
}
};
/// declaration for << operator
template
<
typename CharType,
typename CharTraits,
typename IterType
>
std::basic_ostream <CharType, CharTraits> & operator << (std::basic_ostream
<CharType, CharTraits> & Stream, const BinaryPackingType <CharType, IterType> & BinaryPacking)
{
BinaryPacking.Packing (Stream);
return Stream;
}
/// declaration for binary packing function
template
<
typename CharType
>
const BinaryPackingType <CharType, const CharType *> BinaryPacking
(const CharType * String)
{
/// typedef for char traits
typedef std::char_traits <CharType> CharTraits;
return BinaryPackingType <CharType, const CharType *>
(String, String + CharTraits::length (String));
}
/// declaration for binary packing function
template
<
typename CharType,
typename CharTraits
>
const BinaryPackingType <CharType, const CharType *> BinaryPacking
(const CharType * String)
{
return BinaryPackingType <CharType, const CharType *>
(String, String + CharTraits::length (String));
}
/// declaration for binary packing function
template
<
typename CharType,
typename CharTraits,
typename AllocatorType
>
const BinaryPackingType <CharType, typename std::basic_string <CharType,
CharTraits, AllocatorType>::const_iterator> BinaryPacking (const std::basic_string
<CharType, CharTraits, AllocatorType> & String)
{
return BinaryPackingType <CharType, typename std::basic_string
<CharType, CharTraits, AllocatorType>::const_iterator> (String.begin (),
String.end ());
}
/// declaration for binary extract type
template
<
typename CharType,
typename IterType
>
class BinaryExtractType
{
/// declaration for iterator data member
const IterType Iter_;
public:
/// declaration for constructor
explicit BinaryExtractType (IterType Iter) : Iter_
(Iter) {}
/// declaration for extract function
template
<
typename CharTraits
>
void Extract (std::basic_istream <CharType,
CharTraits> & Stream) const
{
/// declaration for index
int Index (0);
/// declaration for char
CharType Char (0);
/// declaration for iterator
IterType Iter (Iter_);
/// declaration for unity
const CharType Unity (Stream.widen ('1'));
/// declaration for nought
const CharType Nought (Stream.widen ('0'));
for (; Stream.get (Char);)
{
/// calculate char
for (Index = CHAR_BIT - 1;
-1 != Index; -- Index, ++ Iter)
{
if ((static_cast <char> (Char) >> Index) & unsigned (1))
{
* Iter = Unity;
}
else
{
* Iter = Nought;
}
}
}
}
};
/// declaration for >> operator
template
<
typename CharType,
typename CharTraits,
typename IterType
>
std::basic_istream <CharType, CharTraits> & operator >> (std::basic_istream
<CharType, CharTraits> & Stream, const BinaryExtractType <CharType, IterType> & BinaryExtract)
{
BinaryExtract.Extract (Stream);
return Stream;
}
/// declaration for binary extract function
template
<
typename IterType
>
const BinaryExtractType <typename std::iterator_traits
<IterType>::value_type, IterType> BinaryExtract (IterType Iter)
{
return BinaryExtractType <typename std::iterator_traits
<IterType>::value_type, IterType> (Iter);
}
Далее использование:
#include <string>
#include <fstream>
#include <iterator>
int main ()
{
std::wofstream OutputStream ("out.bin",
std::ios_base::binary | std::ios_base::out);
OutputStream << BinaryPacking (L"0000000100000011") << std::flush;
std::wifstream InputStream ("out.bin",
std::ios_base::binary | std::ios_base::in);
std::wifstream::pos_type Size (0);
if (InputStream.seekg (0, std::ios_base::end))
{
Size = InputStream.tellg ();
}
if (0 != Size && InputStream.seekg (0,
std::ios_base::beg))
{
std::wstring String (CHAR_BIT * Size, L'Q');
InputStream >> BinaryExtract (String.begin ());
}
return 0;
}
Есть и несколько проблем. Пришлось писать:
std::wstring String (CHAR_BIT * Size, L'Q');
InputStream >> BinaryExtract (String.begin ());
, вместо красивого использования
back_insert_iterator — а и
basic_string::reserve. Дело в том, что
back_insert_iterator —
output_iterator и для него
value_type определен как
void (непонятно почему), поэтому при использовании такого итератора все падает на этапе компиляции.
value_type необходим для вычисления
CharType в параметрах шаблона
BinaryExtractType и
BinaryPackingType (для связки итератор и символ);
BinaryPackingType не занимается валидацией данных и изначально предполагает, что строка имеет правильный формат (содержит нули и единицы, длина строки кратна
CHAR_BIT);
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>