#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
string trimmed(string& input)
{
size_t firstNonWSIdx = input.find_first_not_of(" ");
size_t lastNonWSIdx = input.find_last_not_of(" ");
firstNonWSIdx = (firstNonWSIdx == string::npos ? 0 : firstNonWSIdx);
return input.substr(firstNonWSIdx, lastNonWSIdx);
}
void resetStrStream(istringstream& sstr, string const& newInput)
{
sstr.clear();
sstr.str(newInput);
}
void readFile(char const* fileName, vector<vector<float> >& data)
{
ifstream infile(fileName);
string input;
istringstream iss;
while(infile)
{
getline(infile, input);
string token = trimmed(input);
if (token.compare("setOfElements") == 0)
{
getline(infile, input);
resetStrStream(iss, trimmed(input));
int arraySize;
iss >> arraySize;
vector<float> values;
int i = 0;
while(i++ < arraySize)
{
getline(infile, input);
resetStrStream(iss, trimmed(input));
float val;
while (iss >> val)
{
values.push_back(val);
}
}
data.push_back(values);
}
}
}
void testData(vector<vector<float> >& data)
{
for (int i = 0; i < data.size(); i++)
{
for (int j = 0; j < data[i].size(); j++)
{
cout << data[i][j] << " ";
}
cout << endl;
}
}
int main()
{
vector< vector<float> > data;
readFile("textfile.txt", data);
testData(data);
return 0;
}
Read text file between specific lines of text in c++
Вопрос
I am currently working on parsing a file into program memory.
The file to parse looks like this:
file info
second line of file info
date
# col1 col2 col3 col4 col5 col6 col7 col8 col9 col10 col11 col12 col13 col14
firstSetOfElements
4
2 1 1 0 3 1 2 3 0 -49.4377 0 0 -26.9356 -24.5221
3 2 1 0 3 2 4 3 13.7527 -43.2619 0 0 -19.3462 -28.0525
4 3 1 0 3 4 1 3 14.2459 43.5163 0 0 33.3506 15.2988
5 4 1 0 3 2 1 4 49.4377 0 0 0 25.0818 38.3082
# col1 col2 col3 col4 col5 col6
secondSetOfElements
1
1 4 3 4 1 2
What I am trying to do:
file.open(FILENAME, ios::in); // Open file
if (file.is_open())
{
// Get the line number where "firstSetOfElements" is located. Store the line number.
// Go to the line after that line, and store the integer listed there as a variable (`int noFirstElems`).
// (this is the number of rows I will be parsing into the first array).
// start parsing at the first line of the array (the line under the previous)
while (getline(file, firstLineOfFirstSetToParse)) //starting at the first row of data array elements, begin parsing into text file (this I've got handled).
{
//add a row vector until you get to a blank line (which will be after 4 rows of data).
}
After doing this for the "firstSetOfElements" array, I will then do the same thing to parse the "secondSetOfElements" data into an array, as above.
I have parsed the data just fine, but have not found a resource I can understand for setting begin/end points for the lines I am to parse.
Thanks in advance!
Решение
Другие советы
The problem based on the way you have described is straightforward to solve: read line by line, scan for a token named "SetOfElements" and treat the next line as the size of your 2D-array, and then read size
number of lines and store them into your array.
But, your file's layout is confusing: your comment line (starting with #) says there are going to be 8 columns, but subsequent lines contain 14 columns. Is your program supposed to ignore the last 6 columns? Also, your elements seem to be mixture of ints and floats, unless the columns 1 through 8 are also floats that don't have a fractional part.
If in fact, the data-type is mixed, and columns 1-8 have to read as ints and the remaining as floats, then your parser code is going to be complex otherwise, it should be simple getline... scan line... continue
kind of algorithm.
Also, do your set delimiters change? The first set is identified by "firstSetOfElements" and the second set's id is "secondSetOfElements", it would be easier if they simply "SetOfElements", otherwise you would have construct the delimiter string before reading every new set of elements.
This might give you a few ideas:
std::string line;
int line_num = 0;
for (int i = 0; i < 3; ++i)
assert(getline(input, line))); // ignore 3 lines
while (input >> set_name)
{
if (set_name == '#') { input.ignore('\n'); continue; }
std::vector<std::vector<float>>>& set = sets[set_name];
if (input >> rows)
for (int i = 0; i < rows && getline(input, line); ++i)
{
std::istringstream iss(line);
set.push_back(std::vector<float>());
while (iss >> num) set.back().push_back(num);
}
}