简体   繁体   English

C++ 将文本文件中的数据读入结构数组

[英]C++ Reading data from text file into array of structures

I am reasonably new to programming in C++ and i'm having some trouble reading data from a text file into an array of structures.我对 C++ 编程相当陌生,并且在将文本文件中的数据读取到结构数组中时遇到了一些问题。 I have looked around similar posts to try and find a solution however, I have been unable to make any of it work for me and wanted to ask for some help.我环顾了类似的帖子以尝试找到解决方案,但是,我无法使其中的任何一个对我有用,并想寻求一些帮助。 Below is an example of my data set (PS I will be using multiple data sets of varying sizes):以下是我的数据集示例(PS 我将使用多个不同大小的数据集):

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

Below is my code:下面是我的代码:

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");

What I am trying to achieve is to store the first 5 integers of each row of the text file into the 'variables' array in the 'myData' structure and then store the last integer separated by white space into the 'classification' variable and then store that structure into the array 'dataArray' and then move onto the next row.我想要实现的是将文本文件每行的前 5 个整数存储到 'myData' 结构中的 'variables' 数组中,然后将用空格分隔的最后一个整数存储到 'classification' 变量中,然后将该结构存储到数组“dataArray”中,然后移动到下一行。

For example, the first structure in the array will have the variables [00010] and the classification will be 0. The second will have the variables [00011] and the classification will be 1, and so on.例如,数组中的第一个结构将具有变量 [00010],分类为 0。第二个结构将具有变量 [00011],分类为 1,依此类推。

I would really appreciate some help with this, cheers!我真的很感激这方面的帮助,干杯!

Provide stream extraction and stream insertion operators for your type:为您的类型提供流提取和流插入运算符:

#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" });
}

Uncommented it looks less scary:取消注释它看起来不那么可怕:

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;

}

It looks line you are trying to keep binary values as integer index.看起来您正试图将二进制值保留为整数索引。 If that is the case, it will be converted into integer internally.如果是这种情况,它将在内部转换为整数。 You may need int to binary conversion again.您可能需要再次将 int 转换为二进制。

If you want to preserve data as is in the text file, then you need to choose either char/string type for the index value.如果要按文本文件中的原样保留数据,则需要为索引值选择字符/字符串类型。 For classification, it seems value will be either 0 or 1. So you can choose bool as data type.对于分类,值似乎是 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;
} 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM