Reputation: 3442
I am trying to read in a file line by line, parse it based on spaces and place it into a vector called input. However, I cannot do a cin >> x1 >> x2 >> x3 ... because the line doesn't have a set number of terms. Below is what I was thinking, but it could be wrong.
vector <double> input;
fstream inputFile("../Sphere.in", fstream::in);
inputFile.open("../Sphere.in", fstream::in);
while (inputFile.good())
{
getline(inputFile, line);
then something in here that says for each space in line put in input[i]
}
I am very new at C++ and would appreciate any help that someone could throw my way.
Thanks,
John
Upvotes: 0
Views: 1889
Reputation: 476930
If you just want one flat collection of doubles:
#include <vector>
#include <istream> // for operator>>
#include <fstream> // for std::ifstream
std::vector<double> v;
for (double d; inputFile >> d; ) { v.push_back(d); }
Or simpler:
// includes as above
#include <iterator>
std::vector<double> v((std::istream_iterator<double>(inputFile)),
std::istream_iterator<double>());
If you want a container for each line:
// includes as above
#include <string>
#include <sstream>
std::vector<std::vector<double>> v;
for (std::string line; std::getline(inputFile, line); )
{
std::istringstream iss(line);
v.emplace_back(std::istream_iterator<double>(iss),
std::istream_iterator<double>());
}
In the line-by-line approach, you could also check if you've successfully reached the end of the input string, or whether you were stopped by invalid input and emit a diagnostic. If you want to take error checking to an extreme, you could extract individual strings from the stream and parse them as double
(using std::strtod
) and emit a diagnostic if that fails, skipping the unparsable tokens:
// ...
#include <cstdlib>
for (std::string line; std::getline(inputFile, line); )
{
std::istringstream iss(line);
v.emplace_back();
for (std::string token; iss >> token; )
{
char * e;
double const d = std::strtod(token.c_str(), &e);
if (*e != '\0') { /* error! skip this token */ continue; }
v.back().emplace_back(d);
}
}
Upvotes: 4
Reputation: 55395
while (inputFile.good())
is wrong, as it only evaluates to false after a read fails. Without additional checks inside the loop, the last iteration will work on invalid input. The correct, idiomatic way is to put the read in loop's condition:
while (getline(inputFile, line)) { ... }
This way you only enter the loop if getline succeeds. Now you can construct a string stream from line
and read doubles from there, using similar approach with read inside loop condition:
while (getline(inputFile, line)) {
istringstream iss(line);
double d;
while (iss >> d) input.push_back(d);
}
Upvotes: 2