Поскольку требование любой длины не применяется (замечено в комментариях), вот мое мнение о нем.Это шаблон класса (binreader<T>
), где T
- это числовой тип, который вы хотите извлечь из файла, например uint32_t
(или int32_t
для значений со знаком).
binreader.hpp
#ifndef binreader_hpp_8ac51dd6_fe5f_11e8_a64e_90b11c0c0ff8
#define binreader_hpp_8ac51dd6_fe5f_11e8_a64e_90b11c0c0ff8
#include <iostream>
#include <string>
#include <climits>
#include <stdexcept>
// class template to read a line from a stream as a binary value and convert it
// to a user supplied type
template<typename T>
class binreader {
T m_value; // the extracted value
public:
// the number of bits in the type
static constexpr size_t bits = sizeof(T)*CHAR_BIT;
binreader() : m_value(0) {} // default constructor
// input stream operator for reading a line
friend std::istream& operator>>(std::istream& is, binreader& br) {
std::string line;
if(std::getline(is, line)) {
T rv = 0; // the variable we'll populate with the extracted bits
size_t bitcount=0; // overflow guard
// loop through all characters in the line
for(auto ch : line) {
// just discard anything not '0' or '1'
if(ch!='0' && ch!='1') continue;
// check if we've already extracted the max number of bits
if(++bitcount > bits)
throw std::overflow_error(
"Too many bits (>"+std::to_string(bits)+") for binreader type"
);
// store the extracted bit
rv <<= 1; // shift up 1 step
rv |= (ch-'0'); // OR the found 0 or 1
}
// a successful read, set the value of this binreader
br.m_value = rv;
} // else is.failbit will be set and the outer loop will stop
return is;
}
// an output stream operator to print a binreader value
friend std::ostream& operator<<(std::ostream& os, const binreader& br) {
os << br.m_value;
return os;
}
// conversion to T for convenience
operator T () const { return m_value; }
};
#endif
Пример использования:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include "binreader.hpp"
// a test function template to open a file, extract and store the values
// in a std::vector<T> that will be returned to the caller
template<typename T>
std::vector<T> trytype(const std::string& filename) {
std::vector<T> rv;
// open file
std::ifstream fi(filename);
if(fi) { // opened successfully?
// declare a binreader variable of a wanted type
// suitable to fit the binary numbers in the file
binreader<T> value;
std::cout << "Reading at most " << value.bits << " bits\n";
try {
// extract the value on one line
while(fi >> value) {
// store the value to return using the
// conversion operator T ()
rv.push_back(value);
}
} catch(const std::exception& ex) {
std::clog << " ERROR: " << ex.what() << "\n";
}
}
return rv;
}
// function template to display values in a container
// (a std::vector<T> that is returned from trytype<T>)
template<typename C>
void display(const C& extracted_values) {
std::cout << " Extracted values:\n";
for(auto v : extracted_values) {
std::cout << " " << v << "\n";
}
}
int main(int argc, char* argv[]) {
// make a vector of all the command line arguments
std::vector<std::string> args(argv+1, argv+argc);
// open all files given as command line arguments and
// try to extract binary values using different types
// and call display() to print the values
for(const auto& file : args) {
display( trytype<uint64_t>(file) );
display( trytype<int64_t>(file) );
display( trytype<uint32_t>(file) );
display( trytype<int32_t>(file) );
display( trytype<uint16_t>(file) );
display( trytype<int16_t>(file) );
display( trytype<uint8_t>(file) );
display( trytype<int8_t>(file) );
}
}
Файл примера:
0; 1; 1; 0;
1; 1; 1; 0; 1; 0; 1; 1;
1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1;
1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1;
1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1; 1; 1; 1; 0; 1; 0; 1; 1;
Пример вывода:
Reading at most 64 bits
Extracted values:
6
235
60395
3958107115
16999940616948018155
Reading at most 64 bits
Extracted values:
6
235
60395
3958107115
-1446803456761533461
Reading at most 32 bits
ERROR: Too many bits (>32) for binreader type
Extracted values:
6
235
60395
3958107115
Reading at most 32 bits
ERROR: Too many bits (>32) for binreader type
Extracted values:
6
235
60395
-336860181
Reading at most 16 bits
ERROR: Too many bits (>16) for binreader type
Extracted values:
6
235
60395
Reading at most 16 bits
ERROR: Too many bits (>16) for binreader type
Extracted values:
6
235
-5141
Reading at most 8 bits
ERROR: Too many bits (>8) for binreader type
Extracted values:
▒
Reading at most 8 bits
ERROR: Too many bits (>8) for binreader type
Extracted values:
▒
Обратите внимание, что 8-битные типы будут печатать символы вместо цифр, но они также действительны для арифметических операций.static_cast
к большему типу для отображения их значений.