Отдельные целые из файла, разделенного точкой с запятой на разные цифры в C ++ - PullRequest
0 голосов
/ 12 декабря 2018

Мне нужно получить данные из файла.Этим вводом является любое двоичное число любой длины, где цифры разделяются точкой с запятой, например:

0;1;1;0;1;0;

Что бы я сделал, это передал бы файл в переменную типа

if (myfile.is_open())
{
    while ( getline (myfile,line) )
    {
        File = line;
    }
    myfile.close();
}

Но я не уверен, какой тип данных я бы сделал переменной File,После этого мне придется хранить цифры в array или vector.

Ответы [ 2 ]

0 голосов
/ 12 декабря 2018

Поскольку требование любой длины не применяется (замечено в комментариях), вот мое мнение о нем.Это шаблон класса (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 к большему типу для отображения их значений.

0 голосов
/ 12 декабря 2018

По сути, вам нужно разделить string на разделитель (в вашем случае разделитель равен "; ").Это можно сделать с помощью метода std::string::find, который возвращает индекс искомого символа / строки, и метода std::string::substr, который возвращает подстроку на основе предоставленного индекса начала (полученного из find) и количества символов для чтения (мы читаем только 0 или 1, поэтому длина всегда будет 1).После того, как вы извлечете желаемую подстроку, вы можете преобразовать ее в тип данных, который соответствует вашим потребностям.

Ниже приведен простой пример того, как создать vector из bool на основе таких string:

#include <string>
#include <vector>
#include <iostream>

int main()
{
    std::string line = "0; 1; 1; 0; 1; 0; "; // In your case, 'line' will contain getline() result
    std::vector<bool> bits;
    std::size_t lastPos = 0;

    if(!line.empty()) bits.push_back(line.substr(0, 1) == "1");

    while((lastPos = line.find("; ", lastPos)) != std::string::npos)
    {
        lastPos += 2; // +2 because we don't want to read delimiter
        if(lastPos < line.size()) bits.push_back(line.substr(lastPos, 1) == "1");
    }

    for(auto bit : bits)
    {
        std::cout << bit << "\n";
    }
}

Вывод:

0
1
1
0
1
0
...