C ++ Чтение данных из текстового файла в массив структур - PullRequest
0 голосов
/ 05 ноября 2018

Я довольно новичок в программировании на C ++, и у меня возникли некоторые проблемы при чтении данных из текстового файла в массив структур. Я просмотрел похожие посты, чтобы попытаться найти решение, однако я не смог заставить его работать для меня и хотел попросить о помощи. Ниже приведен пример моего набора данных (P.S. Я буду использовать несколько наборов данных разных размеров):

00010 0
00011 1
00100 0
00101 1
00110 1
00111 0
01000 0
01001 1

Ниже мой код:

int variables = 5;

typedef struct {
    int variables[variables];
    int classification;
} myData;

//Get the number of rows in the file
int readData(string dataset)
{
    int numLines = 0;
    string line;
    ifstream dataFile(dataset);
    while (getline(dataFile, line))
    {
        ++numLines;
    }
    return numLines;
}

//Store data set into array of data structure
int storeData(string dataset)
{
    int numLines = readData(dataset);

    myData *dataArray = new myData[numLines];

    ...

    return 0;
}

int main()
{
    storeData("dataset.txt");

То, чего я пытаюсь добиться, - это сохранить первые 5 целых чисел каждой строки текстового файла в массиве «переменных» в структуре «myData», а затем сохранить последнее целое число, разделенное пробелом, в «классификации» переменной, а затем сохранить эту структуру в массиве dataArray, а затем перейти к следующей строке.

Например, первая структура в массиве будет иметь переменные [00010], а классификация будет равна 0. Вторая будет иметь переменные [00011], а классификация будет равна 1 и т. Д.

Я был бы очень признателен за помощь, ура!

Ответы [ 2 ]

0 голосов
/ 05 ноября 2018

Выглядит строка, в которой вы пытаетесь сохранить двоичные значения в виде целочисленного индекса. Если это так, он будет внутренне преобразован в целое число. Возможно, вам снова понадобится преобразование int в двоичное.

Если вы хотите сохранить данные как есть в текстовом файле, тогда вам нужно выбрать тип char / string для значения индекса. Для классификации кажется, что значение будет 0 или 1. Поэтому вы можете выбрать bool в качестве типа данных.

#include <iostream>
#include <map>

using namespace std;

std::map<string, bool> myData;

int main()
{
    // THIS IS SAMPLE INSERT. INTRODUCE LOOP FOR INSERT.
    /*00010 0
    00011 1
    00100 0
    00101 1
    00110 1*/
    myData.insert(std::pair<string, bool>("00010", 0));
    myData.insert(std::pair<string, bool>("00011", 1));
    myData.insert(std::pair<string, bool>("00100", 0));
    myData.insert(std::pair<string, bool>("00101", 1));
    myData.insert(std::pair<string, bool>("00110", 1));

    // Display contents
    std::cout << "My Data:\n";
    std::map<string, bool>::iterator it;

    for (it=myData.begin(); it!=myData.end(); ++it)
        std::cout << it->first << " => " << it->second << '\n';

    return 0;
} 
0 голосов
/ 05 ноября 2018

Укажите операторы извлечения и вставки потока для вашего типа:

#include <cstddef>    // std::size_t
#include <cstdlib>    // EXIT_FAILURE
#include <cctype>     // std::isspace(), std::isdigit()
#include <vector>     // std::vector<>
#include <iterator>   // std::istream_iterator<>, std::ostream_iterator<>
#include <fstream>    // std::ifstream
#include <iostream>   // std::cout, std::cerr, std::cin
#include <algorithm>  // std::copy()

constexpr std::size_t size{ 5 };

struct Data {
    int variables[size];
    int classification;
};

// stream extraction operator
std::istream& operator>>(std::istream &is, Data &data)
{
    Data temp;  // don't write directly to data since extraction might fail
               //  at any point which would leave data in an undefined state.

    int ch;  // signed integer because std::istream::peek() and ...get() return
            //  EOF when they encounter the end of the file which is usually -1.

                                                    // don't feed std::isspace
                                                   //  signed values
    while ((ch = is.peek()) != EOF && std::isspace(static_cast<unsigned>(ch)))
        is.get();  // read and discard whitespace

             // as long as
            //              +- we didn't read all variables
           //               |         +-- the input stream is in good state
          //                |         |      +-- and the character read is not EOF
         //                 |         |      |   
    for (std::size_t i{}; i < size && is && (ch = is.get()) != EOF; ++i)
        if (std::isdigit(static_cast<unsigned>(ch)))
            temp.variables[i] = ch - '0';  // if it is a digit, assign it to our temp
        else is.setstate(std::ios_base::failbit);  // else set the stream to a 
                                                  // failed state which will 
                                                 // cause the loop to end (is)

    if (!(is >> temp.classification))  // if extraction of the integer following the
        return is;                    // variables fails, exit.

    data = temp;  // everything fine, assign temp to data
    return is;
}

// stream insertion operator
std::ostream& operator<<(std::ostream &os, Data const &data)
{
    std::copy(std::begin(data.variables), std::end(data.variables),
              std::ostream_iterator<int>{ os });
    os << ' ' << data.classification;
    return os;

}

int main()
{
    char const *filename{ "test.txt" };
    std::ifstream is{ filename };

    if (!is.is_open()) {
        std::cerr << "Failed to open \"" << filename << "\" for reading :(\n\n";
        return EXIT_FAILURE;
    }

    // read from ifstream
    std::vector<Data> my_data{ std::istream_iterator<Data>{ is },
                               std::istream_iterator<Data>{} };

    // print to ostream
    std::copy(my_data.begin(), my_data.end(),
              std::ostream_iterator<Data>{ std::cout, "\n" });
}

Без комментариев выглядит менее страшно:

std::istream& operator>>(std::istream &is, Data &data)
{
    Data temp;
    int ch;

    while ((ch = is.peek()) != EOF && std::isspace(static_cast<unsigned>(ch)))
        is.get();

    for (std::size_t i{}; i < size && is && (ch = is.get()) != EOF; ++i)
        if (std::isdigit(static_cast<unsigned>(ch)))
            temp.variables[i] = ch - '0';
        else is.setstate(std::ios_base::failbit);

    if (!(is >> temp.classification))
        return is;

    data = temp;
    return is;
}

std::ostream& operator<<(std::ostream &os, Data const &data)
{
    std::copy(std::begin(data.variables), std::end(data.variables),
              std::ostream_iterator<int>{ os });
    os << ' ' << data.classification;
    return os;

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...