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

C++ Reading data from text file into array of structures

本文关键字:读取 结构 数组 数据 文本 文件 C++      更新时间:2023-10-16

我对C++编程相当陌生,在将文本文件中的数据读取到结构数组中时遇到了一些问题。我四处寻找类似的帖子,试图找到一个解决方案,但我无法让任何一个对我有效,我想寻求一些帮助。以下是我的数据集示例(附言:我将使用多个不同大小的数据集(:

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"结构中的"variables"数组中,然后将最后一个用空格分隔的整数存储到"classification"变量中,再将该结构存储到数组"dataArray"中,然后移到下一行。

例如,数组中的第一个结构将具有变量[00010],并且分类将为0。第二个将有变量[00011],分类将为1,依此类推

我真的很感谢你的帮助,干杯!

为您的类型提供流提取和流插入运算符:

#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 :(nn";
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;
}

您试图将二进制值保留为整数索引,这看起来很不错。如果是这种情况,它将在内部转换为整数。您可能需要再次进行int到二进制的转换。

如果要在文本文件中保持数据原样,则需要为索引值选择字符/字符串类型。对于分类,其值似乎是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;
}