Запись нулей и единиц в фаил(С++)
От: mxc  
Дата: 17.10.06 21:12
Оценка:
Итак, вопрос:
В переменной типа 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: Перенесено модератором из 'Алгоритмы' — Кодт
Re: Запись нулей и единиц в фаил(С++)
От: LaptevVV Россия  
Дата: 18.10.06 08:07
Оценка:
Здравствуйте, 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));

можно и прямо из стринга писать, но нужно метод для доступа к буферу использовать — не помню какой...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Запись нулей и единиц в фаил(С++)
От: Au1  
Дата: 18.10.06 08:51
Оценка:
Здравствуйте, 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;  
}


Кажется так.
Re: Запись нулей и единиц в фаил(С++)
От: Alexey Frolov Беларусь  
Дата: 20.10.06 13:19
Оценка:
Здравствуйте, mxc, Вы писали:

mxc>а как в С++.


посмотрите в сторону strtol. Почти готовое решение, остается обработать напильником
Решение, которое будет благодарно за любую критику
От: np9mi7 Россия  
Дата: 23.10.06 06:04
Оценка:
Здравствуйте, 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_iteratoroutput_iterator и для него value_type определен как void (непонятно почему), поэтому при использовании такого итератора все падает на этапе компиляции. value_type необходим для вычисления CharType в параметрах шаблона BinaryExtractType и BinaryPackingType (для связки итератор и символ);

BinaryPackingType не занимается валидацией данных и изначально предполагает, что строка имеет правильный формат (содержит нули и единицы, длина строки кратна CHAR_BIT);
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
"В любое мгновение принятия решения, лучшее, что вы можете сделать, это принять правильное решение; следующим лучшим вариантом будет принять неправильное решение, худший вариант – не принимать решения совсем" (c) Теодор Рузвельт.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.